BigUpdate
Python application / build (push) Has been cancelled

This commit is contained in:
Igor20264
2026-09-03 10:44:08 +03:00
parent d2da20fdb2
commit 516abe7b83
177 changed files with 40178 additions and 2 deletions
+159
View File
@@ -0,0 +1,159 @@
"""Pre-assign section-scoped numbers and resolve @Type:label references."""
from __future__ import annotations
import re
from .numberer import Numberer, APPENDIX_LETTERS
from .renderable import Renderable
from .renderable.heading import Heading
from .renderable.requires_numbering import RequiresNumbering
from .renderable.equation import Equation
from .renderable.paragraph import Paragraph
from .renderable.caption import CaptionInfo
APPENDIX_RE = re.compile(r"^ПРИЛОЖЕНИЕ\s+([А-ЯA-Z])\b", re.IGNORECASE)
class LabelRegistry:
def __init__(self):
self._map: dict[tuple[str, str], str] = {}
def put(self, category: str, name: str, number: str):
self._map[(category.lower(), name)] = number
# also store without category for loose lookup
self._map[("*", name)] = f"{category} {number}"
def get(self, category: str, name: str) -> str | None:
return self._map.get((category.lower(), name))
def get_display(self, category: str, name: str) -> str | None:
n = self.get(category, name)
if n:
return f"{category} {n}"
# try Russian category aliases
aliases = {
"рисунок": "Рисунок",
"figure": "Рисунок",
"таблица": "Таблица",
"table": "Таблица",
"листинг": "Листинг",
"listing": "Листинг",
"формула": "Формула",
"formula": "Формула",
"equation": "Формула",
}
cat = aliases.get(category.lower(), category)
n = self.get(cat, name)
if n:
return f"{cat} {n}"
return None
def assign_numbers(renderables: list[Renderable],
numbered_equations: set[str] | None = None,
numbering_scope: str = "section") -> LabelRegistry:
"""Walk renderables once, set_number on objects, fill LabelRegistry."""
numbered_equations = numbered_equations or set()
numberer = Numberer(mode=numbering_scope)
registry = LabelRegistry()
section_count = 0
appendix_index = 0
for r in renderables:
if isinstance(r, Heading):
text = (r.text or "").strip()
upper = text.upper()
if r.level == 1 and r.is_numbered:
section_count += 1
numberer.enter_section(section_count)
m = APPENDIX_RE.match(upper)
if m:
numberer.enter_appendix(m.group(1).upper())
elif upper.startswith("ПРИЛОЖЕНИЕ"):
parts = upper.split()
if len(parts) >= 2 and parts[1] in APPENDIX_LETTERS:
numberer.enter_appendix(parts[1])
elif appendix_index < len(APPENDIX_LETTERS):
numberer.enter_appendix(APPENDIX_LETTERS[appendix_index])
appendix_index += 1
if isinstance(r, Equation):
label = r.unique_name
if r.needs_numbering or (label and label in numbered_equations):
r.enable_numbering()
num = numberer.next_number("Формула", label)
r.set_number(num)
if label:
registry.put("Формула", label, num)
continue
if isinstance(r, RequiresNumbering):
label = getattr(r, "unique_name", None)
num = numberer.next_number(r.numbering_category, label)
r.set_number(num)
if label:
registry.put(r.numbering_category, label, num)
# Diagram +listing → also number Листинг with same label
from .renderable.diagram import DiagramFigure
if isinstance(r, DiagramFigure) and r.listing is not None:
lnum = numberer.next_number("Листинг", label)
r.set_listing_number(lnum)
if label:
registry.put("Листинг", label, lnum)
# Images nested in paragraphs
if isinstance(r, Paragraph):
pass
# Images attached to paragraphs
if isinstance(r, Paragraph):
for img in getattr(r, "_images", []):
label = getattr(img, "unique_name", None)
num = numberer.next_number(img.numbering_category, label)
img.set_number(num)
if label:
registry.put(img.numbering_category, label, num)
return registry
def resolve_pending_in_renderables(renderables: list[Renderable], resolve_fn) -> None:
"""Resolve @Type:label placeholders in paragraphs, lists, headings and table cells."""
from .renderable.list import List as RList
from .renderable.table import Table
from .renderable.heading import Heading
def resolve_para(p):
if hasattr(p, "resolve_pending_refs"):
p.resolve_pending_refs(resolve_fn)
for r in renderables:
if isinstance(r, Paragraph):
resolve_para(r)
elif isinstance(r, Heading):
resolve_para(r)
elif isinstance(r, RList):
for p in getattr(r, "_paragraphs", []):
resolve_para(p)
elif isinstance(r, Table):
for row in getattr(r, "_rows", []):
for cell in row:
for p in cell:
resolve_para(p)
# Patch Paragraph to resolve references at run-creation time via module-level registry
_ACTIVE_REGISTRY: LabelRegistry | None = None
def set_active_registry(registry: LabelRegistry | None):
global _ACTIVE_REGISTRY
_ACTIVE_REGISTRY = registry
def resolve_reference(type_: str, name: str) -> str:
if _ACTIVE_REGISTRY is None:
return f"{type_}?"
display = _ACTIVE_REGISTRY.get_display(type_, name)
return display or f"{type_}?"