142 lines
5.0 KiB
Python
142 lines
5.0 KiB
Python
|
# -*- 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()
|