nutools/lib/nulib/python/nulib/files.py

142 lines
5.0 KiB
Python
Raw Normal View History

2018-04-26 23:19:17 +04:00
# -*- coding: utf-8 -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
"""Gestion de fichiers de formats spécifiques.
Pour le moment, seuls les fichiers textes sont supportés.
"""
__all__ = ('TextFile', )
from os import path
from .base import isstr, make_prop
from .uio import _s
from .lines import Lines
_marker = []
class TextFile(object):
"""Un fichier texte, accéder et modifié comme un ensemble de lignes.
L'objet qui gère les lignes de ce fichier texte sont disponibles avec la
propriété lines
Lors de la lecture du contenu du fichier sur disque, on détermine la
convention de fin de lignes utilisée, et on la reproduit lors de l'écriture
sur disque.
"""
_file, file = make_prop('_file')[:2]
_absfile, absfile = make_prop('_absfile')[:2]
_absfiledir, absfiledir = make_prop('_absfiledir')[:2]
_absfilename, absfilename = make_prop('_absfilename')[:2]
_inf, inf = make_prop('_inf')[:2]
_lines, lines = make_prop('_lines')[:2]
def __init__(self, file=None, raise_exception=True, readlines=True, lines=None):
super(TextFile, self).__init__()
if lines is not None: self._lines = lines
if file is not None: self.open(file, raise_exception, readlines)
def _new_Lines(self):
"""Retourner une nouvelle instance de BLines pour la lecture des lignes
du fichier.
Par défaut, retourner une instance de Lines, permettant de lire des
lignes en unicode. Il faut surcharger cette méthode et retourner
BLines() si l'on veut lire des lignes non unicode. Une alternative est
de passer une instance de BLines() au constructeur.
"""
return Lines()
def open(self, file, raise_exception=True, readlines=True, lines=None):
"""Spécifier un nouveau fichier à charger, et charger ses lignes
"""
# reset des valeurs
self._file = None
self._absfile = None
self._absfiledir = None
self._absfilename = None
self._inf = None
if lines is not None: self._lines = lines
if self._lines is None: self._lines = self._new_Lines()
# ouvrir le fichier
if isstr(file):
self._file = file
self._absfile = path.abspath(self._file)
self._absfiledir, self._absfilename = path.split(self._absfile)
else:
self._inf = file
if readlines: return self.readlines(raise_exception)
else: return None
def close(self):
if self._inf is not None:
self._inf.close()
self._inf = None
def readlines(self, raise_exception=True, close=True, uio=None):
"""Lire les lignes du fichier.
@return: self.lines
"""
if self._inf is None:
if self._absfile is None:
raise ValueError("Should open() the file before reading")
try:
self._inf = open(self._absfile, 'rb')
except IOError:
if raise_exception: raise
if self._inf is None :
self._lines.reset()
else:
try:
self._lines.readlines(self._inf, raise_exception=raise_exception, uio=uio)
finally:
if close: self.close()
return self._lines
def writelines(self, lines=None, outf=None, raise_exception=True, close=True, uio=None):
"""Ecrire les lignes self.lines dans le fichier.
si lines!=None, il s'agit du nouvel ensemble de lignes.
@return: True si l'écriture a pu se faire, False sinon.
@rtype: bool
"""
if lines is not None: self._lines[:] = lines
if outf is None:
if self._absfile is None: raise ValueError("outf is missing or open() the file before writing")
outf = self._absfile
if isstr(outf):
try:
outf = open(self._absfile, 'wb')
close = True
except IOError:
if raise_exception: raise
return False
try:
try:
self._lines.writelines(outf, uio=uio)
return True
except IOError:
if raise_exception: raise
return False
finally:
if close: outf.close()
def is_valid(self): return self._lines.is_valid()
valid = property(is_valid)
def get_nl(self): return self._lines.get_nl()
def set_nl(self, nl): self._lines.set_nl(nl)
nl = property(get_nl, set_nl)
def reset(self): self._lines.reset()
def grepi(self, pattern, indexes=None, inverse=False): return self._lines.grepi(pattern, indexes, inverse)
def grep(self, pattern, indexes=None, inverse=False): return self._lines.grep(pattern, indexes, inverse)
def replace(self, pattern, repl, count=0, indexes=None): return self._lines.replace(pattern, repl, count, indexes)
def map(self, func, copy=False, **args): return self._lines.map(func, copy, **args)
def filter(self, func, copy=False, **args): return self._lines.filter(func, copy, **args)
def join(self): return self._lines.join()