Skip to content

Commit 65db853

Browse files
author
Steve Canny
committed
para: add Paragraph.insert_paragraph_before()
1 parent 6c122c0 commit 65db853

4 files changed

Lines changed: 57 additions & 6 deletions

File tree

docx/oxml/text.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from .ns import qn
1010
from .simpletypes import ST_BrClear, ST_BrType
1111
from .xmlchemy import (
12-
BaseOxmlElement, OptionalAttribute, ZeroOrMore, ZeroOrOne
12+
BaseOxmlElement, OptionalAttribute, OxmlElement, ZeroOrMore, ZeroOrOne
1313
)
1414

1515

@@ -32,6 +32,14 @@ def _insert_pPr(self, pPr):
3232
self.insert(0, pPr)
3333
return pPr
3434

35+
def add_p_before(self):
36+
"""
37+
Return a new ``<w:p>`` element inserted directly prior to this one.
38+
"""
39+
new_p = OxmlElement('w:p')
40+
self.addprevious(new_p)
41+
return new_p
42+
3543
def set_sectPr(self, sectPr):
3644
"""
3745
Unconditionally replace or add *sectPr* as a grandchild in the

docx/text.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@ def add_run(self, text=None, style=None):
7171
run.style = style
7272
return run
7373

74+
def insert_paragraph_before(self, text=None, style=None):
75+
"""
76+
Return a newly created paragraph, inserted directly before this
77+
paragraph, and having its text set to *text* and style set to
78+
*style*.
79+
"""
80+
p = self._p.add_p_before()
81+
paragraph = Paragraph(p)
82+
if text:
83+
paragraph.add_run(text)
84+
if style is not None:
85+
paragraph.style = style
86+
return paragraph
87+
7488
@property
7589
def runs(self):
7690
"""

features/par-insert-paragraph.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Feature: Insert a paragraph before or after a paragraph
44
I need a way to insert a paragraph relative to another paragraph
55

66

7-
@wip
87
Scenario: Add a new paragraph above an existing paragraph
98
Given a document containing three paragraphs
109
When I insert a paragraph above the second paragraph

tests/test_text.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@
99
)
1010

1111
from docx.enum.text import WD_BREAK, WD_UNDERLINE
12+
from docx.oxml.ns import qn
1213
from docx.oxml.text import CT_P, CT_R
1314
from docx.text import Paragraph, Run
1415

1516
import pytest
1617

18+
from .oxml.parts.unitdata.document import a_body
1719
from .oxml.unitdata.text import (
18-
a_b, a_bCs, a_br, a_caps, a_cs, a_dstrike, a_p, a_shadow, a_smallCaps,
19-
a_snapToGrid, a_specVanish, a_strike, a_t, a_u, a_vanish, a_webHidden,
20-
an_emboss, an_i, an_iCs, an_imprint, an_oMath, a_noProof, an_outline,
21-
an_r, an_rPr, an_rStyle, an_rtl
20+
a_b, a_bCs, a_br, a_caps, a_cs, a_dstrike, a_p, a_pPr, a_pStyle,
21+
a_shadow, a_smallCaps, a_snapToGrid, a_specVanish, a_strike, a_t, a_u,
22+
a_vanish, a_webHidden, an_emboss, an_i, an_iCs, an_imprint, an_oMath,
23+
a_noProof, an_outline, an_r, an_rPr, an_rStyle, an_rtl
2224
)
2325
from .unitutil import call, class_mock, instance_mock, Mock
2426

@@ -62,6 +64,14 @@ def it_knows_the_text_it_contains(self, text_prop_fixture):
6264
p, expected_text = text_prop_fixture
6365
assert p.text == expected_text
6466

67+
def it_can_insert_a_paragraph_before_itself(self, insert_before_fixture):
68+
paragraph, text, style, body, expected_xml = insert_before_fixture
69+
new_paragraph = paragraph.insert_paragraph_before(text, style)
70+
assert isinstance(new_paragraph, Paragraph)
71+
assert new_paragraph.text == text
72+
assert new_paragraph.style == style
73+
assert body.xml == expected_xml
74+
6575
# fixtures -------------------------------------------------------
6676

6777
@pytest.fixture(params=[
@@ -79,6 +89,26 @@ def add_run_fixture(self, request, paragraph):
7989
expected_xml = a_p().with_nsdecls().with_child(r_bldr).xml()
8090
return paragraph, text, style, expected_xml
8191

92+
@pytest.fixture
93+
def insert_before_fixture(self):
94+
text, style = 'foobar', 'Heading1'
95+
body = (
96+
a_body().with_nsdecls().with_child(
97+
a_p())
98+
).element
99+
p = body.find(qn('w:p'))
100+
paragraph = Paragraph(p)
101+
expected_xml = (
102+
a_body().with_nsdecls().with_child(
103+
a_p().with_child(
104+
a_pPr().with_child(
105+
a_pStyle().with_val(style))).with_child(
106+
an_r().with_child(
107+
a_t().with_text(text)))).with_child(
108+
a_p())
109+
).xml()
110+
return paragraph, text, style, body, expected_xml
111+
82112
# fixture components ---------------------------------------------
83113

84114
@pytest.fixture

0 commit comments

Comments
 (0)