v0.6.0 BigUpdate
Example document / build (push) Has been cancelled
Python application / build (push) Has been cancelled

This commit is contained in:
Igor20264
2026-10-20 11:38:06 +03:00
parent daa84f8bce
commit 8223e0ac14
77 changed files with 12158 additions and 117 deletions
+118
View File
@@ -330,3 +330,121 @@ def test_landscape_listing_deferred_after_section(tmp_path, monkeypatch):
texts = [p.text for p in doc.paragraphs]
listing_caps = [t for t in texts if t.startswith("Листинг")]
assert listing_caps, f"no listing caption in {texts!r}"
def _empty_section_break_pairs(doc) -> int:
"""Pairs of next-page breaks with no body content between them (a blank page)."""
children = list(doc.element.body)
pairs = 0
prev_empty_break = False
for child in children:
if child.tag == f"{W_NS}sectPr":
continue
is_break = _is_break_paragraph(child)
if is_break:
if prev_empty_break:
pairs += 1
prev_empty_break = True
continue
prev_empty_break = False
return pairs
def _fresh_doc():
doc = Document(os.path.join(package_dir(), "Template.docx"))
body = doc._body._element
for child in list(body):
if child.tag.endswith("}sectPr"):
continue
body.remove(child)
return doc
def _small_table(doc, name: str, *, landscape: bool) -> Table:
table = Table(doc._body, 2, 2, CaptionInfo(name, name, landscape=landscape))
for r in range(2):
for c in range(2):
table.add_paragraph_to_cell(r, c).add_run(f"{name}{r}{c}")
return table
def test_consecutive_landscape_tables_share_section():
"""Two +landscape tables in a row must not put a blank portrait page between them."""
doc = _fresh_doc()
Renderer(doc, skip_numbering=True).process([
_small_table(doc, "A", landscape=True),
_small_table(doc, "B", landscape=True),
])
assert _empty_section_break_pairs(doc) == 0
assert [s.orientation for s in doc.sections] == [
WD_ORIENT.PORTRAIT,
WD_ORIENT.LANDSCAPE,
WD_ORIENT.PORTRAIT,
]
assert doc.sections[-1].orientation == WD_ORIENT.PORTRAIT
def test_landscape_then_text_then_landscape_returns_to_portrait():
doc = _fresh_doc()
from md2gost.renderable.paragraph import Paragraph
middle = Paragraph(doc._body)
middle.add_run("Между таблицами.")
Renderer(doc, skip_numbering=True).process([
_small_table(doc, "A", landscape=True),
middle,
_small_table(doc, "B", landscape=True),
])
assert _empty_section_break_pairs(doc) == 0
assert [s.orientation for s in doc.sections] == [
WD_ORIENT.PORTRAIT,
WD_ORIENT.LANDSCAPE,
WD_ORIENT.PORTRAIT,
WD_ORIENT.LANDSCAPE,
WD_ORIENT.PORTRAIT,
]
def test_consecutive_landscape_photos_share_section(tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
png = tmp_path / "photo.png"
PILImage.new("RGB", (80, 40), color=(0, 128, 255)).save(png)
os.environ["WORKING_DIR"] = str(tmp_path)
from md2gost.renderable.paragraph import Paragraph
doc = _fresh_doc()
first = Paragraph(doc._body)
first.add_image(str(png), CaptionInfo("p1", "Фото 1", landscape=True))
second = Paragraph(doc._body)
second.add_image(str(png), CaptionInfo("p2", "Фото 2", landscape=True))
Renderer(doc, skip_numbering=True).process([first, second])
assert _empty_section_break_pairs(doc) == 0
assert [s.orientation for s in doc.sections] == [
WD_ORIENT.PORTRAIT,
WD_ORIENT.LANDSCAPE,
WD_ORIENT.PORTRAIT,
]
def test_second_landscape_photo_is_not_shrunk_into_leftover(tmp_path, monkeypatch):
"""A follower that does not fit the rest of the page keeps its page size."""
monkeypatch.chdir(tmp_path)
png = tmp_path / "tall.png"
PILImage.new("RGB", (2000, 2000), color=(0, 128, 255)).save(png)
os.environ["WORKING_DIR"] = str(tmp_path)
doc = _fresh_doc()
first = Image(doc._body, str(png), CaptionInfo("p1", "Фото 1", landscape=True))
second = Image(doc._body, str(png), CaptionInfo("p2", "Фото 2", landscape=True))
Renderer(doc, skip_numbering=True).process([first, second])
A = "{http://schemas.openxmlformats.org/drawingml/2006/main}"
heights = []
for child in doc.element.body:
ext = child.find(f".//{A}ext")
if ext is not None:
heights.append(int(ext.get("cy")))
assert len(heights) == 2
assert heights[1] > heights[0] * 0.9