object.py

Go to the documentation of this file.
00001 from silme.core.entity import Entity, EntityList
00002 
00003 
00004 class Blob(object):
00005     uri = None
00006     id = None
00007     source = None
00008 
00009 
00010 class L10nObject(list, Blob):
00011     process_function = None
00012     fallback = None
00013 
00014     def __init__(self, id=None):
00015         """
00016         L10nObject can be initialized with optional argument: id
00017         """
00018         list.__init__(self)
00019         Blob.__init__(self)
00020         self.id = id
00021 
00022     def _get_pos(self, pos):
00023         """
00024         It is an internal method for translating tuple in form of:
00025         ('before', 'entity.id') or ('after', 'entity.id')
00026         which are returned internally by our methods into a solid number.
00027         
00028         If pos is a number it will just be returned as integer.
00029         """
00030         if isinstance(pos, tuple):
00031             p = self.get_entity_pos(pos[1])
00032             return p + 1 if pos[0] == 'after' else p
00033         else:
00034             return int(pos)
00035 
00036     def add_at_pos(self, element, pos=None):
00037         """
00038         adds an element to L10nObject.
00039         pos - if given, allows you to decide where the element will be added
00040            pos may be in form of an integer or a tuple like ('before', 'entity.id'), ('after', 'entity.id')
00041         """
00042         if pos == None:
00043             self.append(element)
00044         else:
00045             self.insert(self._get_pos(pos), element)
00046 
00047     def add_entity(self, entity, pos=None):
00048         """
00049         adds an entity to L10nObject
00050         pos - if given, allows you to decide where the entity will be added
00051         """
00052         self.add_at_pos(entity, pos)
00053         return 1
00054 
00055     def get_value(self, id, fallback=None):
00056         """
00057         returns a value of an entity with given id
00058         fallback - if given overrides default locale fallback (e.g. ['de', 'fr', 'en-US'])
00059         
00060         if given entity does not exist it will raise a KeyError
00061         """
00062         if fallback == None and self.fallback:
00063             fallback = self.fallback
00064         return self.get_entity(id).get_value(fallback)
00065 
00066     def get_locale_codes(self):
00067         """
00068         returns list of locale codes existing in L10nObject
00069         """
00070         locales = []
00071         for entity in self.get_entities():
00072             for key in entity._value.keys():
00073                 if key not in locales:
00074                     locales.append(key)
00075         return locales
00076 
00077     def get_entity_ids(self):
00078         """
00079         returns list of id's of entities in L10nObject
00080         """
00081         return [item.id for item in self if isinstance(item, Entity)]
00082 
00083     def get_entities(self):
00084         """
00085         returns all entities from L10nObject
00086         """
00087         return [item for item in self if isinstance(item, Entity)]
00088 
00089     def has_entity(self, id):
00090         """
00091         returns True if entity with given id exists or False otherwise
00092         """
00093         for item in self:
00094             if isinstance(item, Entity) and item.id == id:
00095                 return True
00096         return False
00097 
00098     def modify_entity(self, id, value, code=None):
00099         """
00100         modifies entity value
00101         code - if given modified the value for given locale code
00102         """
00103         for item in self:
00104             if isinstance(item, Entity) and item.id == id:
00105                 item.set_value(value, code)
00106                 return True
00107         raise KeyError('No such entity')
00108 
00109     def get_entity(self, id):
00110         """
00111         returns an entity for a given id
00112         """
00113         for item in self:
00114             if isinstance(item, Entity) and item.id == id:
00115                 return item
00116         raise KeyError('No such entity')
00117 
00118     def get_entity_pos(self, id):
00119         """
00120         returns position of entity in L10nObject
00121         """
00122         for (i, item) in enumerate(self):
00123             if isinstance(item, Entity) and item.id == id:
00124                 return i
00125         raise KeyError('No such entity')
00126 
00127     def remove_entity(self, id):
00128         """
00129         removes entity for given id or raises KeyError
00130         """
00131         for (num, item) in enumerate(self):
00132             if isinstance(item, Entity) and item.id == id:
00133                 del self[num]
00134                 return True
00135         raise KeyError('No such entity')
00136 
00137     def set_fallback(self, fallback):
00138         self.fallback = fallback
00139 
00140     def add_comment(self, comment, pos=None):
00141         self.add_at_pos(comment, pos)
00142         return 1
00143 
00144     def add_string(self, string, pos=None):
00145         self.add_at_pos(string, pos)
00146         return 1
00147 
00148     def add_element(self, element, pos=None):
00149         """
00150         adds an element (string, entity or comment) to l10nObject
00151         pos - if given addes an element at given position
00152         
00153         returns a number representing how many new elements have been added
00154           Usually one, but if a new string gets added and is concatanated to previous/next one
00155           the value will be 0.
00156         """
00157         if element == None:
00158             return 0
00159         t = type(element).__name__[0]
00160         if t == 's' or t == 'u': # s - str, u - unicode
00161             return self.add_string(element, pos)
00162         elif t == 'E': # E - Entity
00163             return self.add_entity(element, pos)
00164         elif t == 'C': # C - Comment
00165             return self.add_comment(element, pos)
00166         else:
00167             raise Exception('Cannot add element of type "' + type(element).__name__ +
00168                             '" to L10nObject')
00169 
00170     def add_elements(self, sequence, pos=None):
00171         """
00172         adds set of elements
00173         pos - if given addes the elements at given position
00174         
00175         returns a number representing how many new elements have been added
00176           Usually the number will be equal the number of 
00177         """
00178         it = iter(sequence)
00179         tshift = 0
00180         if not pos == None:
00181             pos = self._get_pos(pos)
00182         while True:
00183             try:
00184                 shift = self.add_element(it.next(), pos=(None if pos == None else pos+tshift))
00185                 tshift += shift
00186             except StopIteration:
00187                 break
00188         return tshift
00189 
00190     def remove_element(self, pos):
00191         """
00192         removes an element at given position from the L10nObject
00193         """
00194         del self[pos]
00195 
00196     def get_element(self, position):
00197         return self[position]
00198 
00199     def get_entitylist(self):
00200         """
00201         returns an ElementList representation of the L10nObject
00202         """
00203         entityList = EntityList()
00204         entityList.id = self.id
00205         entityList.fallback = self.fallback
00206         for entity in self.get_entities():
00207             entityList.add_entity(entity)
00208         return entityList
00209 
00210     def process(self):
00211         """
00212         launches a process function on the L10nObject if
00213         processing method is provided
00214         """
00215         return self.process_function(self)
00216 
00217     def get_locales(self, localelist):
00218         """
00219         returns a clone of L10nObject with entities only
00220         in given list of locales
00221         """
00222         l10n_object = L10nObject()
00223         l10n_object.id = self.id
00224         l10n_object.uri = self.uri
00225         l10n_object.fallback = localelist
00226         l10n_object.source = self.source
00227         for element in self:
00228             if isinstance(element, Entity):
00229                 l10n_object.add_entity(element.get_locales(localelist))
00230             else:
00231                 l10n_object.add_element(element)
00232         return l10n_object
00233 
00234     def merge(self, l10n_object):
00235         """
00236         merges L10nObject with another L10nObject (only entities)
00237         """
00238         for entity in l10n_object.get_entities():
00239             if self.has_entity(entity.id):
00240                 self.get_entity(entity.id).merge(entity)
00241             else:
00242                 self.add_entity(entity)
00243         if l10n_object.fallback:
00244             for code in l10n_object.fallback:
00245                 if code not in self.fallback:
00246                     self.fallback.append(code)
00247 
00248 
00249 class Comment(L10nObject):
00250     """
00251     Comment class is a sub-class of L10nObject but cannot
00252     take Comment as an element.
00253     
00254     It means that by default Comments store strings and Entities.
00255     """
00256     def __init__(self, elist=None):
00257         L10nObject.__init__(self)
00258         if elist:
00259             for i in elist:
00260                 self.add_element(i)
00261 
00262     def add_element(self, element, pos=None):
00263         if isinstance(element, Comment):
00264             raise Exception('Cannot add comment to comment')
00265         return L10nObject.add_element(self, element, pos)
00266 
00267 
00268 class L10nPackage(object):
00269     """
00270     L10nPackage is a container object that stores
00271     set of objects (L10nobject or Object) and sub-l10npackages.
00272     
00273     It's easiest to think of it as a filesystem directory that
00274     can store files and nested directories.
00275     It abstracts the package from the file system, so once you load
00276     L10nPackage into memory you can serialize it, send it, save as .zip file or
00277     simply diff.
00278     """
00279     uri = None
00280 
00281     def __init__(self, id=None):
00282         self.objects = {}
00283         self.packages = {}
00284         self.id = id
00285 
00286     def add_object(self, object, path=None):
00287         """
00288         Adds an object to L10nPackage.
00289         
00290         Optional parameter path allows to declare place
00291         inside the package where the object should be added.
00292         
00293         For example l10npack.add_object(l10nobject, 'pkg1/pkg2') is similar to
00294         l10npack.get_package('pkg1').get_package('pkg2').add_object(l10nobject)
00295         with the difference that it will create missing sub packages.
00296         """
00297         if path == None or path == '':
00298             self.objects[object.id] = object
00299         else:
00300             path = path.split('/')
00301             if path[0] in self.packages:
00302                 self.packages[path[0]].add_object(object, '/'.join(path[1:]))
00303             else:
00304                 sub_l10n_pack = L10nPackage()
00305                 sub_l10n_pack.id = path[0]
00306                 self.add_package(sub_l10n_pack)
00307                 sub_l10n_pack.add_object(object, '/'.join(path[1:]))
00308 
00309     def add_package(self, l10npackage, path=None):
00310         """
00311         Adds a package to L10nPackage.
00312         
00313         Optional parameter path allows to declare place
00314         inside the package where the subpackage should be added.
00315         
00316         For example l10npack.add_package(subl10npack, 'pkg1/pkg2') is similar to
00317         l10npack.get_package('pkg1').get_package('pkg2').add_package(subl10npack)
00318         with the difference that it will create missing sub packages.
00319         """
00320         if path == None or path == '':
00321             self.packages[l10npackage.id] = l10npackage
00322         else:
00323             path = path.split('/')
00324             if path[0] in self.packages:
00325                 self.packages[path[0]].add_package(l10npackage, '/'.join(path[1:]))
00326             else:
00327                 sub_l10n_pack = L10nPackage()
00328                 sub_l10n_pack.id = path[0]
00329                 self.packages[path[0]] = sub_l10n_pack
00330                 sub_l10n_pack.add_package(l10npackage,'/'.join(path[1:]))
00331 
00332     def get_packages(self, names=False):
00333         """
00334         Returns a list of packages inside L10nPackage.
00335         If parameter names is set to True list of
00336         names is returned instead of objects.
00337         """
00338         if names == True:
00339             return self.packages.keys()
00340         else:
00341             return self.packages.values()
00342 
00343     def get_objects(self, type='all', names=False):
00344         """
00345         Returns a list of objects inside L10nPackage.
00346         If parameter names is set to True list of
00347         names is returned instead of objects.
00348         """
00349         if type == 'all':
00350             if names == True:
00351                 return self.objects.keys()
00352             else:
00353                 return self.objects.values()
00354         else:
00355             l10n_objects = {}
00356             if type == 'entitylist':
00357                 type = EntityList
00358             elif type == 'l10nobject':
00359                 type = L10nObject
00360             elif type == 'object':
00361                 type = Object
00362             for object in self.objects:
00363                 if isinstance(self.objects[object], type):
00364                     l10n_objects[object] = self.objects[object] 
00365             if names == True:
00366                 return l10n_objects.keys()
00367             else:
00368                 return l10n_objects.values()
00369 
00370     def get_entities(self, recursive=True):
00371         """
00372         Returns a list of all entities inside the L10nPackage
00373         
00374         If optional parameter recursive is set to True it will
00375         return all packages from this package and its subpackages.
00376         """
00377         entities = []
00378         if recursive:
00379             for pack in self.packages.values():
00380                 entities.extend(pack.get_entities())
00381         for i in self.objects:
00382             if isinstance(self.objects[i], L10nObject):
00383                 entities.extend(self.objects[i].get_entities())
00384             elif isinstance(self.objects[i], EntityList):
00385                 entities.extend(self.objects[i].values())
00386         return entities
00387 
00388     def has_object(self, id):
00389         return id in self.objects
00390 
00391     def has_package(self, id):
00392         return id in self.packages
00393 
00394     def get_object(self, id):
00395         if id in self.objects:
00396             return self.objects[id]
00397         raise KeyError('No such object')
00398         
00399     def get_package(self, id):
00400         if id in self.packages:
00401             return self.packages[id]
00402         raise KeyError('No such package')
00403 
00404     def get_element(self, path):
00405         """
00406         Returns an element from inside L10nPackage
00407         by its path.
00408         
00409         l10npack.get_element('pkg1/pkg2/object.po') will return
00410         the same as
00411         l10npack.get_package('pkg1').get_package('pkg2').get_object('object.po')
00412         
00413         IF the path is empty the result will be None
00414         """
00415         if not path:
00416             return None
00417         elems = path.split('/')
00418         if len(elems) == 0:
00419             return None
00420 
00421         if len(elems) == 2 and elems[1] == '':
00422             elems = elems[:-1]
00423 
00424         if len(elems) == 1:
00425             if self.has_package(elems[0]):
00426                 elem = self.get_package(elems[0])
00427             elif self.has_object(elems[0]):
00428                 elem = self.get_object(elems[0])
00429             else:
00430                 return None
00431             return elem
00432         else:
00433             if self.packages.has_key(elems[0]):
00434                 return self.packages[elems[0]].get_element('/'.join(elems[1:]))
00435             else:
00436                 return None
00437 
00438     def remove_object(self, id):
00439         del self.objects[id]
00440         
00441     def remove_package(self, id):
00442         del self.packages[id]
00443 
00444     def get_value(self, path, entity):
00445         elem = self.get_element(path)
00446         return elem.get_value(entity)
00447 
00448     def merge(self, l10n_package):
00449         for id in l10n_package.objects:
00450             object2 = l10n_package.get_object(id)
00451             if self.has_object(id):
00452                 object = self.get_object(id)
00453                 if type(object) is not type(object2):
00454                     raise Exception('Object type mismatch! (' + id + ': ' +
00455                                     type(object) + ',' + type(object2) + ')')
00456                 elif not isinstance(object, EntityList):
00457                     self.add_object(object2)
00458                 else:
00459                     object.merge(object2)
00460             else:
00461                 self.add_object(object2)
00462         for id in l10n_package.packages:
00463             package = l10n_package.get_package(id)
00464             if self.has_package(id):
00465                 self.get_package(id).merge(package)
00466             else:
00467                 self.add_package(package)
00468 
00469     def get_locales(self, localelist):
00470         l10n_package = L10nPackage()
00471         l10n_package.id = self.id
00472         l10n_package.uri = self.uri
00473         for object in self.objects.values():
00474             l10n_package.add_object(object.get_locales(localelist))
00475         for package in self.packages.values():
00476             l10nPackage.add_package(package.get_locales(localelist))
00477         return l10n_package

Generated on Tue May 12 17:37:27 2009 for silme by  doxygen 1.5.8