Skip to content

Commit ce6afd4

Browse files
committed
hdr: add _Header._get_or_add_header_part()
1 parent e6d234c commit ce6afd4

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

docx/section.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,28 @@ def _get_or_add_header_part(self):
276276
created for the first section and returned.
277277
"""
278278
# ---note this method is called recursively to access inherited headers---
279-
raise NotImplementedError
279+
# ---case-1: header does not inherit---
280+
if self._has_header_part:
281+
return self._header_part
282+
prior_header = self._prior_header
283+
# ---case-2: header inherits and belongs to second-or-later section---
284+
if prior_header is not None:
285+
return prior_header._get_or_add_header_part()
286+
# ---case-3: header inherits, but is first header---
287+
return self._add_header_part()
280288

281289
@property
282290
def _has_header_part(self):
283291
"""True if a header is explicitly defined for this section."""
284292
headerReference = self._sectPr.get_headerReference(WD_HEADER_FOOTER.PRIMARY)
285293
return False if headerReference is None else True
294+
295+
@property
296+
def _header_part(self):
297+
"""|HeaderPart| object containing content of this header."""
298+
raise NotImplementedError
299+
300+
@property
301+
def _prior_header(self):
302+
"""|_Header| proxy on prior sectPr element or None if this is first section."""
303+
raise NotImplementedError

tests/test_section.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,47 @@ def it_provides_access_to_the_hdr_element_to_help(
422422
_get_or_add_header_part_.assert_called_once_with(header)
423423
assert hdr_elm is hdr
424424

425+
def it_gets_the_header_part_when_it_has_one(
426+
self, _has_header_part_prop_, _header_part_prop_, header_part_
427+
):
428+
_has_header_part_prop_.return_value = True
429+
_header_part_prop_.return_value = header_part_
430+
header = _Header(None, None)
431+
432+
header_part = header._get_or_add_header_part()
433+
434+
assert header_part is header_part_
435+
436+
def but_it_gets_the_prior_header_part_when_it_is_linked(
437+
self, _has_header_part_prop_, _prior_header_prop_, prior_header_, header_part_
438+
):
439+
_has_header_part_prop_.return_value = False
440+
_prior_header_prop_.return_value = prior_header_
441+
prior_header_._get_or_add_header_part.return_value = header_part_
442+
header = _Header(None, None)
443+
444+
header_part = header._get_or_add_header_part()
445+
446+
prior_header_._get_or_add_header_part.assert_called_once_with()
447+
assert header_part is header_part_
448+
449+
def and_it_adds_the_header_part_when_it_is_linked_and_the_first_section(
450+
self,
451+
_has_header_part_prop_,
452+
_prior_header_prop_,
453+
_add_header_part_,
454+
header_part_
455+
):
456+
_has_header_part_prop_.return_value = False
457+
_prior_header_prop_.return_value = None
458+
_add_header_part_.return_value = header_part_
459+
header = _Header(None, None)
460+
461+
header_part = header._get_or_add_header_part()
462+
463+
_add_header_part_.assert_called_once_with(header)
464+
assert header_part is header_part_
465+
425466
def it_knows_when_it_has_a_header_part_to_help(self, has_header_part_fixture):
426467
sectPr, expected_value = has_header_part_fixture
427468
header = _Header(sectPr, None)
@@ -484,3 +525,15 @@ def _has_header_part_prop_(self, request):
484525
@pytest.fixture
485526
def header_part_(self, request):
486527
return instance_mock(request, HeaderPart)
528+
529+
@pytest.fixture
530+
def _header_part_prop_(self, request):
531+
return property_mock(request, _Header, "_header_part")
532+
533+
@pytest.fixture
534+
def prior_header_(self, request):
535+
return instance_mock(request, _Header)
536+
537+
@pytest.fixture
538+
def _prior_header_prop_(self, request):
539+
return property_mock(request, _Header, "_prior_header")

0 commit comments

Comments
 (0)