Skip to content

Commit 77be8c9

Browse files
author
Steve Canny
committed
oxml: add CT_P.style setter
1 parent f7ade08 commit 77be8c9

3 files changed

Lines changed: 60 additions & 2 deletions

File tree

docx/oxml/text.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@ class CT_P(OxmlBaseElement):
2121
"""
2222
``<w:p>`` element, containing the properties and text for a paragraph.
2323
"""
24+
def __setattr__(self, attr, value):
25+
"""
26+
Implement setter side of properties. Filters ``__setattr__`` messages
27+
to ObjectifiedElement base class to intercept messages intended for
28+
custom property setters.
29+
"""
30+
if attr == 'style':
31+
self._set_style(value)
32+
else:
33+
super(CT_P, self).__setattr__(attr, value)
34+
2435
def add_r(self):
2536
"""
2637
Return a newly added CT_R (<w:r>) element.
@@ -53,7 +64,35 @@ def style(self):
5364
String contained in w:val attribute of <w:pPr><w:pStyle> child, or
5465
None if that element is not present.
5566
"""
56-
return self.pPr.style if hasattr(self, 'pPr') else None
67+
return self.pPr.style if self._has_pPr else None
68+
69+
def _get_or_add_pPr(self):
70+
"""
71+
Return the pPr child element of this <w:p> element, adding a new one
72+
if one is not present.
73+
"""
74+
if not self._has_pPr:
75+
self.insert(0, CT_PPr.new())
76+
return self.pPr
77+
78+
@property
79+
def _has_pPr(self):
80+
"""
81+
Return True if this <w:p> element has a <w:pPr> child element, False
82+
otherwise.
83+
"""
84+
return hasattr(self, 'pPr')
85+
86+
def _set_style(self, style):
87+
"""
88+
Set style of this <w:p> element to *style*. If *style* is None,
89+
remove the style element. If the pPr element is empty after the
90+
operation, remove it.
91+
"""
92+
pPr = self._get_or_add_pPr()
93+
pPr.style = style
94+
if pPr.countchildren() == 0:
95+
self.remove(pPr)
5796

5897

5998
class CT_PPr(OxmlBaseElement):

features/paragraph_style.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ Feature: Each paragraph has a read/write style
33
As an python-docx developer
44
I need to get and set the style of a paragraph
55

6-
@wip
76
Scenario: Set the style of a paragraph
87
Given a new document created from the default template
98
When I add a new paragraph to the body

tests/oxml/test_text.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,26 @@ def it_knows_its_paragraph_style(self):
4747
p = builder.with_nsdecls().element
4848
assert p.style == expected_value
4949

50+
def it_can_set_its_paragraph_style(self):
51+
# effectively an integration test with CT_PPr
52+
pPr = a_pPr().with_style('foobar')
53+
pPr2 = a_pPr().with_style('barfoo')
54+
cases = (
55+
(1, a_p(), None, a_p()),
56+
(2, a_p(), 'foobar', a_p().with_pPr(pPr)),
57+
(3, a_p().with_pPr(pPr), None, a_p()),
58+
(4, a_p().with_pPr(pPr), 'barfoo', a_p().with_pPr(pPr2)),
59+
)
60+
for case_nmbr, before_bldr, new_style, after_bldr in cases:
61+
print before_bldr.with_nsdecls().xml
62+
print 'case_nmbr, new_style => %d, %s' % (case_nmbr, new_style)
63+
p = before_bldr.with_nsdecls().element
64+
p.style = new_style
65+
expected_xml = after_bldr.with_nsdecls().xml
66+
print expected_xml
67+
print p.xml
68+
assert p.xml == expected_xml
69+
5070

5171
class DescribeCT_PPr(object):
5272

0 commit comments

Comments
 (0)