ps-python-docx 1.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. docx/__init__.py +68 -0
  2. docx/api.py +37 -0
  3. docx/blkcntnr.py +101 -0
  4. docx/comments.py +163 -0
  5. docx/dml/__init__.py +0 -0
  6. docx/dml/color.py +112 -0
  7. docx/document.py +275 -0
  8. docx/drawing/__init__.py +59 -0
  9. docx/enum/__init__.py +0 -0
  10. docx/enum/base.py +150 -0
  11. docx/enum/dml.py +103 -0
  12. docx/enum/section.py +86 -0
  13. docx/enum/shape.py +19 -0
  14. docx/enum/style.py +452 -0
  15. docx/enum/table.py +136 -0
  16. docx/enum/text.py +367 -0
  17. docx/exceptions.py +18 -0
  18. docx/image/__init__.py +23 -0
  19. docx/image/bmp.py +43 -0
  20. docx/image/constants.py +172 -0
  21. docx/image/exceptions.py +13 -0
  22. docx/image/gif.py +38 -0
  23. docx/image/helpers.py +86 -0
  24. docx/image/image.py +234 -0
  25. docx/image/jpeg.py +425 -0
  26. docx/image/png.py +253 -0
  27. docx/image/tiff.py +289 -0
  28. docx/opc/__init__.py +0 -0
  29. docx/opc/constants.py +306 -0
  30. docx/opc/coreprops.py +142 -0
  31. docx/opc/exceptions.py +12 -0
  32. docx/opc/oxml.py +247 -0
  33. docx/opc/package.py +219 -0
  34. docx/opc/packuri.py +109 -0
  35. docx/opc/part.py +247 -0
  36. docx/opc/parts/__init__.py +0 -0
  37. docx/opc/parts/coreprops.py +48 -0
  38. docx/opc/phys_pkg.py +119 -0
  39. docx/opc/pkgreader.py +254 -0
  40. docx/opc/pkgwriter.py +115 -0
  41. docx/opc/rel.py +153 -0
  42. docx/opc/shared.py +31 -0
  43. docx/opc/spec.py +24 -0
  44. docx/oxml/__init__.py +261 -0
  45. docx/oxml/comments.py +124 -0
  46. docx/oxml/coreprops.py +298 -0
  47. docx/oxml/document.py +88 -0
  48. docx/oxml/drawing.py +11 -0
  49. docx/oxml/exceptions.py +10 -0
  50. docx/oxml/ns.py +109 -0
  51. docx/oxml/numbering.py +109 -0
  52. docx/oxml/parser.py +62 -0
  53. docx/oxml/section.py +537 -0
  54. docx/oxml/settings.py +138 -0
  55. docx/oxml/shape.py +299 -0
  56. docx/oxml/shared.py +52 -0
  57. docx/oxml/simpletypes.py +434 -0
  58. docx/oxml/styles.py +341 -0
  59. docx/oxml/table.py +977 -0
  60. docx/oxml/text/__init__.py +0 -0
  61. docx/oxml/text/font.py +333 -0
  62. docx/oxml/text/hyperlink.py +45 -0
  63. docx/oxml/text/pagebreak.py +278 -0
  64. docx/oxml/text/paragraph.py +106 -0
  65. docx/oxml/text/parfmt.py +392 -0
  66. docx/oxml/text/run.py +307 -0
  67. docx/oxml/xmlchemy.py +696 -0
  68. docx/package.py +110 -0
  69. docx/parts/__init__.py +0 -0
  70. docx/parts/comments.py +51 -0
  71. docx/parts/document.py +182 -0
  72. docx/parts/hdrftr.py +53 -0
  73. docx/parts/image.py +80 -0
  74. docx/parts/numbering.py +32 -0
  75. docx/parts/settings.py +50 -0
  76. docx/parts/story.py +95 -0
  77. docx/parts/styles.py +42 -0
  78. docx/parts/theme.py +53 -0
  79. docx/py.typed +0 -0
  80. docx/section.py +479 -0
  81. docx/settings.py +35 -0
  82. docx/shape.py +103 -0
  83. docx/shared.py +382 -0
  84. docx/styles/__init__.py +40 -0
  85. docx/styles/latent.py +198 -0
  86. docx/styles/style.py +264 -0
  87. docx/styles/styles.py +147 -0
  88. docx/table.py +537 -0
  89. docx/templates/default-comments.xml +12 -0
  90. docx/templates/default-docx-template/[Content_Types].xml +17 -0
  91. docx/templates/default-docx-template/_rels/.rels +7 -0
  92. docx/templates/default-docx-template/customXml/_rels/item1.xml.rels +4 -0
  93. docx/templates/default-docx-template/customXml/item1.xml +2 -0
  94. docx/templates/default-docx-template/customXml/itemProps1.xml +6 -0
  95. docx/templates/default-docx-template/docProps/app.xml +36 -0
  96. docx/templates/default-docx-template/docProps/core.xml +13 -0
  97. docx/templates/default-docx-template/docProps/thumbnail.jpeg +0 -0
  98. docx/templates/default-docx-template/word/_rels/document.xml.rels +11 -0
  99. docx/templates/default-docx-template/word/document.xml +11 -0
  100. docx/templates/default-docx-template/word/fontTable.xml +61 -0
  101. docx/templates/default-docx-template/word/numbering.xml +201 -0
  102. docx/templates/default-docx-template/word/settings.xml +53 -0
  103. docx/templates/default-docx-template/word/styles.xml +11844 -0
  104. docx/templates/default-docx-template/word/stylesWithEffects.xml +11800 -0
  105. docx/templates/default-docx-template/word/theme/theme1.xml +318 -0
  106. docx/templates/default-docx-template/word/webSettings.xml +5 -0
  107. docx/templates/default-footer.xml +27 -0
  108. docx/templates/default-header.xml +27 -0
  109. docx/templates/default-settings.xml +26 -0
  110. docx/templates/default-styles.xml +190 -0
  111. docx/templates/default.docx +0 -0
  112. docx/text/__init__.py +0 -0
  113. docx/text/font.py +472 -0
  114. docx/text/hyperlink.py +121 -0
  115. docx/text/pagebreak.py +104 -0
  116. docx/text/paragraph.py +173 -0
  117. docx/text/parfmt.py +286 -0
  118. docx/text/run.py +257 -0
  119. docx/text/tabstops.py +123 -0
  120. docx/theme.py +67 -0
  121. docx/types.py +34 -0
  122. ps_python_docx-1.3.0.dist-info/METADATA +77 -0
  123. ps_python_docx-1.3.0.dist-info/RECORD +126 -0
  124. ps_python_docx-1.3.0.dist-info/WHEEL +5 -0
  125. ps_python_docx-1.3.0.dist-info/licenses/LICENSE +20 -0
  126. ps_python_docx-1.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,106 @@
