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