Skip to content

Commit 4497b10

Browse files
author
Steve Canny
committed
parfmt: add ParagraphFormat.space_before getter
* refactor CT_PPr oxml declarations to use _tag_seq * remove now-obsolete CT_PPr._insert_pStyle() method
1 parent e8de57e commit 4497b10

File tree

4 files changed

+65
-15
lines changed

4 files changed

+65
-15
lines changed

docx/oxml/__init__.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,12 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
136136
register_element_cls('w:tr', CT_Row)
137137
register_element_cls('w:vMerge', CT_VMerge)
138138

139-
from .text.paragraph import CT_Jc, CT_P, CT_PPr
140-
register_element_cls('w:jc', CT_Jc)
141-
register_element_cls('w:p', CT_P)
142-
register_element_cls('w:pPr', CT_PPr)
143-
register_element_cls('w:pStyle', CT_String)
139+
from .text.paragraph import CT_Jc, CT_P, CT_PPr, CT_Spacing
140+
register_element_cls('w:jc', CT_Jc)
141+
register_element_cls('w:p', CT_P)
142+
register_element_cls('w:pPr', CT_PPr)
143+
register_element_cls('w:pStyle', CT_String)
144+
register_element_cls('w:spacing', CT_Spacing)
144145

145146
from .text.run import (
146147
CT_Br, CT_Fonts, CT_HpsMeasure, CT_R, CT_RPr, CT_Text, CT_Underline,

docx/oxml/text/paragraph.py

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
from ...enum.text import WD_ALIGN_PARAGRAPH
88
from ..ns import qn
9+
from ..simpletypes import ST_TwipsMeasure
910
from ..xmlchemy import (
10-
BaseOxmlElement, OxmlElement, RequiredAttribute, ZeroOrMore, ZeroOrOne
11+
BaseOxmlElement, OptionalAttribute, OxmlElement, RequiredAttribute,
12+
ZeroOrMore, ZeroOrOne
1113
)
1214

1315

@@ -92,7 +94,7 @@ class CT_PPr(BaseOxmlElement):
9294
"""
9395
``<w:pPr>`` element, containing the properties for a paragraph.
9496
"""
95-
__child_sequence__ = (
97+
_tag_seq = (
9698
'w:pStyle', 'w:keepNext', 'w:keepLines', 'w:pageBreakBefore',
9799
'w:framePr', 'w:widowControl', 'w:numPr', 'w:suppressLineNumbers',
98100
'w:pBdr', 'w:shd', 'w:tabs', 'w:suppressAutoHyphens', 'w:kinsoku',
@@ -103,14 +105,12 @@ class CT_PPr(BaseOxmlElement):
103105
'w:textboxTightWrap', 'w:outlineLvl', 'w:divId', 'w:cnfStyle',
104106
'w:rPr', 'w:sectPr', 'w:pPrChange'
105107
)
106-
pStyle = ZeroOrOne('w:pStyle')
107-
numPr = ZeroOrOne('w:numPr', successors=__child_sequence__[7:])
108-
jc = ZeroOrOne('w:jc', successors=__child_sequence__[27:])
109-
sectPr = ZeroOrOne('w:sectPr', successors=('w:pPrChange',))
110-
111-
def _insert_pStyle(self, pStyle):
112-
self.insert(0, pStyle)
113-
return pStyle
108+
pStyle = ZeroOrOne('w:pStyle', successors=_tag_seq[1:])
109+
numPr = ZeroOrOne('w:numPr', successors=_tag_seq[7:])
110+
spacing = ZeroOrOne('w:spacing', successors=_tag_seq[22:])
111+
jc = ZeroOrOne('w:jc', successors=_tag_seq[27:])
112+
sectPr = ZeroOrOne('w:sectPr', successors=_tag_seq[35:])
113+
del _tag_seq
114114

115115
@property
116116
def jc_val(self):
@@ -129,6 +129,16 @@ def jc_val(self, value):
129129
return
130130
self.get_or_add_jc().val = value
131131

132+
@property
133+
def spacing_before(self):
134+
"""
135+
The value of `w:spacing@w:before` or |None| if not present.
136+
"""
137+
spacing = self.spacing
138+
if spacing is None:
139+
return None
140+
return spacing.before
141+
132142
@property
133143
def style(self):
134144
"""
@@ -152,3 +162,11 @@ def style(self, style):
152162
return
153163
pStyle = self.get_or_add_pStyle()
154164
pStyle.val = style
165+
166+
167+
class CT_Spacing(BaseOxmlElement):
168+
"""
169+
``<w:spacing>`` element, specifying paragraph spacing attributes such as
170+
space before and line spacing.
171+
"""
172+
before = OptionalAttribute('w:before', ST_TwipsMeasure)

docx/text/paragraph.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,18 @@ def alignment(self):
154154
def alignment(self, value):
155155
pPr = self._element.get_or_add_pPr()
156156
pPr.jc_val = value
157+
158+
@property
159+
def space_before(self):
160+
"""
161+
|Length| value specifying the spacing to appear between this
162+
paragraph and the prior paragraph. |None| indicates this value is
163+
inherited from the style hierarchy. |Length| objects provide
164+
convenience properties, such as :attr:`~.Length.pt` and
165+
:attr:`~.Length.cm`, that allow easy conversion to various length
166+
units.
167+
"""
168+
pPr = self._element.pPr
169+
if pPr is None:
170+
return None
171+
return pPr.spacing_before

tests/text/test_paragraph.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from docx.oxml.text.paragraph import CT_P
1414
from docx.oxml.text.run import CT_R
1515
from docx.parts.document import DocumentPart
16+
from docx.shared import Pt
1617
from docx.text.paragraph import Paragraph, ParagraphFormat
1718
from docx.text.run import Run
1819

@@ -296,6 +297,10 @@ def it_can_change_its_alignment_value(self, alignment_set_fixture):
296297
paragraph_format.alignment = value
297298
assert paragraph_format._element.xml == expected_xml
298299

300+
def it_knows_its_space_before(self, space_before_get_fixture):
301+
paragraph_format, expected_value = space_before_get_fixture
302+
assert paragraph_format.space_before == expected_value
303+
299304
# fixtures -------------------------------------------------------
300305

301306
@pytest.fixture(params=[
@@ -325,3 +330,14 @@ def alignment_set_fixture(self, request):
325330
paragraph_format = ParagraphFormat(element(p_cxml))
326331
expected_xml = xml(expected_cxml)
327332
return paragraph_format, value, expected_xml
333+
334+
@pytest.fixture(params=[
335+
('w:p', None),
336+
('w:p/w:pPr', None),
337+
('w:p/w:pPr/w:spacing', None),
338+
('w:p/w:pPr/w:spacing{w:before=240}', Pt(12)),
339+
])
340+
def space_before_get_fixture(self, request):
341+
p_cxml, expected_value = request.param
342+
paragraph_format = ParagraphFormat(element(p_cxml))
343+
return paragraph_format, expected_value

0 commit comments

Comments
 (0)