+113
-1
@@ -1,9 +1,28 @@
|
||||
"""Page number start / offset helpers."""
|
||||
|
||||
from pathlib import Path
|
||||
from zipfile import ZipFile
|
||||
|
||||
from docx import Document
|
||||
from docx.oxml.ns import qn
|
||||
from lxml import etree
|
||||
|
||||
from md2gost.page_geometry import apply_page_number_start, set_section_page_start
|
||||
from md2gost.page_geometry import (
|
||||
apply_page_number_start,
|
||||
apply_section_geometry,
|
||||
clear_section_page_start,
|
||||
patch_docx_page_starts,
|
||||
set_section_page_start,
|
||||
)
|
||||
|
||||
_W = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"
|
||||
|
||||
|
||||
def _pg_start(section):
|
||||
pg = section._sectPr.find(qn("w:pgNumType"))
|
||||
if pg is None:
|
||||
return None
|
||||
return pg.get(qn("w:start"))
|
||||
|
||||
|
||||
def test_set_section_page_start():
|
||||
@@ -33,3 +52,96 @@ def test_apply_page_number_start_none_strips():
|
||||
apply_page_number_start(doc, None)
|
||||
pg = doc.sections[0]._sectPr.find(qn("w:pgNumType"))
|
||||
assert pg is None or pg.get(qn("w:start")) is None
|
||||
|
||||
|
||||
def test_apply_page_number_start_none_strips_all_four_sections():
|
||||
doc = Document()
|
||||
for _ in range(3):
|
||||
doc.add_section()
|
||||
for section in doc.sections:
|
||||
set_section_page_start(section, 1)
|
||||
assert all(_pg_start(s) == "1" for s in doc.sections)
|
||||
|
||||
apply_page_number_start(doc, None)
|
||||
assert all(_pg_start(s) is None for s in doc.sections)
|
||||
|
||||
|
||||
def test_apply_page_number_start_body_only_with_front():
|
||||
doc = Document()
|
||||
for _ in range(3):
|
||||
doc.add_section() # front + body + landscape + portrait = 4
|
||||
for section in doc.sections:
|
||||
set_section_page_start(section, 1)
|
||||
|
||||
apply_page_number_start(doc, 1, front_sections=1)
|
||||
assert _pg_start(doc.sections[0]) is None
|
||||
assert _pg_start(doc.sections[1]) == "1"
|
||||
assert _pg_start(doc.sections[2]) is None
|
||||
assert _pg_start(doc.sections[3]) is None
|
||||
|
||||
|
||||
def test_apply_section_geometry_strips_copied_start():
|
||||
doc = Document()
|
||||
set_section_page_start(doc.sections[0], 1)
|
||||
apply_section_geometry(doc.sections[0], landscape=True)
|
||||
assert _pg_start(doc.sections[0]) is None
|
||||
|
||||
|
||||
def test_clear_section_page_start_removes_empty_element():
|
||||
doc = Document()
|
||||
set_section_page_start(doc.sections[0], 1)
|
||||
clear_section_page_start(doc.sections[0])
|
||||
assert doc.sections[0]._sectPr.find(qn("w:pgNumType")) is None
|
||||
|
||||
|
||||
def test_patch_docx_page_starts_strips_and_restores(tmp_path: Path):
|
||||
doc = Document()
|
||||
for _ in range(3):
|
||||
doc.add_section()
|
||||
for section in doc.sections:
|
||||
set_section_page_start(section, 1)
|
||||
path = tmp_path / "pages.docx"
|
||||
doc.save(path)
|
||||
|
||||
patch_docx_page_starts(path, None)
|
||||
with ZipFile(path) as z:
|
||||
root = etree.fromstring(z.read("word/document.xml"))
|
||||
starts = [
|
||||
el.get(f"{_W}start")
|
||||
for el in root.findall(f".//{_W}pgNumType")
|
||||
]
|
||||
assert all(s is None for s in starts)
|
||||
|
||||
# Re-seed starts then restore body-only restart.
|
||||
doc2 = Document(str(path))
|
||||
for section in doc2.sections:
|
||||
set_section_page_start(section, 1)
|
||||
doc2.save(path)
|
||||
|
||||
patch_docx_page_starts(path, 2, front_sections=1)
|
||||
with ZipFile(path) as z:
|
||||
root = etree.fromstring(z.read("word/document.xml"))
|
||||
body = root.find(f"{_W}body")
|
||||
sects = []
|
||||
for child in body:
|
||||
if child.tag == f"{_W}sectPr":
|
||||
sects.append(child)
|
||||
continue
|
||||
if child.tag != f"{_W}p":
|
||||
continue
|
||||
p_pr = child.find(f"{_W}pPr")
|
||||
if p_pr is None:
|
||||
continue
|
||||
sect = p_pr.find(f"{_W}sectPr")
|
||||
if sect is not None:
|
||||
sects.append(sect)
|
||||
assert len(sects) == 4
|
||||
vals = [
|
||||
(s.find(f"{_W}pgNumType").get(f"{_W}start")
|
||||
if s.find(f"{_W}pgNumType") is not None else None)
|
||||
for s in sects
|
||||
]
|
||||
assert vals[0] is None
|
||||
assert vals[1] == "2"
|
||||
assert vals[2] is None
|
||||
assert vals[3] is None
|
||||
|
||||
Reference in New Issue
Block a user