Skip to content

Commit 801e3fb

Browse files
ondrej-111scanny
authored andcommitted
hdr: add _Header._has_header_part
1 parent 4ad97ed commit 801e3fb

File tree

5 files changed

+63
-4
lines changed

5 files changed

+63
-4
lines changed

docx/enum/section.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,33 @@
99
from .base import alias, XmlEnumeration, XmlMappedEnumMember
1010

1111

12+
@alias('WD_HEADER_FOOTER')
13+
class WD_HEADER_FOOTER_INDEX(XmlEnumeration):
14+
"""
15+
alias: **WD_HEADER_FOOTER**
16+
17+
Specifies one of the three possible header/footer definitions for a section.
18+
19+
For internal use only; not part of the python-docx API.
20+
"""
21+
22+
__ms_name__ = "WdHeaderFooterIndex"
23+
24+
__url__ = "https://docs.microsoft.com/en-us/office/vba/api/word.wdheaderfooterindex"
25+
26+
__members__ = (
27+
XmlMappedEnumMember(
28+
"PRIMARY", 1, "default", "Header for odd pages or all if no even header."
29+
),
30+
XmlMappedEnumMember(
31+
"FIRST_PAGE", 2, "first", "Header for first page of section."
32+
),
33+
XmlMappedEnumMember(
34+
"EVEN_PAGE", 3, "even", "Header for even pages of recto/verso section."
35+
),
36+
)
37+
38+
1239
@alias('WD_ORIENT')
1340
class WD_ORIENTATION(XmlEnumeration):
1441
"""

docx/oxml/section.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66

77
from copy import deepcopy
88

9-
from docx.enum.section import WD_ORIENTATION, WD_SECTION_START
9+
from docx.enum.section import WD_HEADER_FOOTER, WD_ORIENTATION, WD_SECTION_START
1010
from docx.oxml.simpletypes import ST_SignedTwipsMeasure, ST_TwipsMeasure
11-
from docx.oxml.xmlchemy import BaseOxmlElement, OptionalAttribute, ZeroOrOne
11+
from docx.oxml.xmlchemy import (
12+
BaseOxmlElement,
13+
OptionalAttribute,
14+
ZeroOrOne,
15+
)
1216

1317

1418
class CT_PageMar(BaseOxmlElement):
@@ -93,6 +97,15 @@ def footer(self, value):
9397
pgMar = self.get_or_add_pgMar()
9498
pgMar.footer = value
9599

100+
def get_headerReference(self, type_):
101+
"""Return headerReference element of *type_* or None if not present."""
102+
matching_headerReferences = self.xpath(
103+
"./w:headerReference[@w:type='%s']" % WD_HEADER_FOOTER.to_xml(type_)
104+
)
105+
if len(matching_headerReferences) == 0:
106+
return None
107+
return matching_headerReferences[0]
108+
96109
@property
97110
def gutter(self):
98111
"""

docx/section.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from collections import Sequence
88

99
from docx.blkcntnr import BlockItemContainer
10+
from docx.enum.section import WD_HEADER_FOOTER
1011
from docx.shared import lazyproperty
1112

1213

@@ -242,4 +243,5 @@ def is_linked_to_previous(self):
242243
@property
243244
def _has_header_part(self):
244245
"""True if a header is explicitly defined for this section."""
245-
raise NotImplementedError
246+
headerReference = self._sectPr.get_headerReference(WD_HEADER_FOOTER.PRIMARY)
247+
return False if headerReference is None else True

features/hdr-header-footer.feature

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ Feature: Header and footer behaviors
44
I need properties and methods on _Header and _Footer objects
55

66

7-
@wip
87
Scenario Outline: _Header.is_linked_to_previous getter
98
Given a _Header object <with-or-no> header definition as header
109
Then header.is_linked_to_previous is <value>

tests/test_section.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,26 @@ def it_knows_when_its_linked_to_the_previous_header(
370370

371371
assert is_linked is expected_value
372372

373+
def it_knows_when_it_has_a_header_part_to_help(self, has_header_part_fixture):
374+
sectPr, expected_value = has_header_part_fixture
375+
header = _Header(sectPr, None)
376+
377+
has_header_part = header._has_header_part
378+
379+
assert has_header_part is expected_value
380+
373381
# fixtures -------------------------------------------------------
374382

383+
@pytest.fixture(
384+
params=[
385+
("w:sectPr", False), ("w:sectPr/w:headerReference{w:type=default}", True)
386+
]
387+
)
388+
def has_header_part_fixture(self, request):
389+
sectPr_cxml, expected_value = request.param
390+
sectPr = element(sectPr_cxml)
391+
return sectPr, expected_value
392+
375393
@pytest.fixture(params=[(False, True), (True, False)])
376394
def is_linked_fixture(self, request):
377395
has_header_part, expected_value = request.param

0 commit comments

Comments
 (0)