Source code for datafile.datafile

# -*- coding: utf-8 -*-
# datafile/datafile.py

from builtins import str
from builtins import object
import os.path
from abc import ABCMeta, abstractmethod, abstractproperty
from numpy import ndarray as np_ndarray
from utils.error import FileError
from utils.lastpath import LastPath
from utils import classproperty
from future.utils import with_metaclass

[docs]class DataFile(with_metaclass(ABCMeta, object)): """ Base class for handling data files. Can be initialized with a file (name) to read or with a data array. Test error behaviour >>> from utils import DataFile, getTempFileName, getTempFile, FileNotFound >>> fn = getTempFileName() >>> try: DataFile.checkFilename(fn) ... except FileNotFound, e: str(e).find(fn) > 0 True Prepare test data file >>> fd = getTempFile() >>> l = ['123 234\\n', '1,23 43.4\\r\\n', '2.3; 34,4\\n', ... '21.2 42 2\\n', '23,2 3.4 \\n'] >>> fd.writelines(l) >>> fd.close() Test data parsing >>> df = DataFile() >>> df.loadFile(fd.name) [('123', '234'), ('1.23', '43.4'), ('2.3', '34.4'), ('21.2', '42', '2'), ('23.2', '3.4')] Remove test data finally >>> import os >>> if os.path.isfile(fd.name): ... os.remove(fd.name) """ _filename = None @abstractproperty @classproperty @classmethod def fileFilter(cls): """Extensions of this file type. No extension by default. Use it to construct a proper file name. Reimplement in subclasses. """ raise NotImplementedError @classproperty @classmethod
[docs] def extensions(cls): return (e for t, e in cls.fileFilter)
@property def filename(self): """Absolute path name of this file.""" return self._filename
[docs] def setFilename(self, filename): """Checks provided filename for plausibility and updates LastPath""" self._filename = self.sanitizeReadFilename(filename) LastPath.set(self.filename)
@staticmethod
[docs] def sanitizeReadFilename(filename): """Checks provided filename for plausibility and updates LastPath.""" filename = os.path.abspath(str(filename)) if not os.path.isfile(filename): raise FileError("Given file does not exist!", filename) return filename
@property def name(self): """The plain name of the file with path and extension stripped.""" return os.path.basename(os.path.splitext(self.filename)[0]) # helpers for reading @abstractmethod
[docs] def readFile(self, **kwargs): """Gets a proper file name and returns file data. May modify the instance. To be reimplemented.""" raise NotImplementedError
@abstractmethod
[docs] def getDataObj(self): """Creates and returns the appropriate DataObj instance for this file type.""" raise NotImplementedError
def __init__(self, filename, **kwargs): self.setFilename(filename) self.readFile(**kwargs) # helpers for writing @classmethod
[docs] def sanitizeWriteFilename(cls, filename): """Checks and sets the file name to write to.""" if len(cls.extensions) > 0: dummy, ex = cls.extensions[0] if filename[-len(ex):] != ex: filename = "{0}.{1}".format(filename, ex) filename = os.path.abspath(str(filename)) dirname = os.path.dirname(filename) if not os.path.isdir(dirname): raise FileError("Directory does not exist:", dirname) return filename
@classmethod
[docs] def writeData(cls, filename, data, **kwargs): """Convenience method to write data directly to file.""" self = cls(data, **kwargs) self.write(filename, **kwargs)
[docs] def write(self, filename, **kwargs): filename = self.sanitizeWriteFilename(filename) self.writeFile(filename, self.data, **kwargs) self.setFilename(filename)
@classmethod @abstractmethod
[docs] def writeFile(cls, filename, data, **kwargs): """Gets a proper file name and numpy array and writes it to file. Reimplement this.""" raise NotImplementedError
# vim: set ts=4 sts=4 sw=4 tw=0: