Base class for package parts. Provides common properties and methods, but intended to be subclassed in client code to implement specific part behaviors. Also serves as the default class for parts that are not yet given specific behaviors.
| 279 | |
| 280 | |
| 281 | class Part(_RelatableMixin): |
| 282 | """Base class for package parts. |
| 283 | |
| 284 | Provides common properties and methods, but intended to be subclassed in client code to |
| 285 | implement specific part behaviors. Also serves as the default class for parts that are not yet |
| 286 | given specific behaviors. |
| 287 | """ |
| 288 | |
| 289 | def __init__( |
| 290 | self, partname: PackURI, content_type: str, package: Package, blob: bytes | None = None |
| 291 | ): |
| 292 | # --- XmlPart subtypes, don't store a blob (the original XML) --- |
| 293 | self._partname = partname |
| 294 | self._content_type = content_type |
| 295 | self._package = package |
| 296 | self._blob = blob |
| 297 | |
| 298 | @classmethod |
| 299 | def load(cls, partname: PackURI, content_type: str, package: Package, blob: bytes) -> Self: |
| 300 | """Return `cls` instance loaded from arguments. |
| 301 | |
| 302 | This one is a straight pass-through, but subtypes may do some pre-processing, see XmlPart |
| 303 | for an example. |
| 304 | """ |
| 305 | return cls(partname, content_type, package, blob) |
| 306 | |
| 307 | @property |
| 308 | def blob(self) -> bytes: |
| 309 | """Contents of this package part as a sequence of bytes. |
| 310 | |
| 311 | Intended to be overridden by subclasses. Default behavior is to return the blob initial |
| 312 | loaded during `Package.open()` operation. |
| 313 | """ |
| 314 | return self._blob or b"" |
| 315 | |
| 316 | @blob.setter |
| 317 | def blob(self, blob: bytes): |
| 318 | """Note that not all subclasses use the part blob as their blob source. |
| 319 | |
| 320 | In particular, the |XmlPart| subclass uses its `self._element` to serialize a blob on |
| 321 | demand. This works fine for binary parts though. |
| 322 | """ |
| 323 | self._blob = blob |
| 324 | |
| 325 | @lazyproperty |
| 326 | def content_type(self) -> str: |
| 327 | """Content-type (MIME-type) of this part.""" |
| 328 | return self._content_type |
| 329 | |
| 330 | def load_rels_from_xml(self, xml_rels: CT_Relationships, parts: dict[PackURI, Part]) -> None: |
| 331 | """load _Relationships for this part from `xml_rels`. |
| 332 | |
| 333 | Part references are resolved using the `parts` dict that maps each partname to the loaded |
| 334 | part with that partname. These relationships are loaded from a serialized package and so |
| 335 | already have assigned rIds. This method is only used during package loading. |
| 336 | """ |
| 337 | self._rels.load_from_xml(self._partname.baseURI, xml_rels, parts) |
| 338 |
no outgoing calls
searching dependent graphs…