Provides access to the contents of a zip-format OPC package via its :attr:`serialized_parts` and :attr:`pkg_srels` attributes.
| 8 | |
| 9 | |
| 10 | class PackageReader: |
| 11 | """Provides access to the contents of a zip-format OPC package via its |
| 12 | :attr:`serialized_parts` and :attr:`pkg_srels` attributes.""" |
| 13 | |
| 14 | def __init__(self, content_types, pkg_srels, sparts): |
| 15 | super(PackageReader, self).__init__() |
| 16 | self._pkg_srels = pkg_srels |
| 17 | self._sparts = sparts |
| 18 | |
| 19 | @staticmethod |
| 20 | def from_file(pkg_file): |
| 21 | """Return a |PackageReader| instance loaded with contents of `pkg_file`.""" |
| 22 | phys_reader = PhysPkgReader(pkg_file) |
| 23 | content_types = _ContentTypeMap.from_xml(phys_reader.content_types_xml) |
| 24 | pkg_srels = PackageReader._srels_for(phys_reader, PACKAGE_URI) |
| 25 | sparts = PackageReader._load_serialized_parts(phys_reader, pkg_srels, content_types) |
| 26 | phys_reader.close() |
| 27 | return PackageReader(content_types, pkg_srels, sparts) |
| 28 | |
| 29 | def iter_sparts(self): |
| 30 | """Generate a 4-tuple `(partname, content_type, reltype, blob)` for each of the |
| 31 | serialized parts in the package.""" |
| 32 | for s in self._sparts: |
| 33 | yield (s.partname, s.content_type, s.reltype, s.blob) |
| 34 | |
| 35 | def iter_srels(self): |
| 36 | """Generate a 2-tuple `(source_uri, srel)` for each of the relationships in the |
| 37 | package.""" |
| 38 | for srel in self._pkg_srels: |
| 39 | yield (PACKAGE_URI, srel) |
| 40 | for spart in self._sparts: |
| 41 | for srel in spart.srels: |
| 42 | yield (spart.partname, srel) |
| 43 | |
| 44 | @staticmethod |
| 45 | def _load_serialized_parts(phys_reader, pkg_srels, content_types): |
| 46 | """Return a list of |_SerializedPart| instances corresponding to the parts in |
| 47 | `phys_reader` accessible by walking the relationship graph starting with |
| 48 | `pkg_srels`.""" |
| 49 | sparts = [] |
| 50 | part_walker = PackageReader._walk_phys_parts(phys_reader, pkg_srels) |
| 51 | for partname, blob, reltype, srels in part_walker: |
| 52 | content_type = content_types[partname] |
| 53 | spart = _SerializedPart(partname, content_type, reltype, blob, srels) |
| 54 | sparts.append(spart) |
| 55 | return tuple(sparts) |
| 56 | |
| 57 | @staticmethod |
| 58 | def _srels_for(phys_reader, source_uri): |
| 59 | """Return |_SerializedRelationships| instance populated with relationships for |
| 60 | source identified by `source_uri`.""" |
| 61 | rels_xml = phys_reader.rels_xml_for(source_uri) |
| 62 | return _SerializedRelationships.load_from_xml(source_uri.baseURI, rels_xml) |
| 63 | |
| 64 | @staticmethod |
| 65 | def _walk_phys_parts(phys_reader, srels, visited_partnames=None): |
| 66 | """Generate a 4-tuple `(partname, blob, reltype, srels)` for each of the parts |
| 67 | in `phys_reader` by walking the relationship graph rooted at srels.""" |
no outgoing calls
searching dependent graphs…