119 lines
3.8 KiB
Python
119 lines
3.8 KiB
Python
|
# encoding: utf-8
|
||
|
|
||
|
"""
|
||
|
Provides the PackURI value type along with some useful known pack URI strings
|
||
|
such as PACKAGE_URI.
|
||
|
"""
|
||
|
|
||
|
import posixpath
|
||
|
import re
|
||
|
|
||
|
|
||
|
class PackURI(str):
|
||
|
"""
|
||
|
Provides access to pack URI components such as the baseURI and the
|
||
|
filename slice. Behaves as |str| otherwise.
|
||
|
"""
|
||
|
|
||
|
_filename_re = re.compile("([a-zA-Z]+)([0-9][0-9]*)?")
|
||
|
|
||
|
def __new__(cls, pack_uri_str):
|
||
|
if not pack_uri_str[0] == "/":
|
||
|
tmpl = "PackURI must begin with slash, got '%s'"
|
||
|
raise ValueError(tmpl % pack_uri_str)
|
||
|
return str.__new__(cls, pack_uri_str)
|
||
|
|
||
|
@staticmethod
|
||
|
def from_rel_ref(baseURI, relative_ref):
|
||
|
"""
|
||
|
Return a |PackURI| instance containing the absolute pack URI formed by
|
||
|
translating *relative_ref* onto *baseURI*.
|
||
|
"""
|
||
|
joined_uri = posixpath.join(baseURI, relative_ref)
|
||
|
abs_uri = posixpath.abspath(joined_uri)
|
||
|
return PackURI(abs_uri)
|
||
|
|
||
|
@property
|
||
|
def baseURI(self):
|
||
|
"""
|
||
|
The base URI of this pack URI, the directory portion, roughly
|
||
|
speaking. E.g. ``'/ppt/slides'`` for ``'/ppt/slides/slide1.xml'``.
|
||
|
For the package pseudo-partname '/', baseURI is '/'.
|
||
|
"""
|
||
|
return posixpath.split(self)[0]
|
||
|
|
||
|
@property
|
||
|
def ext(self):
|
||
|
"""
|
||
|
The extension portion of this pack URI, e.g. ``'xml'`` for
|
||
|
``'/ppt/slides/slide1.xml'``. Note that the period is not included.
|
||
|
"""
|
||
|
# raw_ext is either empty string or starts with period, e.g. '.xml'
|
||
|
raw_ext = posixpath.splitext(self)[1]
|
||
|
return raw_ext[1:] if raw_ext.startswith(".") else raw_ext
|
||
|
|
||
|
@property
|
||
|
def filename(self):
|
||
|
"""
|
||
|
The "filename" portion of this pack URI, e.g. ``'slide1.xml'`` for
|
||
|
``'/ppt/slides/slide1.xml'``. For the package pseudo-partname '/',
|
||
|
filename is ''.
|
||
|
"""
|
||
|
return posixpath.split(self)[1]
|
||
|
|
||
|
@property
|
||
|
def idx(self):
|
||
|
"""
|
||
|
Return partname index as integer for tuple partname or None for
|
||
|
singleton partname, e.g. ``21`` for ``'/ppt/slides/slide21.xml'`` and
|
||
|
|None| for ``'/ppt/presentation.xml'``.
|
||
|
"""
|
||
|
filename = self.filename
|
||
|
if not filename:
|
||
|
return None
|
||
|
name_part = posixpath.splitext(filename)[0] # filename w/ext removed
|
||
|
match = self._filename_re.match(name_part)
|
||
|
if match is None:
|
||
|
return None
|
||
|
if match.group(2):
|
||
|
return int(match.group(2))
|
||
|
return None
|
||
|
|
||
|
@property
|
||
|
def membername(self):
|
||
|
"""
|
||
|
The pack URI with the leading slash stripped off, the form used as
|
||
|
the Zip file membername for the package item. Returns '' for the
|
||
|
package pseudo-partname '/'.
|
||
|
"""
|
||
|
return self[1:]
|
||
|
|
||
|
def relative_ref(self, baseURI):
|
||
|
"""
|
||
|
Return string containing relative reference to package item from
|
||
|
*baseURI*. E.g. PackURI('/ppt/slideLayouts/slideLayout1.xml') would
|
||
|
return '../slideLayouts/slideLayout1.xml' for baseURI '/ppt/slides'.
|
||
|
"""
|
||
|
# workaround for posixpath bug in 2.6, doesn't generate correct
|
||
|
# relative path when *start* (second) parameter is root ('/')
|
||
|
if baseURI == "/":
|
||
|
relpath = self[1:]
|
||
|
else:
|
||
|
relpath = posixpath.relpath(self, baseURI)
|
||
|
return relpath
|
||
|
|
||
|
@property
|
||
|
def rels_uri(self):
|
||
|
"""
|
||
|
The pack URI of the .rels part corresponding to the current pack URI.
|
||
|
Only produces sensible output if the pack URI is a partname or the
|
||
|
package pseudo-partname '/'.
|
||
|
"""
|
||
|
rels_filename = "%s.rels" % self.filename
|
||
|
rels_uri_str = posixpath.join(self.baseURI, "_rels", rels_filename)
|
||
|
return PackURI(rels_uri_str)
|
||
|
|
||
|
|
||
|
PACKAGE_URI = PackURI("/")
|
||
|
CONTENT_TYPES_URI = PackURI("/[Content_Types].xml")
|