1010from .compat import cls_method_fn
1111from .constants import RELATIONSHIP_TYPE as RT
1212from .oxml import CT_Relationships , serialize_part_xml
13+ from ..oxml import parse_xml
1314from .packuri import PACKAGE_URI , PackURI
1415from .pkgreader import PackageReader
1516from .pkgwriter import PackageWriter
@@ -146,7 +147,6 @@ def save(self, pkg_file):
146147 Save this package to *pkg_file*, where *file* can be either a path to
147148 a file (a string) or a file-like object.
148149 """
149- # self._notify_before_marshal()
150150 for part in self .parts :
151151 part .before_marshal ()
152152 PackageWriter .write (pkg_file , self .rels , self .parts )
@@ -158,18 +158,13 @@ class Part(object):
158158 intended to be subclassed in client code to implement specific part
159159 behaviors.
160160 """
161- def __init__ (
162- self , partname , content_type , blob = None , element = None ,
163- package = None ):
161+ def __init__ (self , partname , content_type , blob = None , package = None ):
164162 super (Part , self ).__init__ ()
165163 self ._partname = partname
166164 self ._content_type = content_type
167165 self ._blob = blob
168- self ._element = element
169166 self ._package = package
170167
171- # load/save interface to OpcPackage ------------------------------
172-
173168 def after_unmarshal (self ):
174169 """
175170 Entry point for post-unmarshaling processing, for example to parse
@@ -197,8 +192,6 @@ def blob(self):
197192 binary. Intended to be overridden by subclasses. Default behavior is
198193 to return load blob.
199194 """
200- if self ._element is not None :
201- return serialize_part_xml (self ._element )
202195 return self ._blob
203196
204197 @property
@@ -208,18 +201,25 @@ def content_type(self):
208201 """
209202 return self ._content_type
210203
204+ def drop_rel (self , rId ):
205+ """
206+ Remove the relationship identified by *rId* if its reference count
207+ is less than 2. Relationships with a reference count of 0 are
208+ implicit relationships.
209+ """
210+ if self ._rel_ref_count (rId ) < 2 :
211+ del self .rels [rId ]
212+
211213 @classmethod
212214 def load (cls , partname , content_type , blob , package ):
213- return cls (
214- partname , content_type , blob = blob , element = None , package = package
215- )
215+ return cls (partname , content_type , blob , package )
216216
217217 def load_rel (self , reltype , target , rId , is_external = False ):
218218 """
219219 Return newly added |_Relationship| instance of *reltype* between this
220220 part and *target* with key *rId*. Target mode is set to
221221 ``RTM.EXTERNAL`` if *is_external* is |True|. Intended for use during
222- load from a serialized package, where the rId is well known. Other
222+ load from a serialized package, where the rId is well- known. Other
223223 methods exist for adding a new relationship to a part when
224224 manipulating a part.
225225 """
@@ -240,16 +240,12 @@ def partname(self, partname):
240240 raise TypeError (tmpl % type (partname ).__name__ )
241241 self ._partname = partname
242242
243- # relationship management interface for child objects ------------
244-
245- def drop_rel (self , rId ):
243+ @property
244+ def package (self ):
246245 """
247- Remove the relationship identified by *rId* if its reference count
248- is less than 2. Relationships with a reference count of 0 are
249- implicit relationships.
246+ |OpcPackage| instance this part belongs to.
250247 """
251- if self ._rel_ref_count (rId ) < 2 :
252- del self .rels [rId ]
248+ return self ._package
253249
254250 def part_related_by (self , reltype ):
255251 """
@@ -300,18 +296,40 @@ def _rel_ref_count(self, rId):
300296 Return the count of references in this part's XML to the relationship
301297 identified by *rId*.
302298 """
303- assert self ._element is not None
304299 rIds = self ._element .xpath ('//@r:id' )
305300 return len ([_rId for _rId in rIds if _rId == rId ])
306301
307- # ----------------------------------------------------------------
302+
303+ class XmlPart (Part ):
304+ """
305+ Base class for package parts containing an XML payload, which is most of
306+ them. Provides additional methods to the |Part| base class that take care
307+ of parsing and reserializing the XML payload and managing relationships
308+ to other parts.
309+ """
310+ def __init__ (self , partname , content_type , element , package ):
311+ super (XmlPart , self ).__init__ (
312+ partname , content_type , package = package
313+ )
314+ self ._element = element
308315
309316 @property
310- def package (self ):
317+ def blob (self ):
318+ return serialize_part_xml (self ._element )
319+
320+ @classmethod
321+ def load (cls , partname , content_type , blob , package ):
322+ element = parse_xml (blob )
323+ return cls (partname , content_type , element , package )
324+
325+ @property
326+ def part (self ):
311327 """
312- |OpcPackage| instance this part belongs to.
328+ Part of the parent protocol, "children" of the document will not know
329+ the part that contains them so must ask their parent object. That
330+ chain of delegation ends here for child objects.
313331 """
314- return self . _package
332+ return self
315333
316334
317335class PartFactory (object ):
0 commit comments