def save(self, name=None): """Save the Package in the specified file. We expect that the name is a unicode string. """ if name is None: name=self.__uri name = uri2path(name) # handle .azp files. if name.lower().endswith('.azp') or name.endswith('/'): # AZP format if self.__zip is None: # Conversion necessary: we are saving to the new format. z=ZipPackage() z.new() self.__zip = z # Save the content.xml (using binary mode since serialize is handling encoding) stream = open (self.__zip.getContentsFile(), "wb") self.serialize(stream) stream.close () # Generate the statistics self.__zip.update_statistics(self) # Save the whole .azp self.__zip.save(name) else: # Assuming plain XML format stream = open (name, "wb") self.serialize(stream) stream.close ()
def save(self, name=None): """Save the Package in the specified file""" if name is None: name=self.__uri if name.startswith('file:///'): name = name[7:] if re.match('|/', name): # Windows drive: notation. Convert it from # a more URI-compatible syntax name=urllib.url2pathname(name) # handle .azp files. if name.lower().endswith('.azp') or name.endswith('/'): # AZP format if self.__zip is None: # Conversion necessary: we are saving to the new format. z=ZipPackage() z.new() self.__zip = z # Save the content.xml stream = open (self.__zip.getContentsFile(), "w") self.serialize(stream) stream.close () # Generate the statistics self.__zip.update_statistics(self) # Save the whole .azp self.__zip.save(name) else: # Assuming plain XML format stream = open (name, "w") self.serialize(stream) stream.close ()
def save(self, name=None): """Save the Package in the specified file""" if name is None: name = self.__uri if name.startswith('file:///'): name = name[7:] if re.match('|/', name): # Windows drive: notation. Convert it from # a more URI-compatible syntax name = urllib.url2pathname(name) # handle .azp files. if name.lower().endswith('.azp') or name.endswith('/'): # AZP format if self.__zip is None: # Conversion necessary: we are saving to the new format. z = ZipPackage() z.new() self.__zip = z # Save the content.xml stream = open(self.__zip.getContentsFile(), "w") self.serialize(stream) stream.close() # Generate the statistics self.__zip.update_statistics(self) # Save the whole .azp self.__zip.save(name) else: # Assuming plain XML format stream = open(name, "w") self.serialize(stream) stream.close()
def __init__(self, uri, source=_get_from_uri, importer=None): """Calling the constructor with just a URI tries to read the package from this URI. This can be overidden by providing explicitly the source parameter (a URL or a stream). Providing None for the source parameter creates a new Package. """ self.meta_cache={} if isinstance(uri, unicode): uri=uri.encode(sys.getfilesystemencoding()) if re.match('[a-zA-Z]:', uri): # Windows drive: notation. Convert it to # a more URI-compatible syntax uri=urllib.pathname2url(uri) self.__uri = uri self.__importer = importer # Possible container self.__zip = None abs_uri = self.getUri (absolute=True) if importer: importer.__pkg_cache[abs_uri] = self self.__pkg_cache = importer.__pkg_cache else: self.__pkg_cache = {abs_uri:self} element = None if source is None: element = self._make_model() else: reader = PyExpat.Reader() if source is _get_from_uri: # Determine the package format (plain XML or AZP) # FIXME: should be done by content rather than extension if abs_uri.lower().endswith('.azp') or abs_uri.endswith('/'): # Advene Zip Package. Do some magic. self.__zip = ZipPackage(abs_uri) f=urllib.pathname2url(self.__zip.getContentsFile()) element = reader.fromUri("file://" + f).documentElement else: element = reader.fromUri(abs_uri).documentElement elif hasattr(source, 'read'): element = reader.fromStream(source).documentElement else: if re.match('[a-zA-Z]:', source): # Windows drive: notation. Convert it to # a more URI-compatible syntax source=urllib.pathname2url(source) source_uri = util.uri.urljoin ( 'file:%s/' % urllib.pathname2url (os.getcwd ()), str(source) ) if source_uri.lower().endswith('.azp') or source_uri.endswith('/'): # Advene Zip Package. Do some magic. self.__zip = ZipPackage(source_uri) f=urllib.pathname2url(self.__zip.getContentsFile()) element = reader.fromUri("file://" + f).documentElement else: element = reader.fromUri(source_uri).documentElement modeled.Modeled.__init__(self, element, None) self.__imports = None self.__annotations = None self.__queries = None self.__relations = None self.__schemas = None self.__views = None
class Package(modeled.Modeled, viewable.Viewable.withClass('package'), _impl.Authored, _impl.Dated, _impl.Titled, annotation.AnnotationFactory, annotation.RelationFactory, schema.SchemaFactory, query.QueryFactory, view.ViewFactory, ): """A package is the container of all the elements of an annotation (schemas, types, annotations, relations, views, queries). It provides factory methods to create attached annotations, views, ...""" __metaclass__ = auto_properties def __init__(self, uri, source=_get_from_uri, importer=None): """Calling the constructor with just a URI tries to read the package from this URI. This can be overidden by providing explicitly the source parameter (a URL or a stream). Providing None for the source parameter creates a new Package. """ self.meta_cache={} if isinstance(uri, unicode): uri=uri.encode(sys.getfilesystemencoding()) if re.match('[a-zA-Z]:', uri): # Windows drive: notation. Convert it to # a more URI-compatible syntax uri=urllib.pathname2url(uri) self.__uri = uri self.__importer = importer # Possible container self.__zip = None abs_uri = self.getUri (absolute=True) if importer: importer.__pkg_cache[abs_uri] = self self.__pkg_cache = importer.__pkg_cache else: self.__pkg_cache = {abs_uri:self} element = None if source is None: element = self._make_model() else: reader = PyExpat.Reader() if source is _get_from_uri: # Determine the package format (plain XML or AZP) # FIXME: should be done by content rather than extension if abs_uri.lower().endswith('.azp') or abs_uri.endswith('/'): # Advene Zip Package. Do some magic. self.__zip = ZipPackage(abs_uri) f=urllib.pathname2url(self.__zip.getContentsFile()) element = reader.fromUri("file://" + f).documentElement else: element = reader.fromUri(abs_uri).documentElement elif hasattr(source, 'read'): element = reader.fromStream(source).documentElement else: if re.match('[a-zA-Z]:', source): # Windows drive: notation. Convert it to # a more URI-compatible syntax source=urllib.pathname2url(source) source_uri = util.uri.urljoin ( 'file:%s/' % urllib.pathname2url (os.getcwd ()), str(source) ) if source_uri.lower().endswith('.azp') or source_uri.endswith('/'): # Advene Zip Package. Do some magic. self.__zip = ZipPackage(source_uri) f=urllib.pathname2url(self.__zip.getContentsFile()) element = reader.fromUri("file://" + f).documentElement else: element = reader.fromUri(source_uri).documentElement modeled.Modeled.__init__(self, element, None) self.__imports = None self.__annotations = None self.__queries = None self.__relations = None self.__schemas = None self.__views = None def close(self): if self.__zip: self.__zip.close() return def __str__(self): """Return a nice string representation of the object.""" return "Package (%s)" % self.__uri def _make_model(self): """Build a new empty annotation model""" di = xml.dom.getDOMImplementation() doc = di.createDocument(adveneNS, "package", None) elt = doc.documentElement elt.setAttributeNS(xmlNS, "xml:base", unicode(self.__uri)) elt.setAttributeNS(xmlnsNS, "xmlns", adveneNS) elt.setAttributeNS(xmlnsNS, "xmlns:xlink", xlinkNS) elt.setAttributeNS(xmlnsNS, "xmlns:dc", dcNS) elt.setAttributeNS(dcNS, "dc:creator", "") elt.appendChild(doc.createElementNS(adveneNS, "imports")) elt.appendChild(doc.createElementNS(adveneNS, "annotations")) elt.appendChild(doc.createElementNS(adveneNS, "queries")) elt.appendChild(doc.createElementNS(adveneNS, "schemas")) elt.appendChild(doc.createElementNS(adveneNS, "views")) return elt def _get_cached(self, uri): """Return a cached version of the package designated by "uri" """ return self.__pkg_cache.get(uri, None) def getOwnerPackage(self): """Return this package. Used for breaking recursivity in the parenthood tree.""" return self def getAccessPath(self): if self.__importer: r = list(self.__importer.getAccessPath()) r.append(self) return tuple(r) else: return (self,) def getRootPackage(self): if self.__importer: return self.__importer.getRootPackage() else: return self def getUri(self, absolute=True, context=None): """ Return the URI of the package. Parameter if _absolute_ is _True_, the URI will be forced absolute. If not, and if _context_ is _None_, the URI will be resolved with respect to the root package URI, whatever its stored form (absolute or relative). If context is given and is a (direct or indirect) importer package, the URI will be resolved with respect to the context URI, whatever its stored form (absolute or relative). You would probably rather use the uri read-only property, unless you want to set the parameter _absolute_. """ uri = self.__uri if not absolute and context is self: return '' importer = self.__importer if importer is not None: uri = util.uri.urljoin (importer.getUri (absolute, context), uri) if absolute: base_uri = 'file:%s/' % urllib.pathname2url (os.getcwd ()) uri = util.uri.urljoin(base_uri, uri) return uri def getImports (self): """Return a collection of this package's imports""" if self.__imports is None: e = self._getChild ( (adveneNS, "imports") ) self.__imports = InverseDictBundle (self, e, Import, Import.getAlias) return self.__imports def getAnnotations(self): """Return a collection of this package's annotations""" if self.__annotations is None: e = self._getChild((adveneNS, "annotations")) self.__annotations = StandardXmlBundle(self, e, annotation.Annotation) return self.__annotations def getRelations(self): """Return a collection of this package's relations""" if self.__relations is None: e = self._getChild((adveneNS, "annotations")) # yes, "annotations"! #relations are under the same element as annotations # FIXME: is this always the case ? self.__relations = StandardXmlBundle(self, e, annotation.Relation) return self.__relations def getSchemas(self): """Return a collection of this package's schemas""" if self.__schemas is None: e = self._getChild((adveneNS, "schemas")) self.__schemas = ImportBundle(self, e, schema.Schema) return self.__schemas def getViews(self): """Return a collection of this package's view""" if self.__views is None: e = self._getChild((adveneNS, "views")) self.__views = ImportBundle(self, e, view.View) return self.__views def getQueries(self): """Return a collection of this package's queries""" if self.__queries is None: e = self._getChild((adveneNS, "queries")) self.__queries = ImportBundle(self, e, query.Query) return self.__queries def getAnnotationTypes (self): """Return a collection of this package's annotation types""" r = SumBundle () for s in self.getSchemas (): r += s.getAnnotationTypes () return r def getRelationTypes(self): """Return a collection of this package's relation types""" r = SumBundle () for s in self.getSchemas (): r += s.getRelationTypes () return r def getResources(self): if self.__zip is None: return None else: return self.__zip.getResources(package=self) def get_element_by_id(self, i): if not i: return None uri=self.uri for m in (self.getSchemas, self.getViews, self.getAnnotationTypes, self.getRelationTypes, self.getAnnotations, self.getQueries, self.getRelations): el=m().get( '#'.join( (uri, i) ), None ) if el is not None: return el return None def generate_statistics(self): """Generate the statistics.xml file. """ out=u"""<?xml version="1.0" encoding="UTF-8"?> <statistics:statistics xmlns:statistics="urn:advene:names:tc:opendocument:xmlns:manifest:1.0"> """ # Note: we do not use urllib.quote, since it chokes on non-ASCII characters (unicode) out += u"""<statistics:title value="%s" />""" % ((self.title or '').replace('"', '%22') or "") out += u"""<statistics:description value="%s" />""" % ((self.getMetaData(config.data.namespace_prefix['dc'], 'description') or "").replace('"', '%22') or "") for n, l in ( ('schema', len(self.schemas)), ('annotation', len(self.annotations)), ('annotation_type', len(self.annotationTypes)), ('relation', len(self.relations)), ('relation_type', len(self.relationTypes)), ('query', len(self.queries)), ('view', len(self.views)) ): out += u"""<statistics:item name="%s" value="%d" />""" % (n, l) out += u"""</statistics:statistics>""" return out def serialize(self, stream=sys.stdout): """Serialize the Package on the specified stream""" stream.write(self._getModel().toxml(encoding='utf8')) def save(self, name=None): """Save the Package in the specified file""" if name is None: name=self.__uri if name.startswith('file:///'): name = name[7:] if re.match('|/', name): # Windows drive: notation. Convert it from # a more URI-compatible syntax name=urllib.url2pathname(name) # handle .azp files. if name.lower().endswith('.azp') or name.endswith('/'): # AZP format if self.__zip is None: # Conversion necessary: we are saving to the new format. z=ZipPackage() z.new() self.__zip = z # Save the content.xml stream = open (self.__zip.getContentsFile(), "w") self.serialize(stream) stream.close () # Generate the statistics self.__zip.update_statistics(self) # Save the whole .azp self.__zip.save(name) else: # Assuming plain XML format stream = open (name, "w") self.serialize(stream) stream.close () def _recursive_save (self): """Save recursively this packages with all its imported packages""" self.save () for i in self.getImports (): i.getPackage ()._recursive_save () def getQnamePrefix (self, item): if self == item: return None if isinstance (item, Package): try: i=self.getImports()[item.uri] return i.getAlias() except KeyError: raise AdveneException ("item %s has no QName prefix in %s" % (item, self)) else: return self.getQnamePrefix(item._getParent())
def __init__(self, uri, source=_get_from_uri, importer=None): """Calling the constructor with just a URI tries to read the package from this URI. This can be overidden by providing explicitly the source parameter (a URL or a stream). Providing None for the source parameter creates a new Package. """ self.meta_cache = {} if isinstance(uri, unicode): uri = uri.encode(sys.getfilesystemencoding()) if re.match('[a-zA-Z]:', uri): # Windows drive: notation. Convert it to # a more URI-compatible syntax uri = urllib.pathname2url(uri) self.__uri = uri self.__importer = importer # Possible container self.__zip = None abs_uri = self.getUri(absolute=True) if importer: importer.__pkg_cache[abs_uri] = self self.__pkg_cache = importer.__pkg_cache else: self.__pkg_cache = {abs_uri: self} element = None if source is None: element = self._make_model() else: reader = PyExpat.Reader() if source is _get_from_uri: # Determine the package format (plain XML or AZP) # FIXME: should be done by content rather than extension if abs_uri.lower().endswith('.azp') or abs_uri.endswith('/'): # Advene Zip Package. Do some magic. self.__zip = ZipPackage(abs_uri) f = urllib.pathname2url(self.__zip.getContentsFile()) element = reader.fromUri("file://" + f).documentElement else: element = reader.fromUri(abs_uri).documentElement elif hasattr(source, 'read'): element = reader.fromStream(source).documentElement else: if re.match('[a-zA-Z]:', source): # Windows drive: notation. Convert it to # a more URI-compatible syntax source = urllib.pathname2url(source) source_uri = util.uri.urljoin( 'file:%s/' % urllib.pathname2url(os.getcwd()), str(source)) if source_uri.lower().endswith('.azp') or source_uri.endswith( '/'): # Advene Zip Package. Do some magic. self.__zip = ZipPackage(source_uri) f = urllib.pathname2url(self.__zip.getContentsFile()) element = reader.fromUri("file://" + f).documentElement else: element = reader.fromUri(source_uri).documentElement modeled.Modeled.__init__(self, element, None) self.__imports = None self.__annotations = None self.__queries = None self.__relations = None self.__schemas = None self.__views = None
class Package( modeled.Modeled, viewable.Viewable.withClass('package'), _impl.Authored, _impl.Dated, _impl.Titled, annotation.AnnotationFactory, annotation.RelationFactory, schema.SchemaFactory, query.QueryFactory, view.ViewFactory, ): """A package is the container of all the elements of an annotation (schemas, types, annotations, relations, views, queries). It provides factory methods to create attached annotations, views, ...""" __metaclass__ = auto_properties def __init__(self, uri, source=_get_from_uri, importer=None): """Calling the constructor with just a URI tries to read the package from this URI. This can be overidden by providing explicitly the source parameter (a URL or a stream). Providing None for the source parameter creates a new Package. """ self.meta_cache = {} if isinstance(uri, unicode): uri = uri.encode(sys.getfilesystemencoding()) if re.match('[a-zA-Z]:', uri): # Windows drive: notation. Convert it to # a more URI-compatible syntax uri = urllib.pathname2url(uri) self.__uri = uri self.__importer = importer # Possible container self.__zip = None abs_uri = self.getUri(absolute=True) if importer: importer.__pkg_cache[abs_uri] = self self.__pkg_cache = importer.__pkg_cache else: self.__pkg_cache = {abs_uri: self} element = None if source is None: element = self._make_model() else: reader = PyExpat.Reader() if source is _get_from_uri: # Determine the package format (plain XML or AZP) # FIXME: should be done by content rather than extension if abs_uri.lower().endswith('.azp') or abs_uri.endswith('/'): # Advene Zip Package. Do some magic. self.__zip = ZipPackage(abs_uri) f = urllib.pathname2url(self.__zip.getContentsFile()) element = reader.fromUri("file://" + f).documentElement else: element = reader.fromUri(abs_uri).documentElement elif hasattr(source, 'read'): element = reader.fromStream(source).documentElement else: if re.match('[a-zA-Z]:', source): # Windows drive: notation. Convert it to # a more URI-compatible syntax source = urllib.pathname2url(source) source_uri = util.uri.urljoin( 'file:%s/' % urllib.pathname2url(os.getcwd()), str(source)) if source_uri.lower().endswith('.azp') or source_uri.endswith( '/'): # Advene Zip Package. Do some magic. self.__zip = ZipPackage(source_uri) f = urllib.pathname2url(self.__zip.getContentsFile()) element = reader.fromUri("file://" + f).documentElement else: element = reader.fromUri(source_uri).documentElement modeled.Modeled.__init__(self, element, None) self.__imports = None self.__annotations = None self.__queries = None self.__relations = None self.__schemas = None self.__views = None def close(self): if self.__zip: self.__zip.close() return def __str__(self): """Return a nice string representation of the object.""" return "Package (%s)" % self.__uri def _make_model(self): """Build a new empty annotation model""" di = xml.dom.getDOMImplementation() doc = di.createDocument(adveneNS, "package", None) elt = doc.documentElement elt.setAttributeNS(xmlNS, "xml:base", unicode(self.__uri)) elt.setAttributeNS(xmlnsNS, "xmlns", adveneNS) elt.setAttributeNS(xmlnsNS, "xmlns:xlink", xlinkNS) elt.setAttributeNS(xmlnsNS, "xmlns:dc", dcNS) elt.setAttributeNS(dcNS, "dc:creator", "") elt.appendChild(doc.createElementNS(adveneNS, "imports")) elt.appendChild(doc.createElementNS(adveneNS, "annotations")) elt.appendChild(doc.createElementNS(adveneNS, "queries")) elt.appendChild(doc.createElementNS(adveneNS, "schemas")) elt.appendChild(doc.createElementNS(adveneNS, "views")) return elt def _get_cached(self, uri): """Return a cached version of the package designated by "uri" """ return self.__pkg_cache.get(uri, None) def getOwnerPackage(self): """Return this package. Used for breaking recursivity in the parenthood tree.""" return self def getAccessPath(self): if self.__importer: r = list(self.__importer.getAccessPath()) r.append(self) return tuple(r) else: return (self, ) def getRootPackage(self): if self.__importer: return self.__importer.getRootPackage() else: return self def getUri(self, absolute=True, context=None): """ Return the URI of the package. Parameter if _absolute_ is _True_, the URI will be forced absolute. If not, and if _context_ is _None_, the URI will be resolved with respect to the root package URI, whatever its stored form (absolute or relative). If context is given and is a (direct or indirect) importer package, the URI will be resolved with respect to the context URI, whatever its stored form (absolute or relative). You would probably rather use the uri read-only property, unless you want to set the parameter _absolute_. """ uri = self.__uri if not absolute and context is self: return '' importer = self.__importer if importer is not None: uri = util.uri.urljoin(importer.getUri(absolute, context), uri) if absolute: base_uri = 'file:%s/' % urllib.pathname2url(os.getcwd()) uri = util.uri.urljoin(base_uri, uri) return uri def getImports(self): """Return a collection of this package's imports""" if self.__imports is None: e = self._getChild((adveneNS, "imports")) self.__imports = InverseDictBundle(self, e, Import, Import.getAlias) return self.__imports def getAnnotations(self): """Return a collection of this package's annotations""" if self.__annotations is None: e = self._getChild((adveneNS, "annotations")) self.__annotations = StandardXmlBundle(self, e, annotation.Annotation) return self.__annotations def getRelations(self): """Return a collection of this package's relations""" if self.__relations is None: e = self._getChild((adveneNS, "annotations")) # yes, "annotations"! #relations are under the same element as annotations # FIXME: is this always the case ? self.__relations = StandardXmlBundle(self, e, annotation.Relation) return self.__relations def getSchemas(self): """Return a collection of this package's schemas""" if self.__schemas is None: e = self._getChild((adveneNS, "schemas")) self.__schemas = ImportBundle(self, e, schema.Schema) return self.__schemas def getViews(self): """Return a collection of this package's view""" if self.__views is None: e = self._getChild((adveneNS, "views")) self.__views = ImportBundle(self, e, view.View) return self.__views def getQueries(self): """Return a collection of this package's queries""" if self.__queries is None: e = self._getChild((adveneNS, "queries")) self.__queries = ImportBundle(self, e, query.Query) return self.__queries def getAnnotationTypes(self): """Return a collection of this package's annotation types""" r = SumBundle() for s in self.getSchemas(): r += s.getAnnotationTypes() return r def getRelationTypes(self): """Return a collection of this package's relation types""" r = SumBundle() for s in self.getSchemas(): r += s.getRelationTypes() return r def getResources(self): if self.__zip is None: return None else: return self.__zip.getResources(package=self) def get_element_by_id(self, i): if not i: return None uri = self.uri for m in (self.getSchemas, self.getViews, self.getAnnotationTypes, self.getRelationTypes, self.getAnnotations, self.getQueries, self.getRelations): el = m().get('#'.join((uri, i)), None) if el is not None: return el return None def generate_statistics(self): """Generate the statistics.xml file. """ out = u"""<?xml version="1.0" encoding="UTF-8"?> <statistics:statistics xmlns:statistics="urn:advene:names:tc:opendocument:xmlns:manifest:1.0"> """ # Note: we do not use urllib.quote, since it chokes on non-ASCII characters (unicode) out += u"""<statistics:title value="%s" />""" % ( (self.title or '').replace('"', '%22') or "") out += u"""<statistics:description value="%s" />""" % ( (self.getMetaData(config.data.namespace_prefix['dc'], 'description') or "").replace('"', '%22') or "") for n, l in (('schema', len(self.schemas)), ('annotation', len(self.annotations)), ('annotation_type', len(self.annotationTypes)), ('relation', len(self.relations)), ('relation_type', len(self.relationTypes)), ('query', len(self.queries)), ('view', len(self.views))): out += u"""<statistics:item name="%s" value="%d" />""" % (n, l) out += u"""</statistics:statistics>""" return out def serialize(self, stream=sys.stdout): """Serialize the Package on the specified stream""" stream.write(self._getModel().toxml(encoding='utf8')) def save(self, name=None): """Save the Package in the specified file""" if name is None: name = self.__uri if name.startswith('file:///'): name = name[7:] if re.match('|/', name): # Windows drive: notation. Convert it from # a more URI-compatible syntax name = urllib.url2pathname(name) # handle .azp files. if name.lower().endswith('.azp') or name.endswith('/'): # AZP format if self.__zip is None: # Conversion necessary: we are saving to the new format. z = ZipPackage() z.new() self.__zip = z # Save the content.xml stream = open(self.__zip.getContentsFile(), "w") self.serialize(stream) stream.close() # Generate the statistics self.__zip.update_statistics(self) # Save the whole .azp self.__zip.save(name) else: # Assuming plain XML format stream = open(name, "w") self.serialize(stream) stream.close() def _recursive_save(self): """Save recursively this packages with all its imported packages""" self.save() for i in self.getImports(): i.getPackage()._recursive_save() def getQnamePrefix(self, item): if self == item: return None if isinstance(item, Package): try: i = self.getImports()[item.uri] return i.getAlias() except KeyError: raise AdveneException("item %s has no QName prefix in %s" % (item, self)) else: return self.getQnamePrefix(item._getParent())