123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- from __future__ import unicode_literals
- from abc import ABCMeta, abstractmethod
- from six import with_metaclass
- import datetime
- import os
- __all__ = (
- 'FileHistory',
- 'History',
- 'InMemoryHistory',
- )
- class History(with_metaclass(ABCMeta, object)):
- """
- Base ``History`` interface.
- """
- @abstractmethod
- def append(self, string):
- " Append string to history. "
- @abstractmethod
- def __getitem__(self, key):
- " Return one item of the history. It should be accessible like a `list`. "
- @abstractmethod
- def __iter__(self):
- " Iterate through all the items of the history. Cronologically. "
- @abstractmethod
- def __len__(self):
- " Return the length of the history. "
- def __bool__(self):
- """
- Never evaluate to False, even when the history is empty.
- (Python calls __len__ if __bool__ is not implemented.)
- This is mainly to allow lazy evaluation::
- x = history or InMemoryHistory()
- """
- return True
- __nonzero__ = __bool__ # For Python 2.
- class InMemoryHistory(History):
- """
- :class:`.History` class that keeps a list of all strings in memory.
- """
- def __init__(self):
- self.strings = []
- def append(self, string):
- self.strings.append(string)
- def __getitem__(self, key):
- return self.strings[key]
- def __iter__(self):
- return iter(self.strings)
- def __len__(self):
- return len(self.strings)
- class FileHistory(History):
- """
- :class:`.History` class that stores all strings in a file.
- """
- def __init__(self, filename):
- self.strings = []
- self.filename = filename
- self._load()
- def _load(self):
- lines = []
- def add():
- if lines:
- # Join and drop trailing newline.
- string = ''.join(lines)[:-1]
- self.strings.append(string)
- if os.path.exists(self.filename):
- with open(self.filename, 'rb') as f:
- for line in f:
- line = line.decode('utf-8')
- if line.startswith('+'):
- lines.append(line[1:])
- else:
- add()
- lines = []
- add()
- def append(self, string):
- self.strings.append(string)
- # Save to file.
- with open(self.filename, 'ab') as f:
- def write(t):
- f.write(t.encode('utf-8'))
- write('\n# %s\n' % datetime.datetime.now())
- for line in string.split('\n'):
- write('+%s\n' % line)
- def __getitem__(self, key):
- return self.strings[key]
- def __iter__(self):
- return iter(self.strings)
- def __len__(self):
- return len(self.strings)
|