Skip to content

Commit 3119a45

Browse files
author
Steve Canny
committed
style: add _ParaStyle.next_paragraph_style getter
* add a more descriptive __repr__() for _ParagraphStyle
1 parent bbedd39 commit 3119a45

File tree

5 files changed

+64
-1
lines changed

5 files changed

+64
-1
lines changed

docx/oxml/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def OxmlElement(nsptag_str, attrs=None, nsdecls=None):
119119
register_element_cls('w:locked', CT_OnOff)
120120
register_element_cls('w:lsdException', CT_LsdException)
121121
register_element_cls('w:name', CT_String)
122+
register_element_cls('w:next', CT_String)
122123
register_element_cls('w:qFormat', CT_OnOff)
123124
register_element_cls('w:semiHidden', CT_OnOff)
124125
register_element_cls('w:style', CT_Style)

docx/oxml/styles.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class CT_Style(BaseOxmlElement):
118118
)
119119
name = ZeroOrOne('w:name', successors=_tag_seq[1:])
120120
basedOn = ZeroOrOne('w:basedOn', successors=_tag_seq[3:])
121+
next = ZeroOrOne('w:next', successors=_tag_seq[4:])
121122
uiPriority = ZeroOrOne('w:uiPriority', successors=_tag_seq[8:])
122123
semiHidden = ZeroOrOne('w:semiHidden', successors=_tag_seq[9:])
123124
unhideWhenUsed = ZeroOrOne('w:unhideWhenUsed', successors=_tag_seq[10:])
@@ -204,6 +205,19 @@ def name_val(self, value):
204205
name = self._add_name()
205206
name.val = value
206207

208+
@property
209+
def next_style(self):
210+
"""
211+
Sibling CT_Style element identified by the value of `w:name/@w:val`
212+
or |None| if no value is present or no style with that style id
213+
is found.
214+
"""
215+
next = self.next
216+
if next is None:
217+
return None
218+
styles = self.getparent()
219+
return styles.get_by_id(next.val) # None if not found
220+
207221
@property
208222
def qFormat_val(self):
209223
"""

docx/styles/style.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,25 @@ class _ParagraphStyle(_CharacterStyle):
229229

230230
__slots__ = ()
231231

232+
def __repr__(self):
233+
return '_ParagraphStyle(\'%s\') id: %s' % (self.name, id(self))
234+
235+
@property
236+
def next_paragraph_style(self):
237+
"""
238+
|_ParagraphStyle| object representing the style to be applied
239+
automatically to a new paragraph inserted after a paragraph of this
240+
style. Returns self if no next paragraph style is defined. Assigning
241+
|None| or *self* removes the setting such that new paragraphs are
242+
created using this same style.
243+
"""
244+
next_style_elm = self._element.next_style
245+
if next_style_elm is None:
246+
return self
247+
if next_style_elm.type != WD_STYLE_TYPE.PARAGRAPH:
248+
return self
249+
return StyleFactory(next_style_elm)
250+
232251
@property
233252
def paragraph_format(self):
234253
"""

features/sty-style-props.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ Feature: Get and set style properties
8181
Then style.name is the new name
8282

8383

84-
@wip
8584
Scenario Outline: Get next paragraph style
8685
Given a style having next paragraph style set to <setting>
8786
Then style.next_paragraph_style is <value>

tests/styles/test_style.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,10 @@ def StyleFactory_(self, request):
464464

465465
class Describe_ParagraphStyle(object):
466466

467+
def it_knows_its_next_paragraph_style(self, next_get_fixture):
468+
style, expected_value = next_get_fixture
469+
assert style.next_paragraph_style == expected_value
470+
467471
def it_provides_access_to_its_paragraph_format(self, parfmt_fixture):
468472
style, ParagraphFormat_, paragraph_format_ = parfmt_fixture
469473
paragraph_format = style.paragraph_format
@@ -472,6 +476,32 @@ def it_provides_access_to_its_paragraph_format(self, parfmt_fixture):
472476

473477
# fixtures -------------------------------------------------------
474478

479+
@pytest.fixture(params=[
480+
('H1', 'Body'),
481+
('H2', 'H2'),
482+
('Body', 'Body'),
483+
('Foo', 'Foo'),
484+
])
485+
def next_get_fixture(self, request):
486+
style_name, next_style_name = request.param
487+
styles = element(
488+
'w:styles/('
489+
'w:style{w:type=paragraph,w:styleId=H1}/w:next{w:val=Body},'
490+
'w:style{w:type=paragraph,w:styleId=H2}/w:next{w:val=Char},'
491+
'w:style{w:type=paragraph,w:styleId=Body},'
492+
'w:style{w:type=paragraph,w:styleId=Foo}/w:next{w:val=Bar},'
493+
'w:style{w:type=character,w:styleId=Char})'
494+
)
495+
style_names = ['H1', 'H2', 'Body', 'Foo', 'Char']
496+
style_elm = styles[style_names.index(style_name)]
497+
next_style_elm = styles[style_names.index(next_style_name)]
498+
style = _ParagraphStyle(style_elm)
499+
if style_name == 'H1':
500+
next_style = _ParagraphStyle(next_style_elm)
501+
else:
502+
next_style = style
503+
return style, next_style
504+
475505
@pytest.fixture
476506
def parfmt_fixture(self, ParagraphFormat_, paragraph_format_):
477507
style = _ParagraphStyle(element('w:style'))

0 commit comments

Comments
 (0)