Skip to content

Commit 931012d

Browse files
author
Steve Canny
committed
parfmt: add ParaFormat.first_line_indent getter
1 parent 0f58ff4 commit 931012d

File tree

4 files changed

+60
-1
lines changed

4 files changed

+60
-1
lines changed

docx/oxml/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ 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, CT_Spacing
139+
from .text.paragraph import CT_Ind, CT_Jc, CT_P, CT_PPr, CT_Spacing
140+
register_element_cls('w:ind', CT_Ind)
140141
register_element_cls('w:jc', CT_Jc)
141142
register_element_cls('w:p', CT_P)
142143
register_element_cls('w:pPr', CT_PPr)

docx/oxml/text/paragraph.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,22 @@
66

77
from ...enum.text import WD_ALIGN_PARAGRAPH, WD_LINE_SPACING
88
from ..ns import qn
9+
from ...shared import Length
910
from ..simpletypes import ST_SignedTwipsMeasure, ST_TwipsMeasure
1011
from ..xmlchemy import (
1112
BaseOxmlElement, OptionalAttribute, OxmlElement, RequiredAttribute,
1213
ZeroOrMore, ZeroOrOne
1314
)
1415

1516

17+
class CT_Ind(BaseOxmlElement):
18+
"""
19+
``<w:ind>`` element, specifying paragraph indentation.
20+
"""
21+
firstLine = OptionalAttribute('w:firstLine', ST_TwipsMeasure)
22+
hanging = OptionalAttribute('w:hanging', ST_TwipsMeasure)
23+
24+
1625
class CT_Jc(BaseOxmlElement):
1726
"""
1827
``<w:jc>`` element, specifying paragraph justification.
@@ -108,10 +117,29 @@ class CT_PPr(BaseOxmlElement):
108117
pStyle = ZeroOrOne('w:pStyle', successors=_tag_seq[1:])
109118
numPr = ZeroOrOne('w:numPr', successors=_tag_seq[7:])
110119
spacing = ZeroOrOne('w:spacing', successors=_tag_seq[22:])
120+
ind = ZeroOrOne('w:ind', successors=_tag_seq[23:])
111121
jc = ZeroOrOne('w:jc', successors=_tag_seq[27:])
112122
sectPr = ZeroOrOne('w:sectPr', successors=_tag_seq[35:])
113123
del _tag_seq
114124

125+
@property
126+
def first_line_indent(self):
127+
"""
128+
A |Length| value calculated from the values of `w:ind/@w:firstLine`
129+
and `w:ind/@w:hanging`. Returns |None| if the `w:ind` child is not
130+
present.
131+
"""
132+
ind = self.ind
133+
if ind is None:
134+
return None
135+
hanging = ind.hanging
136+
if hanging is not None:
137+
return Length(-hanging)
138+
firstLine = ind.firstLine
139+
if firstLine is None:
140+
return None
141+
return firstLine
142+
115143
@property
116144
def jc_val(self):
117145
"""

docx/text/paragraph.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,20 @@ def alignment(self, value):
158158
pPr = self._element.get_or_add_pPr()
159159
pPr.jc_val = value
160160

161+
@property
162+
def first_line_indent(self):
163+
"""
164+
|Length| value specifying the relative difference in indentation for
165+
the first line of the paragraph. A positive value causes the first
166+
line to be indented. A negative value produces a hanging indent.
167+
|None| indicates first line indentation is inherited from the style
168+
hierarchy.
169+
"""
170+
pPr = self._element.pPr
171+
if pPr is None:
172+
return None
173+
return pPr.first_line_indent
174+
161175
@property
162176
def line_spacing(self):
163177
"""

tests/text/test_paragraph.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,10 @@ def it_can_change_its_line_spacing_rule(self,
334334
paragraph_format.line_spacing_rule = value
335335
assert paragraph_format._element.xml == expected_xml
336336

337+
def it_knows_its_first_line_indent(self, first_indent_get_fixture):
338+
paragraph_format, expected_value = first_indent_get_fixture
339+
assert paragraph_format.first_line_indent == expected_value
340+
337341
# fixtures -------------------------------------------------------
338342

339343
@pytest.fixture(params=[
@@ -364,6 +368,18 @@ def alignment_set_fixture(self, request):
364368
expected_xml = xml(expected_cxml)
365369
return paragraph_format, value, expected_xml
366370

371+
@pytest.fixture(params=[
372+
('w:p', None),
373+
('w:p/w:pPr', None),
374+
('w:p/w:pPr/w:ind', None),
375+
('w:p/w:pPr/w:ind{w:firstLine=240}', Pt(12)),
376+
('w:p/w:pPr/w:ind{w:hanging=240}', Pt(-12)),
377+
])
378+
def first_indent_get_fixture(self, request):
379+
p_cxml, expected_value = request.param
380+
paragraph_format = ParagraphFormat(element(p_cxml))
381+
return paragraph_format, expected_value
382+
367383
@pytest.fixture(params=[
368384
('w:p', None),
369385
('w:p/w:pPr', None),

0 commit comments

Comments
 (0)