forked from python-openxml/python-docx
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocument.py
More file actions
149 lines (133 loc) · 5.21 KB
/
document.py
File metadata and controls
149 lines (133 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# encoding: utf-8
"""
|DocumentPart| and closely related objects
"""
from __future__ import (
absolute_import, division, print_function, unicode_literals
)
from ..document import Document
from .numbering import NumberingPart
from ..opc.constants import RELATIONSHIP_TYPE as RT
from ..opc.part import XmlPart
from ..oxml.shape import CT_Inline
from ..shape import InlineShapes
from ..shared import lazyproperty
from .styles import StylesPart
class DocumentPart(XmlPart):
"""
Main document part of a WordprocessingML (WML) package, aka a .docx file.
Acts as broker to other parts such as image, core properties, and style
parts. It also acts as a convenient delegate when a mid-document object
needs a service involving a remote ancestor. The `Parented.part` property
inherited by many content objects provides access to this part object for
that purpose.
"""
@property
def core_properties(self):
"""
A |CoreProperties| object providing read/write access to the core
properties of this document.
"""
return self.package.core_properties
@property
def document(self):
"""
A |Document| object providing access to the content of this document.
"""
return Document(self._element, self)
def get_or_add_image(self, image_descriptor):
"""
Return an (rId, image) 2-tuple for the image identified by
*image_descriptor*. *image* is an |Image| instance providing access
to the properties of the image, such as dimensions and image type.
*rId* is the key for the relationship between this document part and
the image part, reused if already present, newly created if not.
"""
image_part = self._package.image_parts.get_or_add_image_part(
image_descriptor
)
rId = self.relate_to(image_part, RT.IMAGE)
return rId, image_part.image
def get_style(self, style_id, style_type):
"""
Return the style in this document matching *style_id*. Returns the
default style for *style_type* if *style_id* is |None| or does not
match a defined style of *style_type*.
"""
return self.styles.get_by_id(style_id, style_type)
def get_style_id(self, style_or_name, style_type):
"""
Return the style_id (|str|) of the style of *style_type* matching
*style_or_name*. Returns |None| if the style resolves to the default
style for *style_type* or if *style_or_name* is itself |None|. Raises
if *style_or_name* is a style of the wrong type or names a style not
present in the document.
"""
return self.styles.get_style_id(style_or_name, style_type)
@lazyproperty
def inline_shapes(self):
"""
The |InlineShapes| instance containing the inline shapes in the
document.
"""
return InlineShapes(self._element.body, self)
def new_pic_inline(self, image_descriptor, width, height):
"""
Return a newly-created `w:inline` element containing the image
specified by *image_descriptor* and scaled based on the values of
*width* and *height*.
"""
rId, image = self.get_or_add_image(image_descriptor)
cx, cy = image.scaled_dimensions(width, height)
shape_id, filename = self.next_id, image.filename
return CT_Inline.new_pic_inline(shape_id, rId, filename, cx, cy)
@property
def next_id(self):
"""
The next available positive integer id value in this document. Gaps
in id sequence are filled. The id attribute value is unique in the
document, without regard to the element type it appears on.
"""
id_str_lst = self._element.xpath('//@id')
used_ids = [int(id_str) for id_str in id_str_lst if id_str.isdigit()]
for n in range(1, len(used_ids)+2):
if n not in used_ids:
return n
@lazyproperty
def numbering_part(self):
"""
A |NumberingPart| object providing access to the numbering
definitions for this document. Creates an empty numbering part if one
is not present.
"""
try:
return self.part_related_by(RT.NUMBERING)
except KeyError:
numbering_part = NumberingPart.new()
self.relate_to(numbering_part, RT.NUMBERING)
return numbering_part
def save(self, path_or_stream):
"""
Save this document to *path_or_stream*, which can be either a path to
a filesystem location (a string) or a file-like object.
"""
self.package.save(path_or_stream)
@property
def styles(self):
"""
A |Styles| object providing access to the styles in the styles part
of this document.
"""
return self._styles_part.styles
@property
def _styles_part(self):
"""
Instance of |StylesPart| for this document. Creates an empty styles
part if one is not present.
"""
try:
return self.part_related_by(RT.STYLES)
except KeyError:
styles_part = StylesPart.default(self.package)
self.relate_to(styles_part, RT.STYLES)
return styles_part