103 lines
2.1 KiB
Python
103 lines
2.1 KiB
Python
#! /usr/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
|