Compare commits
No commits in common. "main" and "statements-library-packaging-checks" have entirely different histories.
main
...
statements
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,13 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
## 0.1.2 — 2026-10-30
|
|
||||||
|
|
||||||
- Добавлен маркер PEP 561 `arm_statements/py.typed` в дистрибутив: аннотации доступны потребителям библиотеки.
|
|
||||||
- `statements_version()` получает версию только из `importlib.metadata` дистрибутива `pylib-ai-arm-statements`; при отсутствии метаданных возвращает `None`. Параметр пути и чтение `arm_statements/VERSION` удалены.
|
|
||||||
- `statement_code_orders.yaml` обновлён байтовой копией `docs/contracts/statement-code-orders.yaml`: комментарии описывают библиотечную поставку без `sync-statements`.
|
|
||||||
- README приведён к установке библиотеки; changelog и маркер типов включены в исходный дистрибутив.
|
|
||||||
|
|
||||||
## 0.1.1
|
|
||||||
|
|
||||||
- Общий код нормализации ББ/ОФР оформлен как устанавливаемый пакет `pylib-ai-arm-statements` с импортом `arm_statements` и YAML-словарями.
|
|
||||||
- Добавлены проверки упаковки, тесты и настройки Ruff/mypy.
|
|
||||||
@ -3,6 +3,3 @@ include VERSION
|
|||||||
include requirements.txt
|
include requirements.txt
|
||||||
recursive-include arm_statements *.py
|
recursive-include arm_statements *.py
|
||||||
recursive-include arm_statements/rules *.yaml
|
recursive-include arm_statements/rules *.yaml
|
||||||
|
|
||||||
include CHANGELOG.md
|
|
||||||
include arm_statements/py.typed
|
|
||||||
|
|||||||
11
README.md
11
README.md
@ -1,11 +1,10 @@
|
|||||||
# arm-statements
|
# arm-statements
|
||||||
|
|
||||||
Общий код нормализации форм ББ/ОФР (пакет `arm_statements`) для tabular-parser, scan-gateway и arm-core.
|
Общий код нормализации форм ББ/ОФР (пакет `arm_statements`) для tabular-parser, scan-gateway и arm-core.
|
||||||
Устанавливается как библиотека `pylib_ai_arm_statements` из локального checkout или собранного wheel; в PyPI не публикуется.
|
Раскладывается копией в `api/arm_statements/` хостов скриптом `sync-statements` из arm-ka-docs.
|
||||||
Спека: arm-ka-docs, `openspec/changes/unified-statement-normalization/`.
|
Спека: arm-ka-docs, `openspec/changes/unified-statement-normalization/`.
|
||||||
|
|
||||||
В сервисах библиотека устанавливается через `make venv` / `make install`; исходники и словари изменяются в этом репозитории.
|
Копия раскладывается `make -C docs sync-statements`; прямые правки копии в хостах запрещены.
|
||||||
История выпусков — [CHANGELOG.md](CHANGELOG.md).
|
|
||||||
|
|
||||||
## Как проверить
|
## Как проверить
|
||||||
|
|
||||||
@ -141,7 +140,7 @@ make_warning(code: str, message: str, rules: Rules, *, line_refs: Sequence[str]
|
|||||||
# SHEET_NOT_JOINED, SHEET_OTHER только через неё
|
# SHEET_NOT_JOINED, SHEET_OTHER только через неё
|
||||||
to_jsonable(obj: object) -> Any # dataclass пакета → json-совместимое значение (golden)
|
to_jsonable(obj: object) -> Any # dataclass пакета → json-совместимое значение (golden)
|
||||||
candidate_from_dict(data: Mapping[str, Any]) -> FormCandidate # обратная для кандидата
|
candidate_from_dict(data: Mapping[str, Any]) -> FormCandidate # обратная для кандидата
|
||||||
statements_version() -> str | None # importlib.metadata: версия установленного дистрибутива
|
statements_version(path: Path | None = None) -> str | None # содержимое api/arm_statements/VERSION копии
|
||||||
load_rules(directory: Path | None = None) -> Rules # RulesError при ошибке словаря
|
load_rules(directory: Path | None = None) -> Rules # RulesError при ошибке словаря
|
||||||
default_rules() -> Rules # кэш словарей пакета
|
default_rules() -> Rules # кэш словарей пакета
|
||||||
```
|
```
|
||||||
@ -239,8 +238,8 @@ Rules.warnings -> Mapping[str, WarningRule] # WarningRule(code, severit
|
|||||||
|
|
||||||
## Как менять словари
|
## Как менять словари
|
||||||
|
|
||||||
Словари пакета — данные в `arm_statements/rules/*.yaml`, правка идёт PR сюда, затем выпускается новая версия библиотеки
|
Словари пакета — данные в `arm_statements/rules/*.yaml`, правка идёт PR сюда, затем `make -C docs sync-statements` в
|
||||||
и обновляется зависимость в сервисах («сначала пакет»).
|
хостах («сначала пакет»).
|
||||||
|
|
||||||
- `statement_code_orders.yaml` — **байтовая копия** `docs/contracts/statement-code-orders.yaml` (arm-ka-docs); руками не
|
- `statement_code_orders.yaml` — **байтовая копия** `docs/contracts/statement-code-orders.yaml` (arm-ka-docs); руками не
|
||||||
правится. Перечень кодов меняется только PR в docs, затем копия переносится сюда без изменений.
|
правится. Перечень кодов меняется только PR в docs, затем копия переносится сюда без изменений.
|
||||||
|
|||||||
@ -1,10 +1,20 @@
|
|||||||
"""Версия установленного дистрибутива библиотеки."""
|
"""Версия копии из VERSION или метаданных установленного пакета."""
|
||||||
|
|
||||||
from importlib.metadata import PackageNotFoundError, version
|
from importlib.metadata import PackageNotFoundError, version
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
_DEFAULT_MARKER = Path(__file__).parent / "VERSION"
|
||||||
|
|
||||||
|
|
||||||
def statements_version() -> str | None:
|
def statements_version(path: Path | None = None) -> str | None:
|
||||||
"""Вернуть версию установленного пакета или None, если метаданные недоступны."""
|
"""Прочитать VERSION; для установленного пакета использовать версию дистрибутива."""
|
||||||
|
marker = _DEFAULT_MARKER if path is None else path
|
||||||
|
if marker.is_file():
|
||||||
|
text = marker.read_text(encoding="utf-8").strip()
|
||||||
|
if text or path is not None:
|
||||||
|
return text or None
|
||||||
|
if path is not None:
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
return version("pylib-ai-arm-statements")
|
return version("pylib-ai-arm-statements")
|
||||||
except PackageNotFoundError:
|
except PackageNotFoundError:
|
||||||
|
|||||||
@ -1,23 +1,74 @@
|
|||||||
from importlib.metadata import PackageNotFoundError
|
from importlib.metadata import PackageNotFoundError
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import arm_statements.version as version_module
|
import arm_statements.version as version_module
|
||||||
from arm_statements.version import statements_version
|
from arm_statements.version import statements_version
|
||||||
|
|
||||||
|
FULL_HASH = "abc1234def5678abc1234def5678abc1234def56"
|
||||||
def test_version_from_distribution(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
||||||
def distribution_version(name: str) -> str:
|
|
||||||
assert name == "pylib-ai-arm-statements"
|
|
||||||
return "0.1.2"
|
|
||||||
|
|
||||||
monkeypatch.setattr(version_module, "version", distribution_version)
|
|
||||||
assert statements_version() == "0.1.2"
|
|
||||||
|
|
||||||
|
|
||||||
def test_version_without_metadata_is_none(monkeypatch: pytest.MonkeyPatch) -> None:
|
def test_version_absent_file_is_none(tmp_path: Path) -> None:
|
||||||
|
assert statements_version(tmp_path / "VERSION") is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_version_read_from_file(tmp_path: Path) -> None:
|
||||||
|
marker = tmp_path / "VERSION"
|
||||||
|
marker.write_text(f"{FULL_HASH}\n", encoding="utf-8")
|
||||||
|
assert statements_version(marker) == FULL_HASH
|
||||||
|
|
||||||
|
|
||||||
|
def test_version_empty_file_is_none(tmp_path: Path) -> None:
|
||||||
|
marker = tmp_path / "VERSION"
|
||||||
|
marker.write_text(" \n", encoding="utf-8")
|
||||||
|
assert statements_version(marker) is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("contents", [None, " \n"])
|
||||||
|
def test_default_marker_falls_back_to_distribution(
|
||||||
|
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, contents: str | None
|
||||||
|
) -> None:
|
||||||
|
marker = tmp_path / "VERSION"
|
||||||
|
if contents is not None:
|
||||||
|
marker.write_text(contents, encoding="utf-8")
|
||||||
|
monkeypatch.setattr(version_module, "_DEFAULT_MARKER", marker)
|
||||||
|
monkeypatch.setattr(version_module, "version", lambda name: "0.1.1" if name == "pylib-ai-arm-statements" else None)
|
||||||
|
assert statements_version() == "0.1.1"
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_marker_takes_priority(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
|
marker = tmp_path / "VERSION"
|
||||||
|
marker.write_text(f" {FULL_HASH}\n", encoding="utf-8")
|
||||||
|
monkeypatch.setattr(version_module, "_DEFAULT_MARKER", marker)
|
||||||
|
|
||||||
|
def unexpected_metadata_lookup(name: str) -> str:
|
||||||
|
raise AssertionError(f"Unexpected metadata lookup: {name}")
|
||||||
|
|
||||||
|
monkeypatch.setattr(version_module, "version", unexpected_metadata_lookup)
|
||||||
|
assert statements_version() == FULL_HASH
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_version_without_metadata_is_none(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
|
monkeypatch.setattr(version_module, "_DEFAULT_MARKER", tmp_path / "VERSION")
|
||||||
|
|
||||||
def missing_distribution(name: str) -> str:
|
def missing_distribution(name: str) -> str:
|
||||||
raise PackageNotFoundError(name)
|
raise PackageNotFoundError(name)
|
||||||
|
|
||||||
monkeypatch.setattr(version_module, "version", missing_distribution)
|
monkeypatch.setattr(version_module, "version", missing_distribution)
|
||||||
assert statements_version() is None
|
assert statements_version() is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("contents", [None, " \n"])
|
||||||
|
def test_explicit_marker_does_not_use_distribution(
|
||||||
|
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, contents: str | None
|
||||||
|
) -> None:
|
||||||
|
marker = tmp_path / "VERSION"
|
||||||
|
if contents is not None:
|
||||||
|
marker.write_text(contents, encoding="utf-8")
|
||||||
|
|
||||||
|
def unexpected_metadata_lookup(name: str) -> str:
|
||||||
|
raise AssertionError(f"Unexpected metadata lookup: {name}")
|
||||||
|
|
||||||
|
monkeypatch.setattr(version_module, "version", unexpected_metadata_lookup)
|
||||||
|
assert statements_version(marker) is None
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user