1
+ # pyright: reportPrivateUsage=false
2
+
3
+ """Custom element classes related to paragraphs (CT_P)."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from typing import TYPE_CHECKING, Callable, List, cast
8
+
9
+ from docx.oxml.parser import OxmlElement
10
+ from docx.oxml.xmlchemy import BaseOxmlElement, ZeroOrMore, ZeroOrOne
11
+
12
+ if TYPE_CHECKING:
13
+ from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
14
+ from docx.oxml.section import CT_SectPr
15
+ from docx.oxml.text.hyperlink import CT_Hyperlink
16
+ from docx.oxml.text.pagebreak import CT_LastRenderedPageBreak
17
+ from docx.oxml.text.parfmt import CT_PPr
18
+ from docx.oxml.text.run import CT_R
19
+
20
+
21
+ class CT_P(BaseOxmlElement):
22
+ """`<w:p>` element, containing the properties and text for a paragraph."""
23
+
24
+ add_r: Callable[[], CT_R]
25
+ get_or_add_pPr: Callable[[], CT_PPr]
26
+ hyperlink_lst: List[CT_Hyperlink]
27
+ r_lst: List[CT_R]
28
+
29
+ pPr: CT_PPr | None = ZeroOrOne("w:pPr") # pyright: ignore[reportAssignmentType]
30
+ hyperlink = ZeroOrMore("w:hyperlink")
31
+ r = ZeroOrMore("w:r")
32
+
33
+ def add_p_before(self) -> CT_P:
34
+ """Return a new `<w:p>` element inserted directly prior to this one."""
35
+ new_p = cast(CT_P, OxmlElement("w:p"))
36
+ self.addprevious(new_p)
37
+ return new_p
38
+
39
+ @property
40
+ def alignment(self) -> WD_PARAGRAPH_ALIGNMENT | None:
41
+ """The value of the `<w:jc>` grandchild element or |None| if not present."""
42
+ pPr = self.pPr
43
+ if pPr is None:
44
+ return None
45
+ return pPr.jc_val
46
+
47
+ @alignment.setter
48
+ def alignment(self, value: WD_PARAGRAPH_ALIGNMENT):
49
+ pPr = self.get_or_add_pPr()
50
+ pPr.jc_val = value
51
+
52
+ def clear_content(self):
53
+ """Remove all child elements, except the `<w:pPr>` element if present."""
54
+ for child in self.xpath("./*[not(self::w:pPr)]"):
55
+ self.remove(child)
56
+
57
+ @property
58
+ def inner_content_elements(self) -> List[CT_R | CT_Hyperlink]:
59
+ """Run and hyperlink children of the `w:p` element, in document order."""
60
+ return self.xpath("./w:r | ./w:hyperlink")
61
+
62
+ @property
63
+ def lastRenderedPageBreaks(self) -> List[CT_LastRenderedPageBreak]:
64
+ """All `w:lastRenderedPageBreak` descendants of this paragraph.
65
+
66
+ Rendered page-breaks commonly occur in a run but can also occur in a run inside
67
+ a hyperlink. This returns both.
68
+ """
69
+ return self.xpath(
70
+ "./w:r/w:lastRenderedPageBreak | ./w:hyperlink/w:r/w:lastRenderedPageBreak"
71
+ )
72
+
73
+ def set_sectPr(self, sectPr: CT_SectPr):
74
+ """Unconditionally replace or add `sectPr` as grandchild in correct sequence."""
75
+ pPr = self.get_or_add_pPr()
76
+ pPr._remove_sectPr()
77
+ pPr._insert_sectPr(sectPr)
78
+
79
+ @property
80
+ def style(self) -> str | None:
81
+ """String contained in `w:val` attribute of `./w:pPr/w:pStyle` grandchild.
82
+
83
+ |None| if not present.
84
+ """
85
+ pPr = self.pPr
86
+ if pPr is None:
87
+ return None
88
+ return pPr.style
89
+
90
+ @style.setter
91
+ def style(self, style: str | None):
92
+ pPr = self.get_or_add_pPr()
93
+ pPr.style = style
94
+
95
+ @property
96
+ def text(self): # pyright: ignore[reportIncompatibleMethodOverride]
97
+ """The textual content of this paragraph.
98
+
99
+ Inner-content child elements like `w:r` and `w:hyperlink` are translated to
100
+ their text equivalent.
101
+ """
102
+ return "".join(e.text for e in self.xpath("w:r | w:hyperlink"))
103
+
104
+ def _insert_pPr(self, pPr: CT_PPr) -> CT_PPr:
105
+ self.insert(0, pPr)
106
+ return pPr
@@ -0,0 +1,392 @@
1
+ """Custom element classes related to paragraph properties (CT_PPr)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Callable
6
+
7
+ from docx.enum.text import (
8
+ WD_ALIGN_PARAGRAPH,
9
+ WD_LINE_SPACING,
10
+ WD_TAB_ALIGNMENT,
11
+ WD_TAB_LEADER,
12
+ )
13
+ from docx.oxml.shared import CT_DecimalNumber
14
+ from docx.oxml.simpletypes import ST_SignedTwipsMeasure, ST_TwipsMeasure
15
+ from docx.oxml.xmlchemy import (
16
+ BaseOxmlElement,
17
+ OneOrMore,
18
+ OptionalAttribute,
19
+ RequiredAttribute,
20
+ ZeroOrOne,
21
+ )
22
+ from docx.shared import Length
23
+
24
+ if TYPE_CHECKING:
25
+ from docx.oxml.section import CT_SectPr
26
+ from docx.oxml.shared import CT_String
27
+
28
+
29
+ class CT_Ind(BaseOxmlElement):
30
+ """``<w:ind>`` element, specifying paragraph indentation."""
31
+
32
+ left: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
33
+ "w:left", ST_SignedTwipsMeasure
34
+ )
35
+ right: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
36
+ "w:right", ST_SignedTwipsMeasure
37
+ )
38
+ firstLine: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
39
+ "w:firstLine", ST_TwipsMeasure
40
+ )
41
+ hanging: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
42
+ "w:hanging", ST_TwipsMeasure
43
+ )
44
+
45
+
46
+ class CT_Jc(BaseOxmlElement):
47
+ """``<w:jc>`` element, specifying paragraph justification."""
48
+
49
+ val: WD_ALIGN_PARAGRAPH = RequiredAttribute( # pyright: ignore[reportAssignmentType]
50
+ "w:val", WD_ALIGN_PARAGRAPH
51
+ )
52
+
53
+
54
+ class CT_PPr(BaseOxmlElement):
55
+ """``<w:pPr>`` element, containing the properties for a paragraph."""
56
+
57
+ get_or_add_ind: Callable[[], CT_Ind]
58
+ get_or_add_pStyle: Callable[[], CT_String]
59
+ get_or_add_sectPr: Callable[[], CT_SectPr]
60
+ _insert_sectPr: Callable[[CT_SectPr], None]
61
+ _remove_pStyle: Callable[[], None]
62
+ _remove_sectPr: Callable[[], None]
63
+
64
+ _tag_seq = (
65
+ "w:pStyle",
66
+ "w:keepNext",
67
+ "w:keepLines",
68
+ "w:pageBreakBefore",
69
+ "w:framePr",
70
+ "w:widowControl",
71
+ "w:numPr",
72
+ "w:suppressLineNumbers",
73
+ "w:pBdr",
74
+ "w:shd",
75
+ "w:tabs",
76
+ "w:suppressAutoHyphens",
77
+ "w:kinsoku",
78
+ "w:wordWrap",
79
+ "w:overflowPunct",
80
+ "w:topLinePunct",
81
+ "w:autoSpaceDE",
82
+ "w:autoSpaceDN",
83
+ "w:bidi",
84
+ "w:adjustRightInd",
85
+ "w:snapToGrid",
86
+ "w:spacing",
87
+ "w:ind",
88
+ "w:contextualSpacing",
89
+ "w:mirrorIndents",
90
+ "w:suppressOverlap",
91
+ "w:jc",
92
+ "w:textDirection",
93
+ "w:textAlignment",
94
+ "w:textboxTightWrap",
95
+ "w:outlineLvl",
96
+ "w:divId",
97
+ "w:cnfStyle",
98
+ "w:rPr",
99
+ "w:sectPr",
100
+ "w:pPrChange",
101
+ )
102
+ pStyle: CT_String | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
103
+ "w:pStyle", successors=_tag_seq[1:]
104
+ )
105
+ keepNext = ZeroOrOne("w:keepNext", successors=_tag_seq[2:])
106
+ keepLines = ZeroOrOne("w:keepLines", successors=_tag_seq[3:])
107
+ pageBreakBefore = ZeroOrOne("w:pageBreakBefore", successors=_tag_seq[4:])
108
+ widowControl = ZeroOrOne("w:widowControl", successors=_tag_seq[6:])
109
+ numPr = ZeroOrOne("w:numPr", successors=_tag_seq[7:])
110
+ tabs = ZeroOrOne("w:tabs", successors=_tag_seq[11:])
111
+ spacing = ZeroOrOne("w:spacing", successors=_tag_seq[22:])
112
+ ind: CT_Ind | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
113
+ "w:ind", successors=_tag_seq[23:]
114
+ )
115
+ jc = ZeroOrOne("w:jc", successors=_tag_seq[27:])
116
+ outlineLvl: CT_DecimalNumber = ZeroOrOne( # pyright: ignore[reportAssignmentType]
117
+ "w:outlineLvl", successors=_tag_seq[31:]
118
+ )
119
+ sectPr = ZeroOrOne("w:sectPr", successors=_tag_seq[35:])
120
+ del _tag_seq
121
+
122
+ @property
123
+ def first_line_indent(self) -> Length | None:
124
+ """A |Length| value calculated from the values of `w:ind/@w:firstLine` and
125
+ `w:ind/@w:hanging`.
126
+
127
+ Returns |None| if the `w:ind` child is not present.
128
+ """
129
+ ind = self.ind
130
+ if ind is None:
131
+ return None
132
+ hanging = ind.hanging
133
+ if hanging is not None:
134
+ return Length(-hanging)
135
+ firstLine = ind.firstLine
136
+ if firstLine is None:
137
+ return None
138
+ return firstLine
139
+
140
+ @first_line_indent.setter
141
+ def first_line_indent(self, value: Length | None):
142
+ if self.ind is None and value is None:
143
+ return
144
+ ind = self.get_or_add_ind()
145
+ ind.firstLine = ind.hanging = None
146
+ if value is None:
147
+ return
148
+ elif value < 0:
149
+ ind.hanging = -value
150
+ else:
151
+ ind.firstLine = value
152
+
153
+ @property
154
+ def ind_left(self) -> Length | None:
155
+ """The value of `w:ind/@w:left` or |None| if not present."""
156
+ ind = self.ind
157
+ if ind is None:
158
+ return None
159
+ return ind.left
160
+
161
+ @ind_left.setter
162
+ def ind_left(self, value: Length | None):
163
+ if value is None and self.ind is None:
164
+ return
165
+ ind = self.get_or_add_ind()
166
+ ind.left = value
167
+
168
+ @property
169
+ def ind_right(self) -> Length | None:
170
+ """The value of `w:ind/@w:right` or |None| if not present."""
171
+ ind = self.ind
172
+ if ind is None:
173
+ return None
174
+ return ind.right
175
+
176
+ @ind_right.setter
177
+ def ind_right(self, value: Length | None):
178
+ if value is None and self.ind is None:
179
+ return
180
+ ind = self.get_or_add_ind()
181
+ ind.right = value
182
+
183
+ @property
184
+ def jc_val(self) -> WD_ALIGN_PARAGRAPH | None:
185
+ """Value of the `<w:jc>` child element or |None| if not present."""
186
+ return self.jc.val if self.jc is not None else None
187
+
188
+ @jc_val.setter
189
+ def jc_val(self, value):
190
+ if value is None:
191
+ self._remove_jc()
192
+ return
193
+ self.get_or_add_jc().val = value
194
+
195
+ @property
196
+ def keepLines_val(self):
197
+ """The value of `keepLines/@val` or |None| if not present."""
198
+ keepLines = self.keepLines
199
+ if keepLines is None:
200
+ return None
201
+ return keepLines.val
202
+
203
+ @keepLines_val.setter
204
+ def keepLines_val(self, value):
205
+ if value is None:
206
+ self._remove_keepLines()
207
+ else:
208
+ self.get_or_add_keepLines().val = value
209
+
210
+ @property
211
+ def keepNext_val(self):
212
+ """The value of `keepNext/@val` or |None| if not present."""
213
+ keepNext = self.keepNext
214
+ if keepNext is None:
215
+ return None
216
+ return keepNext.val
217
+
218
+ @keepNext_val.setter
219
+ def keepNext_val(self, value):
220
+ if value is None:
221
+ self._remove_keepNext()
222
+ else:
223
+ self.get_or_add_keepNext().val = value
224
+
225
+ @property
226
+ def pageBreakBefore_val(self):
227
+ """The value of `pageBreakBefore/@val` or |None| if not present."""
228
+ pageBreakBefore = self.pageBreakBefore
229
+ if pageBreakBefore is None:
230
+ return None
231
+ return pageBreakBefore.val
232
+
233
+ @pageBreakBefore_val.setter
234
+ def pageBreakBefore_val(self, value):
235
+ if value is None:
236
+ self._remove_pageBreakBefore()
237
+ else:
238
+ self.get_or_add_pageBreakBefore().val = value
239
+
240
+ @property
241
+ def spacing_after(self):
242
+ """The value of `w:spacing/@w:after` or |None| if not present."""
243
+ spacing = self.spacing
244
+ if spacing is None:
245
+ return None
246
+ return spacing.after
247
+
248
+ @spacing_after.setter
249
+ def spacing_after(self, value):
250
+ if value is None and self.spacing is None:
251
+ return
252
+ self.get_or_add_spacing().after = value
253
+
254
+ @property
255
+ def spacing_before(self):
256
+ """The value of `w:spacing/@w:before` or |None| if not present."""
257
+ spacing = self.spacing
258
+ if spacing is None:
259
+ return None
260
+ return spacing.before
261
+
262
+ @spacing_before.setter
263
+ def spacing_before(self, value):
264
+ if value is None and self.spacing is None:
265
+ return
266
+ self.get_or_add_spacing().before = value
267
+
268
+ @property
269
+ def spacing_line(self):
270
+ """The value of `w:spacing/@w:line` or |None| if not present."""
271
+ spacing = self.spacing
272
+ if spacing is None:
273
+ return None
274
+ return spacing.line
275
+
276
+ @spacing_line.setter
277
+ def spacing_line(self, value):
278
+ if value is None and self.spacing is None:
279
+ return
280
+ self.get_or_add_spacing().line = value
281
+
282
+ @property
283
+ def spacing_lineRule(self):
284
+ """The value of `w:spacing/@w:lineRule` as a member of the :ref:`WdLineSpacing`
285
+ enumeration.
286
+
287
+ Only the `MULTIPLE`, `EXACTLY`, and `AT_LEAST` members are used. It is the
288
+ responsibility of the client to calculate the use of `SINGLE`, `DOUBLE`, and
289
+ `MULTIPLE` based on the value of `w:spacing/@w:line` if that behavior is
290
+ desired.
291
+ """
292
+ spacing = self.spacing
293
+ if spacing is None:
294
+ return None
295
+ lineRule = spacing.lineRule
296
+ if lineRule is None and spacing.line is not None:
297
+ return WD_LINE_SPACING.MULTIPLE
298
+ return lineRule
299
+
300
+ @spacing_lineRule.setter
301
+ def spacing_lineRule(self, value):
302
+ if value is None and self.spacing is None:
303
+ return
304
+ self.get_or_add_spacing().lineRule = value
305
+
306
+ @property
307
+ def style(self) -> str | None:
308
+ """String contained in `./w:pStyle/@val`, or None if child is not present."""
309
+ pStyle = self.pStyle
310
+ if pStyle is None:
311
+ return None
312
+ return pStyle.val
313
+
314
+ @style.setter
315
+ def style(self, style: str | None):
316
+ """Set `./w:pStyle/@val` `style`, adding a new element if necessary.
317
+
318
+ If `style` is |None|, remove `./w:pStyle` when present.
319
+ """
320
+ if style is None:
321
+ self._remove_pStyle()
322
+ return
323
+ pStyle = self.get_or_add_pStyle()
324
+ pStyle.val = style
325
+
326
+ @property
327
+ def widowControl_val(self):
328
+ """The value of `widowControl/@val` or |None| if not present."""
329
+ widowControl = self.widowControl
330
+ if widowControl is None:
331
+ return None
332
+ return widowControl.val
333
+
334
+ @widowControl_val.setter
335
+ def widowControl_val(self, value):
336
+ if value is None:
337
+ self._remove_widowControl()
338
+ else:
339
+ self.get_or_add_widowControl().val = value
340
+
341
+
342
+ class CT_Spacing(BaseOxmlElement):
343
+ """``<w:spacing>`` element, specifying paragraph spacing attributes such as space
344
+ before and line spacing."""
345
+
346
+ after = OptionalAttribute("w:after", ST_TwipsMeasure)
347
+ before = OptionalAttribute("w:before", ST_TwipsMeasure)
348
+ line = OptionalAttribute("w:line", ST_SignedTwipsMeasure)
349
+ lineRule = OptionalAttribute("w:lineRule", WD_LINE_SPACING)
350
+
351
+
352
+ class CT_TabStop(BaseOxmlElement):
353
+ """`<w:tab>` element, representing an individual tab stop.
354
+
355
+ Overloaded to use for a tab-character in a run, which also uses the w:tab tag but
356
+ only needs a __str__ method.
357
+ """
358
+
359
+ val: WD_TAB_ALIGNMENT = RequiredAttribute( # pyright: ignore[reportAssignmentType]
360
+ "w:val", WD_TAB_ALIGNMENT
361
+ )
362
+ leader: WD_TAB_LEADER | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
363
+ "w:leader", WD_TAB_LEADER, default=WD_TAB_LEADER.SPACES
364
+ )
365
+ pos: Length = RequiredAttribute( # pyright: ignore[reportAssignmentType]
366
+ "w:pos", ST_SignedTwipsMeasure
367
+ )
368
+
369
+ def __str__(self) -> str:
370
+ """Text equivalent of a `w:tab` element appearing in a run.
371
+
372
+ Allows text of run inner-content to be accessed consistently across all text
373
+ inner-content.
374
+ """
375
+ return "\t"
376
+
377
+
378
+ class CT_TabStops(BaseOxmlElement):
379
+ """``<w:tabs>`` element, container for a sorted sequence of tab stops."""
380
+
381
+ tab = OneOrMore("w:tab", successors=())
382
+
383
+ def insert_tab_in_order(self, pos, align, leader):
384
+ """Insert a newly created `w:tab` child element in `pos` order."""
385
+ new_tab = self._new_tab()
386
+ new_tab.pos, new_tab.val, new_tab.leader = pos, align, leader
387
+ for tab in self.tab_lst:
388
+ if new_tab.pos < tab.pos:
389
+ tab.addprevious(new_tab)
390
+ return new_tab
391
+ self.append(new_tab)
392
+ return new_tab