def get_entry(self, location): """ Returns the archive entry in the given location or raises an KeyError, if not found """ location = utils.clean_pathname(location) if self.entries[location]: return self.entries[location] else: raise KeyError('Did not found {loc} in COMBINE archive'.format(loc=location))
def _read_manifest(self): """ internal function. Reads the manifest file of a COMBINE Archive """ try: with self._zip.open(self.MANIFEST_LOCATION) as manifest_file: manifest = ElementTree.fromstring(manifest_file.read()) except KeyError: # manifest does not exists, probably an empty/new archive return False except ElementTree.ParseError as e: raise exceptions.CombineArchiveException( 'Cannot parse xml manifest. {}'.format(e.msg)) # check for correct root element and namespace if manifest.tag != utils.extend_tag_name(_XML_ROOT_ELEM, _XML_NS): raise exceptions.CombineArchiveException( 'manifest has no valid omex root element') # check entries for entry in manifest.findall(_XML_CONTENT_TAG, _XML_NS): try: location = utils.get_attribute(entry, _XML_CONTENT_LOCATION, _XML_NS) entry_format = utils.check_format(utils.get_attribute( entry, _XML_CONTENT_FORMAT, _XML_NS), convert=False) master = True if entry.attrib.get(_XML_CONTENT_MASTER, False) in ('True', 'true', True) else False except KeyError: raise exceptions.CombineArchiveException( 'location and format field are required. Corrupt manifest.xml' ) # clean location location = utils.clean_pathname(location) # check if file is in zip, if it's not the root element zipinfo = None if location not in self.ARCHIVE_REFERENCE: try: zipinfo = self._zip.getinfo(location) except KeyError: raise exceptions.CombineArchiveException( '{location} is specified by the manifest, but not contained by the ZIP file' .format(location=location)) archive_entry = ArchiveEntry(location, format=entry_format, master=master, archive=self, zipinfo=zipinfo) self.entries[location] = archive_entry
def remove_entry(self, location): """ Removes an entry from the COMBINE archive. The file will remain in the zip archive, until pack() is called. """ location = utils.clean_pathname(location) if self.entries[location]: self._zip.remove(location) del self.entries[location] else: raise KeyError('Did not found {loc} in COMBINE archive'.format(loc=location))
def get_entry(self, location): """ Returns the archive entry in the given location or raises an KeyError, if not found """ location = utils.clean_pathname(location) if self.entries[location]: return self.entries[location] else: raise KeyError( 'Did not found {loc} in COMBINE archive'.format(loc=location))
def remove_entry(self, location): """ Removes an entry from the COMBINE archive. The file will remain in the zip archive, until pack() is called. """ location = utils.clean_pathname(location) if self.entries[location]: self._zip.remove(location) del self.entries[location] else: raise KeyError( 'Did not found {loc} in COMBINE archive'.format(loc=location))
def add_entry(self, file, format, location=None, master=False, replace=False): """ adds a file-like object to the COMBINE archive and adds a manifest entry if file is an instance of unicode or str, the content of this variable is written as content Returns: ArchiveEntry """ if not file or not format: raise exceptions.CombineArchiveException( 'both a file and the corresponding format must be provided') # check format schema format = utils.check_format(format) # no location provided. Guess it if location is None or not location: location = os.path.basename(file) # clean location location = utils.clean_pathname(location) if location == self.MANIFEST_LOCATION or location in self.ARCHIVE_REFERENCE: raise exceptions.CombineArchiveException( 'it is not allowed to name a file {loc}'.format(loc=location)) if location in self._zip.namelist(): if replace is False: raise exceptions.CombineArchiveException( '{loc} exists already in the COMBINE archive. set replace=True, to override it' .format(loc=location)) else: self.remove_entry(location) # write file to zip if isinstance(file, (str, unicode)): # file is actually string zipinfo = self._zip.writestr(location, file) else: zipinfo = self._zip.write(file, location) entry = ArchiveEntry(location, format=format, master=master, zipinfo=zipinfo, archive=self) self.entries[entry.location] = entry return entry
def _read_manifest(self): """ internal function. Reads the manifest file of a COMBINE Archive """ try: with self._zip.open(self.MANIFEST_LOCATION) as manifest_file: manifest = ElementTree.fromstring(manifest_file.read()) except KeyError: # manifest does not exists, probably an empty/new archive return False except ElementTree.ParseError as e: raise exceptions.CombineArchiveException('Cannot parse xml manifest. {}'.format(e.msg)) # check for correct root element and namespace if manifest.tag != utils.extend_tag_name(_XML_ROOT_ELEM, _XML_NS): raise exceptions.CombineArchiveException('manifest has no valid omex root element') # check entries for entry in manifest.findall(_XML_CONTENT_TAG, _XML_NS): try: location = utils.get_attribute(entry, _XML_CONTENT_LOCATION, _XML_NS) entry_format = utils.check_format(utils.get_attribute(entry, _XML_CONTENT_FORMAT, _XML_NS), convert=False) master = True if entry.attrib.get(_XML_CONTENT_MASTER, False) in ('True', 'true', True) else False except KeyError: raise exceptions.CombineArchiveException('location and format field are required. Corrupt manifest.xml') # clean location location = utils.clean_pathname(location) # check if file is in zip, if it's not the root element zipinfo = None if location not in self.ARCHIVE_REFERENCE: try: zipinfo = self._zip.getinfo(location) except KeyError: raise exceptions.CombineArchiveException( '{location} is specified by the manifest, but not contained by the ZIP file'.format(location=location)) archive_entry = ArchiveEntry(location, format=entry_format, master=master, archive=self, zipinfo=zipinfo) self.entries[location] = archive_entry
def add_entry(self, file, format, location=None, master=False, replace=False): """ adds a file-like object to the COMBINE archive and adds a manifest entry if file is an instance of unicode or str, the content of this variable is written as content Returns: ArchiveEntry """ if not file or not format: raise exceptions.CombineArchiveException('both a file and the corresponding format must be provided') # check format schema format = utils.check_format(format) # no location provided. Guess it if location is None or not location: location = os.path.basename(file) # clean location location = utils.clean_pathname(location) if location == self.MANIFEST_LOCATION or location in self.ARCHIVE_REFERENCE: raise exceptions.CombineArchiveException('it is not allowed to name a file {loc}'.format(loc=location)) if location in self._zip.namelist(): if replace is False: raise exceptions.CombineArchiveException('{loc} exists already in the COMBINE archive. set replace=True, to override it'.format(loc=location)) else: self.remove_entry(location) # write file to zip if isinstance(file, (str, unicode)): # file is actually string zipinfo = self._zip.writestr(location, file) else: zipinfo = self._zip.write(file, location) entry = ArchiveEntry(location, format=format, master=master, zipinfo=zipinfo, archive=self) self.entries[entry.location] = entry return entry