Skip to main content

chancellery

Канцелярия — библиотека русского склонения и сборки служебных документов. Склоняет по падежам ФИО, должности и воинские звания (с автоопределением рода и согласованием слов во фразе) и собирает готовый docx по шаблону с русской разметкой, где падеж задаётся местом подстановки, а не данными.

Изначальное видение и границы — в CONCEPT.md.

Статус: 0.1.0. Движок переехал из «Дьяка» 0.3.3, где обкатан на настоящих кадровых документах; поведение сверено с эталоном донора поабзацно. План переноса — в specs/T001-engine-extraction/spec.md.

Потребители: «Дьяк» (кадровые документы пачкой из таблицы) и «Летопись» (приказы из кадровой базы).

Быстрый старт

uv add chancellery

Сценарий целиком — таблица со строками данных плюс размеченный шаблон docx дают папку готовых документов, по одному на строку:

from chancellery import generate_documents

written = generate_documents(
    table='employees.xlsx',
    template='order_template.docx',
    out='out',
    filename='{{ Фамилия }}.docx',  # необязательно: по умолчанию — по ФИО
)

Если сценарий не подходит (источник данных не таблица, свой цикл, своя обработка ошибок) — те же слои доступны по отдельности: read_table, build_context, render_document, check_table. А если документы не нужны вовсе, а нужно только склонение:

from chancellery import Case, Person, PetrovichInflector, PhraseInflector, build_context

context = build_context(
    Person(
        cells={
            'Фамилия': 'Иванов',
            'Имя': 'Пётр',
            'Отчество': 'Семёнович',
            'Должность': 'старший механик-водитель',
        }
    ),
    roles={
        'surname': 'Фамилия',
        'name': 'Имя',
        'patronymic': 'Отчество',
        'position': 'Должность',
    },
    inflector=PetrovichInflector(),
    position_inflector=PhraseInflector(),
)
context['ФИО'].inflect(Case.DATV)  # Иванову Петру Семёновичу
context['Должность'].inflect(Case.DATV)  # старшему механику-водителю

Разметка шаблона

Падеж задаётся местом подстановки, а не данными: один и тот же человек в шапке стоит в именительном, а в теле приказа — в дательном, и шаблон говорит об этом фильтром.

Падежные фильтры:

{{ ФИО | ип }}   именительный    Иванов Пётр Семёнович
{{ ФИО | рд }}   родительный     Иванова Петра Семёновича
{{ ФИО | дт }}   дательный       Иванову Петру Семёновичу
{{ ФИО | вн }}   винительный     Иванова Петра Семёновича
{{ ФИО | тв }}   творительный    Ивановым Петром Семёновичем
{{ ФИО | пр }}   предложный      Иванове Петре Семёновиче

Тег без фильтра даёт именительный. Фильтр применим к любому склоняемому значению — ФИО, части имени, должности, званию, произвольной колонке.

Согласование по полу — фильтр согл, мужская форма первой; пол берётся из ФИО (определяется автоматически по имени и отчеству):

{{ ФИО | согл('ознакомлен', 'ознакомлена') }}

Теги ФИО. Колонка «ФИО» разбирается на части, а части собираются обратно, поэтому доступны сразу все формы:

{{ ФИО }}                 Иванов Пётр Семёнович
{{ Фамилия }}             Иванов          {{ Имя }}, {{ Отчество }} — так же
{{ Инициалы }}            Иванов П. С.
{{ Инициалы_впереди }}    П. С. Иванов
{{ Инициалы_слитно }}     Иванов П.С.
{{ Имя_инициал }}         П.              одна буква с точкой

Инициалы тоже склоняются: {{ Инициалы | рд }} → «Иванова П. С.». Пустое отчество не роняет рендер — форма просто становится короче.

Остальные колонки доступны по своему заголовку: {{ Должность | дт }}, {{ Номер приказа }}. Заголовок нормализуется (пробелы → подчёркивания, спецсимволы вычищаются), поэтому «л/н» в таблице пишется в шаблоне как {{ л_н }}.

Неизвестная переменная — ошибка, а не пустое место в готовом приказе: шаблон рендерится в строгом режиме. Пустое значение, наоборот, убирается вместе с осиротевшей пунктуацией.

Разработка

Менеджер зависимостей и окружения: uv.

uv sync                       # поставить зависимости
uv run pytest                 # прогнать тесты

Зависимости

uv add <pkg>                  # runtime
uv add --dev <pkg>            # dev

Выпуск версии

scripts/publish.sh --test    # репетиция на TestPyPI (нужен PYPI_TEST_TOKEN)
scripts/publish.sh           # боевой PyPI

Скрипт сам гоняет четыре гейта, собирает колесо и архив исходников, проверяет артефакты twine и выкладывает. Токен читается из .secrets (под git-ignore, образец — .secrets.example) и машину не покидает. Порядок: закрыть версию в CHANGELOG.md, поднять version в pyproject.toml, слить, поставить git-тег вида 0.1.0, выложить.

Проверки перед push

uv run ruff check .
uv run ruff format --check .
uv run mypy src
scripts/pytest-guard.sh --cov=src --cov-report=term-missing --cov-fail-under=80

Все четыре должны проходить с 0 ошибок. Обходные манёвры (# noqa, # type: ignore, расширение ignore-секции) — только по согласованию.

Структура проекта

  • src/ — корень исходников.
  • CONCEPT.md — изначальное видение проекта (immutable).
  • DECISIONS.md — архитектурные решения с обоснованиями (ADR-Lite).
  • BOARD.md — рабочая Kanban-доска (To Do / Doing / Done).
  • BACKLOG.md — парковка идей и побочных находок.
  • CHANGELOG.md — журнал заметных изменений.
  • specs/ — спецификации крупных фич.
  • CLAUDE.md — проектные правила для Claude (Claude Code).

Методика работы

Проект создан из шаблона vlakir/dreamteam. Подробное описание методики (scope discipline, ритуал spec/clarify/analyze для крупных фич, pre-push контроль) — см. репозиторий шаблона.

Release files for chancellery 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chancellery 0.1.0
File Size Uploaded
chancellery-0.1.0.tar.gz 187.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for chancellery 0.1.0
File Interpreter ABI Platform
chancellery-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 260.7 kB

Release files / chancellery-0.1.0.tar.gz

Download URL chancellery-0.1.0.tar.gz
Size 187.5 kB
Tags Source
SHA-256 checksum
How to use checksums
2fcb07d5224d4bc90e6c189518bb7f3777ee421b36ed706f6762a7c15551aec5
BLAKE2b-256 checksum
How to use checksums
bcfc27778b90f0dd6f3b064a25fe0aa0dbefb4d7e1d76bae457cdf0d3839bcca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / chancellery-0.1.0-py3-none-any.whl

Download URL chancellery-0.1.0-py3-none-any.whl
Size 73.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
af2c8b997d3b03b1f14154dafabf96aacb34f21c723c9e85f0556aa5312f63ea
BLAKE2b-256 checksum
How to use checksums
4f2ec02b4c98a3c61bb356bdf82d7bed13be9c251eb4e75070dbe23e342ef2dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page