MoinSupport

ItemSupport.py

48:816ebc7dcb6a
2013-04-30 Paul Boddie Removed confusing version information.
     1 # -*- coding: iso-8859-1 -*-     2 """     3     MoinMoin - ItemSupport library     4      5     @copyright: 2013 by Paul Boddie <paul@boddie.org.uk>     6     @license: GNU GPL (v2 or later), see COPYING.txt for details.     7 """     8      9 from MoinMoin.util import lock    10 import os    11     12 # Content storage support.    13     14 class ItemDirectoryStore:    15     16     "A directory-based item store."    17     18     def __init__(self, path, lock_dir):    19     20         "Initialise an item store for the given 'path' and 'lock_dir'."    21     22         self.path = path    23         self.next_path = os.path.join(self.path, "next")    24         self.lock_dir = lock_dir    25         self.writelock = lock.WriteLock(lock_dir)    26         self.readlock = lock.ReadLock(lock_dir)    27     28     def mtime(self):    29     30         "Return the last modified time of the item store directory."    31     32         return os.path.getmtime(self.path)    33     34     def get_next(self):    35     36         "Return the next item number."    37     38         next = self.read_next()    39         if next is None:    40             next = self.deduce_next()    41             self.write_next(next)    42         return next    43     44     def deduce_next(self):    45     46         "Deduce the next item number from the existing item files."    47     48         return max([int(filename) for filename in os.listdir(self.path) if filename.isdigit()] or [-1]) + 1    49     50     def read_next(self):    51     52         "Read the next item number from a special file."    53     54         if not os.path.exists(self.next_path):    55             return None    56     57         f = open(self.next_path)    58         try:    59             try:    60                 return int(f.read())    61             except ValueError:    62                 return None    63         finally:    64             f.close()    65     66     def write_next(self, next):    67     68         "Write the 'next' item number to a special file."    69     70         f = open(self.next_path, "w")    71         try:    72             f.write(str(next))    73         finally:    74             f.close()    75     76     def write_item(self, item, next):    77     78         "Write the given 'item' to a file with the given 'next' item number."    79     80         f = open(self.get_item_path(next), "w")    81         try:    82             f.write(item)    83         finally:    84             f.close()    85     86     def read_item(self, number):    87     88         "Read the item with the given item 'number'."    89     90         f = open(self.get_item_path(number))    91         try:    92             return f.read()    93         finally:    94             f.close()    95     96     def get_item_path(self, number):    97     98         "Get the path for the given item 'number'."    99    100         path = os.path.abspath(os.path.join(self.path, str(number)))   101         basepath = os.path.join(self.path, "")   102    103         if os.path.commonprefix([path, basepath]) != basepath:   104             raise OSError, path   105    106         return path   107    108     # High-level methods.   109    110     def append(self, item):   111    112         "Append the given 'item' to the store."   113    114         self.writelock.acquire()   115         try:   116             next = self.get_next()   117             self.write_item(item, next)   118             self.write_next(next + 1)   119         finally:   120             self.writelock.release()   121    122     def __len__(self):   123    124         """   125         Return the number of the next item (which should also be the number of   126         items).   127         """   128    129         self.writelock.acquire()   130         try:   131             return self.get_next()   132         finally:   133             self.writelock.release()   134    135     def __iter__(self):   136    137         "Return an iterator over the items in the store."   138    139         return ItemIterator(self)   140    141     def __getitem__(self, number):   142    143         "Return the item with the given 'number'."   144    145         self.readlock.acquire()   146         try:   147             try:   148                 return self.read_item(number)   149             except (IOError, OSError):   150                 raise IndexError, number   151         finally:   152             self.readlock.release()   153    154 class ItemIterator:   155    156     "An iterator over items in a store."   157    158     def __init__(self, store, direction=1):   159         self.store = store   160         self.direction = direction   161         self.reset()   162    163     def reset(self):   164         if self.direction == 1:   165             self._next = 0   166             self.final = len(self.store)   167         else:   168             self._next = len(self.store) - 1   169             self.final = 0   170    171     def more(self):   172         if self.direction == 1:   173             return self._next < self.final   174         else:   175             return self._next >= self.final   176    177     def get_next(self):   178         next = self._next   179         self._next += self.direction   180         return next   181    182     def next(self):   183         while self.more():   184             try:   185                 return self.store[self.get_next()]   186             except IndexError:   187                 pass   188    189         raise StopIteration   190    191     def reverse(self):   192         self.direction = -self.direction   193         self.reset()   194    195     def reversed(self):   196         self.reverse()   197         return self   198    199     def __iter__(self):   200         return self   201    202 # vim: tabstop=4 expandtab shiftwidth=4