Files
Igor20264 516abe7b83
Python application / build (push) Has been cancelled
BigUpdate
2026-09-03 10:44:08 +03:00

71 lines
2.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Section-scoped and continuous object numbering."""
from collections import defaultdict
APPENDIX_LETTERS = "АБВГДЕЖИКЛМНПРСТУФХЦШЩЭЮЯ" # without Ё З Й О Ч Ь Ы Ъ
class Numberer:
"""Assigns object numbers.
* ``section`` (MIREA): ``1.1``, ``2.3`` or ``Б.1`` — counters reset per section/appendix.
* ``continuous`` (PIS_custom): ``1``, ``2``, ``3`` — сквозная нумерация по всему документу.
"""
def __init__(self, mode: str = "section"):
if mode not in ("section", "continuous"):
raise ValueError(f"Unknown numbering mode: {mode!r}")
self._mode = mode
self._section: int = 0
self._appendix: str | None = None
self._counters: dict[str, int] = defaultdict(int)
self._labels: dict[tuple[str, str], str] = {} # (category, unique_name) -> number string
@property
def mode(self) -> str:
return self._mode
@property
def section(self) -> int:
return self._section
@property
def appendix(self) -> str | None:
return self._appendix
def enter_section(self, section_number: int) -> None:
"""Start a numbered chapter (Heading 1 numbered)."""
self._section = section_number
self._appendix = None
if self._mode != "continuous":
self._counters.clear()
def enter_appendix(self, letter: str) -> None:
"""Start an appendix (letter А, Б, …)."""
self._appendix = letter
if self._mode != "continuous":
self._counters.clear()
def next_number(self, category: str, unique_name: str | None = None) -> str:
"""Allocate next number for category; optionally bind a label."""
self._counters[category] += 1
n = self._counters[category]
if self._mode == "continuous":
number = str(n)
elif self._appendix:
number = f"{self._appendix}.{n}"
elif self._section:
number = f"{self._section}.{n}"
else:
number = str(n)
if unique_name:
self._labels[(category, unique_name)] = number
return number
def resolve(self, category: str, unique_name: str) -> str | None:
return self._labels.get((category, unique_name))
def register_label(self, category: str, unique_name: str, number: str) -> None:
self._labels[(category, unique_name)] = number