#! /bin/env python3 # encoding: utf-8 import os from .aux import _print from .text import prefix # -------------------------------------------------- class File: ''' A binary r/w file container that abstracts file descriptors away. You just read and write data. Nonexistent files will be created, including any directories if necessary. ''' def __init__(self, path, encoding=None): ''' encoding which encoding to use when opening files; None means binary (raw) ''' self.encoding = encoding if path[0] == '~': self.path = os.path.join(os.getenv('HOME'), path[2:]) else: self.path = path if not os.path.isfile(self.path): if os.path.exists(self.path): _print('path §y%s§/ exists but §ris not a file§/' %(self.path), prefix.fail) raise RuntimeError else: dirname = os.path.dirname(self.path) if dirname and not os.path.isdir(dirname): _print('creating directory §B%s§/' %(dirname)) os.makedirs(dirname) # create the file touch(self.path) @property def data(self): ''' Reads the file and returns the contents. ''' if self.encoding: fd = open(self.path, encoding=self.encoding) else: fd = open(self.path, 'rb') data = fd.read() fd.close() return data @data.setter def data(self, data): ''' Writes data into the file. ''' if self.encoding: fd = open(self.path, 'w', encoding=self.encoding) else: fd = open(self.path, 'wb') fd.write(data) fd.close() def __repr__(self): return 'over.core.File(%s %s)' %(self.path, self.encoding if self.encoding else 'raw') # -------------------------------------------------- def touch(fname, times=None): ''' Sets a filename's atime and mtime. times is a tuple of (atime, mtime) and defaults to 'now'. ''' with open(fname, 'a'): os.utime(fname, times) # -------------------------------------------------- def count_lines(filename): ''' A reasonably fast and memory-lean line counter. ''' lines = 0 buffer = bytearray(2048) with open(filename, 'rb') as f: while f.readinto(buffer): lines += buffer.count(b'\n') return lines