Skip to content

Commit 8097e39

Browse files
ondrej-111scanny
authored andcommitted
rfctr: Sections gets document_part
To access header and footer parts, Section will need the document part and the source for that will be its Sections parent proxy. Add document_part as construction parameter for Sections and modify tests to suit.
1 parent a93373a commit 8097e39

File tree

4 files changed

+67
-50
lines changed

4 files changed

+67
-50
lines changed

docx/document.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def save(self, path_or_stream):
137137
@property
138138
def sections(self):
139139
"""|Sections| object providing access to each section in this document."""
140-
return Sections(self._element)
140+
return Sections(self._element, self._part)
141141

142142
@property
143143
def settings(self):

docx/section.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,15 @@ class Sections(Sequence):
1313
Supports ``len()``, iteration, and indexed access.
1414
"""
1515

16-
def __init__(self, document_elm):
16+
def __init__(self, document_elm, document_part):
1717
super(Sections, self).__init__()
1818
self._document_elm = document_elm
19+
self._document_part = document_part
1920

2021
def __getitem__(self, key):
2122
if isinstance(key, slice):
22-
sectPr_lst = self._document_elm.sectPr_lst[key]
23-
return [Section(sectPr) for sectPr in sectPr_lst]
24-
sectPr = self._document_elm.sectPr_lst[key]
25-
return Section(sectPr)
23+
return [Section(sectPr) for sectPr in self._document_elm.sectPr_lst[key]]
24+
return Section(self._document_elm.sectPr_lst[key])
2625

2726
def __iter__(self):
2827
for sectPr in self._document_elm.sectPr_lst:
@@ -33,7 +32,10 @@ def __len__(self):
3332

3433

3534
class Section(object):
36-
"""Document section, providing access to section and page-setup settings."""
35+
"""Document section, providing access to section and page setup settings.
36+
37+
Also provides access to headers and footers.
38+
"""
3739

3840
def __init__(self, sectPr):
3941
super(Section, self).__init__()

tests/test_document.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@
2121
from docx.text.run import Run
2222

2323
from .unitutil.cxml import element, xml
24-
from .unitutil.mock import (
25-
class_mock, instance_mock, method_mock, property_mock
26-
)
24+
from .unitutil.mock import class_mock, instance_mock, method_mock, property_mock
2725

2826

2927
class DescribeDocument(object):
@@ -106,10 +104,14 @@ def it_provides_access_to_its_paragraphs(self, paragraphs_fixture):
106104
paragraphs = document.paragraphs
107105
assert paragraphs is paragraphs_
108106

109-
def it_provides_access_to_its_sections(self, sections_fixture):
110-
document, Sections_, sections_ = sections_fixture
107+
def it_provides_access_to_its_sections(self, document_part_, Sections_, sections_):
108+
document_elm = element('w:document')
109+
Sections_.return_value = sections_
110+
document = Document(document_elm, document_part_)
111+
111112
sections = document.sections
112-
Sections_.assert_called_once_with(document._element)
113+
114+
Sections_.assert_called_once_with(document_elm, document_part_)
113115
assert sections is sections_
114116

115117
def it_provides_access_to_its_settings(self, settings_fixture):
@@ -245,13 +247,6 @@ def save_fixture(self, document_part_):
245247
file_ = 'foobar.docx'
246248
return document, file_
247249

248-
@pytest.fixture
249-
def sections_fixture(self, Sections_, sections_):
250-
document_elm = element('w:document')
251-
document = Document(document_elm, None)
252-
Sections_.return_value = sections_
253-
return document, Sections_, sections_
254-
255250
@pytest.fixture
256251
def settings_fixture(self, document_part_, settings_):
257252
document = Document(None, document_part_)

tests/test_section.py

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,54 +7,74 @@
77
import pytest
88

99
from docx.enum.section import WD_ORIENT, WD_SECTION
10+
from docx.parts.document import DocumentPart
1011
from docx.section import Section, Sections
1112
from docx.shared import Inches
1213

1314
from .unitutil.cxml import element, xml
15+
from .unitutil.mock import call, class_mock, instance_mock
1416

1517

1618
class DescribeSections(object):
1719

18-
def it_knows_how_many_sections_it_contains(self, len_fixture):
19-
sections, expected_len = len_fixture
20-
assert len(sections) == expected_len
20+
def it_knows_how_many_sections_it_contains(self):
21+
sections = Sections(
22+
element("w:document/w:body/(w:p/w:pPr/w:sectPr, w:sectPr)"), None
23+
)
24+
assert len(sections) == 2
2125

22-
def it_can_iterate_over_its_Section_instances(self, iter_fixture):
23-
sections, expected_count = iter_fixture
24-
section_count = 0
25-
for section in sections:
26-
section_count += 1
27-
assert isinstance(section, Section)
28-
assert section_count == expected_count
26+
def it_can_iterate_over_its_Section_instances(self, Section_, section_):
27+
document_elm = element("w:document/w:body/(w:p/w:pPr/w:sectPr, w:sectPr)")
28+
sectPrs = document_elm.xpath("//w:sectPr")
29+
Section_.return_value = section_
30+
sections = Sections(document_elm, None)
2931

30-
def it_can_access_its_Section_instances_by_index(self, index_fixture):
31-
sections, indicies = index_fixture
32-
assert len(sections[0:2]) == 2
33-
for index in indicies:
34-
assert isinstance(sections[index], Section)
32+
section_lst = [s for s in sections]
3533

36-
# fixtures -------------------------------------------------------
34+
assert Section_.call_args_list == [call(sectPrs[0]), call(sectPrs[1])]
35+
assert section_lst == [section_, section_]
3736

38-
@pytest.fixture
39-
def index_fixture(self, document_elm):
40-
sections = Sections(document_elm)
41-
return sections, [0, 1]
37+
def it_can_access_its_Section_instances_by_index(self, Section_, section_):
38+
document_elm = element(
39+
"w:document/w:body/(w:p/w:pPr/w:sectPr,w:p/w:pPr/w:sectPr,w:sectPr)"
40+
)
41+
sectPrs = document_elm.xpath("//w:sectPr")
42+
Section_.return_value = section_
43+
sections = Sections(document_elm, None)
4244

43-
@pytest.fixture
44-
def iter_fixture(self, document_elm):
45-
sections = Sections(document_elm)
46-
return sections, 2
45+
section_lst = [sections[idx] for idx in range(3)]
4746

48-
@pytest.fixture
49-
def len_fixture(self, document_elm):
50-
sections = Sections(document_elm)
51-
return sections, 2
47+
assert Section_.call_args_list == [
48+
call(sectPrs[0]), call(sectPrs[1]), call(sectPrs[2])
49+
]
50+
assert section_lst == [section_, section_, section_]
51+
52+
def it_can_access_its_Section_instances_by_slice(self, Section_, section_):
53+
document_elm = element(
54+
"w:document/w:body/(w:p/w:pPr/w:sectPr,w:p/w:pPr/w:sectPr,w:sectPr)"
55+
)
56+
sectPrs = document_elm.xpath("//w:sectPr")
57+
Section_.return_value = section_
58+
sections = Sections(document_elm, None)
59+
60+
section_lst = sections[1:9]
61+
62+
assert Section_.call_args_list == [call(sectPrs[1]), call(sectPrs[2])]
63+
assert section_lst == [section_, section_]
5264

5365
# fixture components ---------------------------------------------
5466

5567
@pytest.fixture
56-
def document_elm(self):
57-
return element('w:document/w:body/(w:p/w:pPr/w:sectPr, w:sectPr)')
68+
def document_part_(self, request):
69+
return instance_mock(request, DocumentPart)
70+
71+
@pytest.fixture
72+
def Section_(self, request):
73+
return class_mock(request, "docx.section.Section")
74+
75+
@pytest.fixture
76+
def section_(self, request):
77+
return instance_mock(request, Section)
5878

5979

6080
class DescribeSection(object):

0 commit comments

Comments
 (0)