v8unpack-agent 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- v8unpack_agent-0.1.0/LICENSE +21 -0
- v8unpack_agent-0.1.0/PKG-INFO +285 -0
- v8unpack_agent-0.1.0/README.md +268 -0
- v8unpack_agent-0.1.0/pyproject.toml +60 -0
- v8unpack_agent-0.1.0/setup.cfg +4 -0
- v8unpack_agent-0.1.0/tests/test_catalog_resolver.py +317 -0
- v8unpack_agent-0.1.0/tests/test_catalog_resolver_issue172.py +202 -0
- v8unpack_agent-0.1.0/tests/test_catalog_resolver_raw_header.py +229 -0
- v8unpack_agent-0.1.0/tests/test_chain_zero_binding_issue116.py +516 -0
- v8unpack_agent-0.1.0/tests/test_common_modules_issue151.py +198 -0
- v8unpack_agent-0.1.0/tests/test_coverage_metric.py +327 -0
- v8unpack_agent-0.1.0/tests/test_decode_element_data_path.py +222 -0
- v8unpack_agent-0.1.0/tests/test_discover_managed_forms_issue55.py +395 -0
- v8unpack_agent-0.1.0/tests/test_docs_contract_issue245.py +118 -0
- v8unpack_agent-0.1.0/tests/test_drift_checker.py +312 -0
- v8unpack_agent-0.1.0/tests/test_drift_checker_external.py +350 -0
- v8unpack_agent-0.1.0/tests/test_drift_checker_issue91.py +140 -0
- v8unpack_agent-0.1.0/tests/test_drift_content_hash.py +171 -0
- v8unpack_agent-0.1.0/tests/test_elem_parser.py +265 -0
- v8unpack_agent-0.1.0/tests/test_elem_parser_issue103.py +109 -0
- v8unpack_agent-0.1.0/tests/test_elem_parser_issue105.py +449 -0
- v8unpack_agent-0.1.0/tests/test_elem_parser_issue108.py +477 -0
- v8unpack_agent-0.1.0/tests/test_elem_parser_issue123.py +247 -0
- v8unpack_agent-0.1.0/tests/test_elem_parser_issue85.py +928 -0
- v8unpack_agent-0.1.0/tests/test_elem_parser_issue89.py +340 -0
- v8unpack_agent-0.1.0/tests/test_elem_sha256_drift.py +617 -0
- v8unpack_agent-0.1.0/tests/test_elem_structure_hash.py +223 -0
- v8unpack_agent-0.1.0/tests/test_examples_contract_issue246.py +36 -0
- v8unpack_agent-0.1.0/tests/test_examples_determinism_issue251.py +137 -0
- v8unpack_agent-0.1.0/tests/test_form_artifact.py +50 -0
- v8unpack_agent-0.1.0/tests/test_form_classifier_issue109.py +263 -0
- v8unpack_agent-0.1.0/tests/test_form_classifier_issue112.py +270 -0
- v8unpack_agent-0.1.0/tests/test_form_classifier_issue98.py +439 -0
- v8unpack_agent-0.1.0/tests/test_form_context.py +495 -0
- v8unpack_agent-0.1.0/tests/test_form_context_issue147.py +418 -0
- v8unpack_agent-0.1.0/tests/test_form_context_issue148.py +264 -0
- v8unpack_agent-0.1.0/tests/test_form_context_object_attributes.py +135 -0
- v8unpack_agent-0.1.0/tests/test_form_entry_protocol_issue191.py +220 -0
- v8unpack_agent-0.1.0/tests/test_form_identity_issue226.py +278 -0
- v8unpack_agent-0.1.0/tests/test_form_key_public_issue134.py +106 -0
- v8unpack_agent-0.1.0/tests/test_form_paths.py +41 -0
- v8unpack_agent-0.1.0/tests/test_form_router.py +256 -0
- v8unpack_agent-0.1.0/tests/test_form_router_hash_baseline.py +211 -0
- v8unpack_agent-0.1.0/tests/test_form_router_mixed.py +285 -0
- v8unpack_agent-0.1.0/tests/test_form_scan_index_elem.py +372 -0
- v8unpack_agent-0.1.0/tests/test_form_scan_index_paths_issue239.py +251 -0
- v8unpack_agent-0.1.0/tests/test_form_summary_issue69.py +278 -0
- v8unpack_agent-0.1.0/tests/test_forms_index.py +72 -0
- v8unpack_agent-0.1.0/tests/test_full_pipeline_walkthrough_issue175.py +242 -0
- v8unpack_agent-0.1.0/tests/test_init_form_context_exports_issue124.py +101 -0
- v8unpack_agent-0.1.0/tests/test_init_lazy_imports_issue128.py +130 -0
- v8unpack_agent-0.1.0/tests/test_init_lazy_imports_issue131.py +267 -0
- v8unpack_agent-0.1.0/tests/test_init_lazy_imports_issue134.py +250 -0
- v8unpack_agent-0.1.0/tests/test_init_lazy_imports_issue140.py +213 -0
- v8unpack_agent-0.1.0/tests/test_legacy_form_json_extractor.py +249 -0
- v8unpack_agent-0.1.0/tests/test_managed_fixtures.py +263 -0
- v8unpack_agent-0.1.0/tests/test_managed_form_summary.py +180 -0
- v8unpack_agent-0.1.0/tests/test_object_decoder.py +601 -0
- v8unpack_agent-0.1.0/tests/test_object_decoder_layout_contract_issue160.py +167 -0
- v8unpack_agent-0.1.0/tests/test_packaging_issue149.py +89 -0
- v8unpack_agent-0.1.0/tests/test_pipeline.py +127 -0
- v8unpack_agent-0.1.0/tests/test_platform_reference_types_issue165.py +123 -0
- v8unpack_agent-0.1.0/tests/test_platform_types_cross_config_issue164.py +208 -0
- v8unpack_agent-0.1.0/tests/test_post_run_report_issue196.py +277 -0
- v8unpack_agent-0.1.0/tests/test_production_runner_issue198.py +509 -0
- v8unpack_agent-0.1.0/tests/test_reference_type_resolution.py +232 -0
- v8unpack_agent-0.1.0/tests/test_run_report_docs_issue248.py +101 -0
- v8unpack_agent-0.1.0/tests/test_scan_external_forms.py +250 -0
- v8unpack_agent-0.1.0/tests/test_scan_forms.py +309 -0
- v8unpack_agent-0.1.0/tests/test_scan_forms_cli.py +161 -0
- v8unpack_agent-0.1.0/tests/test_scan_forms_external_bsl.py +223 -0
- v8unpack_agent-0.1.0/tests/test_scan_forms_load.py +171 -0
- v8unpack_agent-0.1.0/tests/test_scan_forms_reference_type_docs_issue168.py +97 -0
- v8unpack_agent-0.1.0/tests/test_scan_forms_root_issue234.py +52 -0
- v8unpack_agent-0.1.0/tests/test_scan_root_invalid_reserved_issue242.py +55 -0
- v8unpack_agent-0.1.0/tests/test_scan_warning_codes_issue167.py +422 -0
- v8unpack_agent-0.1.0/tests/test_skd_extractor.py +144 -0
- v8unpack_agent-0.1.0/tests/test_skd_extractor_batch.py +171 -0
- v8unpack_agent-0.1.0/tests/test_unindexed_forms_report_issue235.py +89 -0
- v8unpack_agent-0.1.0/tests/test_unresolved_refs_metric_issue278.py +115 -0
- v8unpack_agent-0.1.0/tests/test_warning_error_paths_issue123.py +102 -0
- v8unpack_agent-0.1.0/v8unpack_agent/__init__.py +322 -0
- v8unpack_agent-0.1.0/v8unpack_agent/_safe_paths.py +135 -0
- v8unpack_agent-0.1.0/v8unpack_agent/catalog_resolver.py +354 -0
- v8unpack_agent-0.1.0/v8unpack_agent/chain_data_path.py +546 -0
- v8unpack_agent-0.1.0/v8unpack_agent/cli.py +230 -0
- v8unpack_agent-0.1.0/v8unpack_agent/common_modules.py +117 -0
- v8unpack_agent-0.1.0/v8unpack_agent/coverage_metric.py +364 -0
- v8unpack_agent-0.1.0/v8unpack_agent/drift_checker.py +494 -0
- v8unpack_agent-0.1.0/v8unpack_agent/elem_parser.py +1452 -0
- v8unpack_agent-0.1.0/v8unpack_agent/form_artifact.py +118 -0
- v8unpack_agent-0.1.0/v8unpack_agent/form_classifier.py +462 -0
- v8unpack_agent-0.1.0/v8unpack_agent/form_context.py +493 -0
- v8unpack_agent-0.1.0/v8unpack_agent/form_identity.py +299 -0
- v8unpack_agent-0.1.0/v8unpack_agent/form_paths.py +81 -0
- v8unpack_agent-0.1.0/v8unpack_agent/form_router.py +168 -0
- v8unpack_agent-0.1.0/v8unpack_agent/form_summary.py +163 -0
- v8unpack_agent-0.1.0/v8unpack_agent/forms_index.py +145 -0
- v8unpack_agent-0.1.0/v8unpack_agent/managed_form_summary.py +71 -0
- v8unpack_agent-0.1.0/v8unpack_agent/managed_forms.py +338 -0
- v8unpack_agent-0.1.0/v8unpack_agent/object_decoder.py +662 -0
- v8unpack_agent-0.1.0/v8unpack_agent/pipeline.py +202 -0
- v8unpack_agent-0.1.0/v8unpack_agent/platform_reference_types.py +68 -0
- v8unpack_agent-0.1.0/v8unpack_agent/run_report.py +381 -0
- v8unpack_agent-0.1.0/v8unpack_agent/runner.py +583 -0
- v8unpack_agent-0.1.0/v8unpack_agent/scan_forms.py +998 -0
- v8unpack_agent-0.1.0/v8unpack_agent/skd_extractor.py +273 -0
- v8unpack_agent-0.1.0/v8unpack_agent.egg-info/PKG-INFO +285 -0
- v8unpack_agent-0.1.0/v8unpack_agent.egg-info/SOURCES.txt +111 -0
- v8unpack_agent-0.1.0/v8unpack_agent.egg-info/dependency_links.txt +1 -0
- v8unpack_agent-0.1.0/v8unpack_agent.egg-info/entry_points.txt +2 -0
- v8unpack_agent-0.1.0/v8unpack_agent.egg-info/requires.txt +8 -0
- v8unpack_agent-0.1.0/v8unpack_agent.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Иофик Михаил (MRDK80)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: v8unpack-agent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agent-pipeline adapter for v8unpack: path factory, FormArtifact, drift index
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/MRDK80/v8unpack-agent
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: v8unpack>=1.2.13
|
|
11
|
+
Provides-Extra: test
|
|
12
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: mypy==2.3.1; extra == "dev"
|
|
15
|
+
Requires-Dist: ruff==0.16.4; extra == "dev"
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# v8unpack-agent
|
|
19
|
+
|
|
20
|
+
Прикладной инструмент над upstream-распаковщиком `v8unpack`: превращает
|
|
21
|
+
выгрузку конфигурации 1С в читаемый текстовый слой, машиночитаемую опись
|
|
22
|
+
форм и компактный контекст для LLM.
|
|
23
|
+
|
|
24
|
+
Задача пакета — дать агенту достоверные сведения о формах и модулях без
|
|
25
|
+
угадывания. Где данные нечитаемы, результат помечается как неполный, а не
|
|
26
|
+
достраивается догадками.
|
|
27
|
+
|
|
28
|
+
## Границы и non-goals
|
|
29
|
+
|
|
30
|
+
- Пакет не распаковывает контейнер сам: дерево выгрузки готовит upstream
|
|
31
|
+
`v8unpack`, а агент работает с уже раскрытым каталогом.
|
|
32
|
+
- Production-адаптера одиночного `Form.bin` в пакете нет: реализацию
|
|
33
|
+
распаковщика передаёт вызывающая сторона.
|
|
34
|
+
- Функций `index_cf()` и `rag.rebuild()` не существует; векторная индексация
|
|
35
|
+
находится вне scope пакета.
|
|
36
|
+
- Пакет не подключается к живой информационной базе и не читает её данные.
|
|
37
|
+
|
|
38
|
+
## Кто что решает
|
|
39
|
+
|
|
40
|
+
| Компонент | Ответственность |
|
|
41
|
+
|---|---|
|
|
42
|
+
| upstream `v8unpack` | распаковка контейнеров в дерево файлов |
|
|
43
|
+
| `v8unpack-agent` | опись форм, текстовый слой, индексы, контекст, отчёт о запуске |
|
|
44
|
+
| вызывающая сторона | реализация распаковщика формы и решения по degraded-результату |
|
|
45
|
+
|
|
46
|
+
## Установка
|
|
47
|
+
|
|
48
|
+
Основная установка из PyPI:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install v8unpack-agent
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Исторический pre-release `0.1.0rc1` остаётся доступным в PyPI и по умолчанию
|
|
55
|
+
не выбирается резолверами (нужен явный pin или `--pre`):
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install v8unpack-agent==0.1.0rc1
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Установка актуального состояния `main` напрямую из Git остаётся вариантом для
|
|
62
|
+
проверки ещё не опубликованных изменений:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install git+https://github.com/MRDK80/v8unpack-agent.git
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Установка для разработки из клона:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install -e ".[test]"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
upstream `v8unpack` нужен для фактического извлечения текстов, включая
|
|
75
|
+
поддержку внешних отчётов `.erf`.
|
|
76
|
+
|
|
77
|
+
## Быстрый старт: CLI
|
|
78
|
+
|
|
79
|
+
Один прогон — один отчёт и один код возврата. На вход подаётся каталог
|
|
80
|
+
уже распакованной выгрузки.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
v8unpack-agent-run <корень_выгрузки> --report-path post-run.json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Аргумент `--report-path` обязателен, значения по умолчанию нет, а
|
|
87
|
+
каталог-родитель должен существовать заранее.
|
|
88
|
+
|
|
89
|
+
| Код | Значение |
|
|
90
|
+
|---:|---|
|
|
91
|
+
| 0 | все объекты обработаны полностью |
|
|
92
|
+
| 2 | ошибка аргументов или корень не является каталогом |
|
|
93
|
+
| 3 | degraded: есть частичные или отказавшие объекты |
|
|
94
|
+
| 4 | управляемая фатальная ошибка пайплайна |
|
|
95
|
+
| 5 | ошибка записи отчёта |
|
|
96
|
+
| 6 | фатальная ошибка и ошибка записи одновременно |
|
|
97
|
+
|
|
98
|
+
Degraded — неуспешное завершение: неполный контекст не должен выглядеть
|
|
99
|
+
успехом для автоматизации. Полное описание аргументов, стадий и кодов причин —
|
|
100
|
+
в [`docs/runner.md`](docs/runner.md), схема отчёта — в
|
|
101
|
+
[`docs/run_report.md`](docs/run_report.md).
|
|
102
|
+
|
|
103
|
+
## Быстрый старт: Python
|
|
104
|
+
|
|
105
|
+
Каноническая цепочка: обнаружение источников, распаковка по `FormBinSource`,
|
|
106
|
+
обновление индекса.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from pathlib import Path
|
|
110
|
+
|
|
111
|
+
from v8unpack_agent import unpack_all_forms, update_forms_index
|
|
112
|
+
from v8unpack_agent.form_artifact import FormArtifact
|
|
113
|
+
from v8unpack_agent.form_identity import FormBinSource
|
|
114
|
+
from v8unpack_agent.scan_forms import scan_forms
|
|
115
|
+
|
|
116
|
+
dump_root = Path("unpacked_cf")
|
|
117
|
+
unpacked_root = Path("text_layer")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def unpack_one(source: FormBinSource, root: Path) -> FormArtifact:
|
|
121
|
+
"""Здесь вызывается реальное извлечение текстов из source.bin_path."""
|
|
122
|
+
return FormArtifact.for_form(root, source.name)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
scan_index = scan_forms(dump_root)
|
|
126
|
+
print(f"Найдено форм: {scan_index.total}")
|
|
127
|
+
|
|
128
|
+
artifacts = unpack_all_forms(dump_root, unpacked_root, unpack_one)
|
|
129
|
+
index = update_forms_index(dump_root, unpacked_root, artifacts)
|
|
130
|
+
index.save(Path("forms_index.json"))
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Распаковщик получает `FormBinSource` и корень текстового слоя — ровно два
|
|
134
|
+
аргумента. Существующая трёхаргументная реализация подключается только через
|
|
135
|
+
`adapt_legacy_unpacker()`. Подробный разбор и отбор по `form_ids` — в
|
|
136
|
+
[`docs/pipeline.md`](docs/pipeline.md), готовые сценарии — в
|
|
137
|
+
[`examples/README.md`](examples/README.md).
|
|
138
|
+
|
|
139
|
+
## Пайплайн
|
|
140
|
+
|
|
141
|
+
| Шаг | Функция | Результат |
|
|
142
|
+
|---|---|---|
|
|
143
|
+
| опись форм | `scan_forms()` | `FormScanIndex` с layout-метаданными и индексом ссылочных типов |
|
|
144
|
+
| обнаружение источников | `discover_form_sources()` | `FormBinSource` с каноническим `form_id` |
|
|
145
|
+
| распаковка | `unpack_all_forms()` | `FormArtifact` на каждую форму |
|
|
146
|
+
| структура формы | `parse_elem_json()` | элементы и привязки `data_path`, best-effort |
|
|
147
|
+
| реквизиты объекта | `decode_object_attributes()` | `Properties` и `TabularSections` |
|
|
148
|
+
| классификация | `classify_form()` | `object`, `service` или `unknown` |
|
|
149
|
+
| внешние отчёты | `unpack_erf()` | текстовый слой и запросы СКД |
|
|
150
|
+
| индекс актуальности | `update_forms_index()` | `FormsIndex` с ключом `form_id` |
|
|
151
|
+
| контроль дрейфа | `check_drift()` | `DriftReport` по хешам |
|
|
152
|
+
| контекст для LLM | `build_form_context()` | `FormContext` и промпт-фрагмент |
|
|
153
|
+
|
|
154
|
+
## Ключевые возможности
|
|
155
|
+
|
|
156
|
+
- Одноимённые формы разных владельцев не затирают друг друга: идентичность —
|
|
157
|
+
`form_id`, а не имя.
|
|
158
|
+
- Формы без кода попадают в опись: elem-only ветка заполняет `elem_json_path`.
|
|
159
|
+
- Частичный результат всегда явный: `extraction_ok=False` невозможен без
|
|
160
|
+
непустого `extraction_warnings`.
|
|
161
|
+
- Ссылочные типы реквизитов приводятся к имени объекта метаданных; неизвестный
|
|
162
|
+
UUID остаётся `Ref#<uuid>` и не угадывается.
|
|
163
|
+
- Сервисные формы отделены от объектных, чтобы метрика покрытия не занижалась
|
|
164
|
+
архитектурным паттерном платформы.
|
|
165
|
+
- Дрейф детектируется по хешам модуля и структуры, а не только по времени
|
|
166
|
+
изменения файла.
|
|
167
|
+
- Сериализация индексов переносима: в файлы пишутся только относительные
|
|
168
|
+
POSIX-пути, одинаковые на POSIX и NT.
|
|
169
|
+
|
|
170
|
+
## Версии схем
|
|
171
|
+
|
|
172
|
+
Три независимые версии, которые не сравниваются друг с другом.
|
|
173
|
+
|
|
174
|
+
| Артефакт | Версия | Где описан |
|
|
175
|
+
|---|---:|---|
|
|
176
|
+
| `FormsIndex` | 2 | [`docs/pipeline.md`](docs/pipeline.md) |
|
|
177
|
+
| `FormScanIndex` | 2 при чтении legacy 1 | [`docs/scan_forms.md`](docs/scan_forms.md) |
|
|
178
|
+
| post-run report | 1 | [`docs/run_report.md`](docs/run_report.md) |
|
|
179
|
+
|
|
180
|
+
## Публичная поверхность
|
|
181
|
+
|
|
182
|
+
| Модуль | Основные имена | Канонический документ |
|
|
183
|
+
|---|---|---|
|
|
184
|
+
| `scan_forms` | `scan_forms`, `FormEntry`, `FormScanIndex`, `scan_warning_code` | [scan_forms](docs/scan_forms.md) |
|
|
185
|
+
| `pipeline` | `unpack_all_forms`, `unpack_erf`, `update_forms_index`, `FormUnpacker` | [pipeline](docs/pipeline.md) |
|
|
186
|
+
| `form_identity` | `FormBinSource`, `discover_form_sources`, `select_sources`, `adapt_legacy_unpacker` | [pipeline](docs/pipeline.md) |
|
|
187
|
+
| `form_artifact` | `FormArtifact` | [pipeline](docs/pipeline.md) |
|
|
188
|
+
| `forms_index` | `FormsIndex`, `FormsIndexEntry`, `is_form_stale` | [pipeline](docs/pipeline.md) |
|
|
189
|
+
| `runner`, `cli` | `RunOptions`, `RunOutcome`, `run_pipeline` | [runner](docs/runner.md) |
|
|
190
|
+
| `run_report` | `PostRunReport`, `ObjectRunResult`, `write_post_run_report` | [run_report](docs/run_report.md) |
|
|
191
|
+
| `elem_parser` | `parse_elem_json`, `ElemIndexResult`, `UnindexedReason` | [elem_parser](docs/elem_parser.md) |
|
|
192
|
+
| `form_classifier` | `classify_form`, `FormClass`, `classify_empty_tree_form` | [form_classifier](docs/form_classifier.md) |
|
|
193
|
+
| `coverage_metric` | `calc_data_path_coverage`, `CoverageReport` | [form_classifier](docs/form_classifier.md) |
|
|
194
|
+
| `object_decoder` | `decode_object_attributes`, `DecodeResult`, `DecodeError` | [object_decoder](docs/object_decoder.md) |
|
|
195
|
+
| `catalog_resolver` | `resolve_data_path`, `ResolvedBinding` | [catalog_resolver](docs/catalog_resolver.md) |
|
|
196
|
+
| `form_context` | `FormContext`, `build_form_context`, `to_llm_prompt_fragment` | [form_context](docs/form_context.md) |
|
|
197
|
+
| `form_summary` | `build_form_summary`, `to_normalized_json` | [form_summary](docs/form_summary.md) |
|
|
198
|
+
| `form_router` | `FormRouter`, `form_paths` | [form_router](docs/form_router.md) |
|
|
199
|
+
| `common_modules` | `scan_common_modules`, `build_common_module_context` | [common_modules](docs/common_modules.md) |
|
|
200
|
+
| `managed_forms` | `discover_elem_forms`, `ElemFormEntry` | [managed_forms_structure](docs/managed_forms_structure.md) |
|
|
201
|
+
| `skd_extractor` | `extract_skd_queries`, `extract_all_skd_queries` | [skd_extractor](docs/skd_extractor.md) |
|
|
202
|
+
| `drift_checker` | `check_drift`, `DriftReport` | [drift_checker](docs/drift_checker.md) |
|
|
203
|
+
|
|
204
|
+
## Документация
|
|
205
|
+
|
|
206
|
+
### Начало работы
|
|
207
|
+
|
|
208
|
+
- [Текущее состояние реализации](docs/IMPLEMENTATION_STATUS.md)
|
|
209
|
+
- [Процесс контрибуции](CONTRIBUTING.md)
|
|
210
|
+
- [История изменений](CHANGELOG.md)
|
|
211
|
+
|
|
212
|
+
### Пайплайн и запуск
|
|
213
|
+
|
|
214
|
+
- [Контракт пайплайна и `FormUnpacker`](docs/pipeline.md)
|
|
215
|
+
- [Production runner, CLI и коды возврата](docs/runner.md)
|
|
216
|
+
- [Схема отчёта о запуске](docs/run_report.md)
|
|
217
|
+
|
|
218
|
+
### Формы и разбор
|
|
219
|
+
|
|
220
|
+
- [Структура элементов и `UnindexedReason`](docs/elem_parser.md)
|
|
221
|
+
- [Классификация форм и метрика покрытия](docs/form_classifier.md)
|
|
222
|
+
- [Сводка по форме](docs/form_summary.md)
|
|
223
|
+
- [Контекст для LLM](docs/form_context.md)
|
|
224
|
+
- [Маршрутизация путей формы](docs/form_router.md)
|
|
225
|
+
- [Структура управляемых форм](docs/managed_forms_structure.md)
|
|
226
|
+
- [Структура внешних обработок и отчётов](docs/external_forms_structure.md)
|
|
227
|
+
- [Запросы СКД](docs/skd_extractor.md)
|
|
228
|
+
|
|
229
|
+
### Метаданные и индексы
|
|
230
|
+
|
|
231
|
+
- [Опись форм и индекс ссылочных типов](docs/scan_forms.md)
|
|
232
|
+
- [Реквизиты объекта из raw-секции `header`](docs/object_decoder.md)
|
|
233
|
+
- [Разрешение `data_path`](docs/catalog_resolver.md)
|
|
234
|
+
- [Общие модули](docs/common_modules.md)
|
|
235
|
+
- [Контроль дрейфа](docs/drift_checker.md)
|
|
236
|
+
|
|
237
|
+
### Исследования
|
|
238
|
+
|
|
239
|
+
Датированные протоколы с агрегатами; выводы не переписываются задним числом.
|
|
240
|
+
|
|
241
|
+
- [Доля неиндексированных форм](docs/research/unindexed_share_issue229.md)
|
|
242
|
+
- [Разрешение ссылочных типов](docs/research/ref_resolver_issue143.md)
|
|
243
|
+
- [Нессылочные типовые грани](docs/research/non_reference_type_facets_issue166.md)
|
|
244
|
+
- [Кросс-конфигурационная проверка типов](docs/research/platform_types_cross_config_issue164.md)
|
|
245
|
+
- [Пустые реквизиты объекта](docs/research/missing_object_attributes_issue163.md)
|
|
246
|
+
- [Структура `Form.bin`](docs/research/form_bin_issue150.md)
|
|
247
|
+
- [Валидация на третьей выгрузке](docs/research/third_configuration_validation.md)
|
|
248
|
+
|
|
249
|
+
### Примеры и политики
|
|
250
|
+
|
|
251
|
+
- [Исполняемые примеры](examples/README.md)
|
|
252
|
+
- [Политика ветвления](docs/branch_protection.md)
|
|
253
|
+
- [Аудит документации](docs/documentation_audit_issue245.md)
|
|
254
|
+
|
|
255
|
+
## Известные ограничения
|
|
256
|
+
|
|
257
|
+
- Обычные (неуправляемые) формы хранят разметку в бинарном виде и частично
|
|
258
|
+
не читаются; такие формы получают `unknown` и исключаются из знаменателя
|
|
259
|
+
метрики.
|
|
260
|
+
- Квалификаторы реквизитов и составные типы не декодируются.
|
|
261
|
+
- Индекс ссылочных типов строится только для видов метаданных с доказанной
|
|
262
|
+
ссылочной формой; остальные UUID остаются `Ref#<uuid>`.
|
|
263
|
+
- В режиме `mode="external"` индекс ссылочных типов не собирается.
|
|
264
|
+
- Распаковщики из `examples/` и тестов — заглушки и не читают бинарный
|
|
265
|
+
формат.
|
|
266
|
+
- Пакет ещё не опубликован в индексе пакетов (issue #149).
|
|
267
|
+
|
|
268
|
+
## Тесты
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
pytest
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Фикстуры синтетические: реальная выгрузка для прогона не требуется. Порядок
|
|
275
|
+
работы с ветками, проверки перед PR и требования к обезличенности описаны в
|
|
276
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
277
|
+
|
|
278
|
+
## Связанное
|
|
279
|
+
|
|
280
|
+
- [`saby-integration/v8unpack`](https://github.com/saby-integration/v8unpack) —
|
|
281
|
+
upstream-распаковщик на Python, лицензия MIT.
|
|
282
|
+
|
|
283
|
+
## Лицензия
|
|
284
|
+
|
|
285
|
+
MIT — см. [LICENSE](LICENSE).
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# v8unpack-agent
|
|
2
|
+
|
|
3
|
+
Прикладной инструмент над upstream-распаковщиком `v8unpack`: превращает
|
|
4
|
+
выгрузку конфигурации 1С в читаемый текстовый слой, машиночитаемую опись
|
|
5
|
+
форм и компактный контекст для LLM.
|
|
6
|
+
|
|
7
|
+
Задача пакета — дать агенту достоверные сведения о формах и модулях без
|
|
8
|
+
угадывания. Где данные нечитаемы, результат помечается как неполный, а не
|
|
9
|
+
достраивается догадками.
|
|
10
|
+
|
|
11
|
+
## Границы и non-goals
|
|
12
|
+
|
|
13
|
+
- Пакет не распаковывает контейнер сам: дерево выгрузки готовит upstream
|
|
14
|
+
`v8unpack`, а агент работает с уже раскрытым каталогом.
|
|
15
|
+
- Production-адаптера одиночного `Form.bin` в пакете нет: реализацию
|
|
16
|
+
распаковщика передаёт вызывающая сторона.
|
|
17
|
+
- Функций `index_cf()` и `rag.rebuild()` не существует; векторная индексация
|
|
18
|
+
находится вне scope пакета.
|
|
19
|
+
- Пакет не подключается к живой информационной базе и не читает её данные.
|
|
20
|
+
|
|
21
|
+
## Кто что решает
|
|
22
|
+
|
|
23
|
+
| Компонент | Ответственность |
|
|
24
|
+
|---|---|
|
|
25
|
+
| upstream `v8unpack` | распаковка контейнеров в дерево файлов |
|
|
26
|
+
| `v8unpack-agent` | опись форм, текстовый слой, индексы, контекст, отчёт о запуске |
|
|
27
|
+
| вызывающая сторона | реализация распаковщика формы и решения по degraded-результату |
|
|
28
|
+
|
|
29
|
+
## Установка
|
|
30
|
+
|
|
31
|
+
Основная установка из PyPI:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install v8unpack-agent
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Исторический pre-release `0.1.0rc1` остаётся доступным в PyPI и по умолчанию
|
|
38
|
+
не выбирается резолверами (нужен явный pin или `--pre`):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install v8unpack-agent==0.1.0rc1
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Установка актуального состояния `main` напрямую из Git остаётся вариантом для
|
|
45
|
+
проверки ещё не опубликованных изменений:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install git+https://github.com/MRDK80/v8unpack-agent.git
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Установка для разработки из клона:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install -e ".[test]"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
upstream `v8unpack` нужен для фактического извлечения текстов, включая
|
|
58
|
+
поддержку внешних отчётов `.erf`.
|
|
59
|
+
|
|
60
|
+
## Быстрый старт: CLI
|
|
61
|
+
|
|
62
|
+
Один прогон — один отчёт и один код возврата. На вход подаётся каталог
|
|
63
|
+
уже распакованной выгрузки.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
v8unpack-agent-run <корень_выгрузки> --report-path post-run.json
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Аргумент `--report-path` обязателен, значения по умолчанию нет, а
|
|
70
|
+
каталог-родитель должен существовать заранее.
|
|
71
|
+
|
|
72
|
+
| Код | Значение |
|
|
73
|
+
|---:|---|
|
|
74
|
+
| 0 | все объекты обработаны полностью |
|
|
75
|
+
| 2 | ошибка аргументов или корень не является каталогом |
|
|
76
|
+
| 3 | degraded: есть частичные или отказавшие объекты |
|
|
77
|
+
| 4 | управляемая фатальная ошибка пайплайна |
|
|
78
|
+
| 5 | ошибка записи отчёта |
|
|
79
|
+
| 6 | фатальная ошибка и ошибка записи одновременно |
|
|
80
|
+
|
|
81
|
+
Degraded — неуспешное завершение: неполный контекст не должен выглядеть
|
|
82
|
+
успехом для автоматизации. Полное описание аргументов, стадий и кодов причин —
|
|
83
|
+
в [`docs/runner.md`](docs/runner.md), схема отчёта — в
|
|
84
|
+
[`docs/run_report.md`](docs/run_report.md).
|
|
85
|
+
|
|
86
|
+
## Быстрый старт: Python
|
|
87
|
+
|
|
88
|
+
Каноническая цепочка: обнаружение источников, распаковка по `FormBinSource`,
|
|
89
|
+
обновление индекса.
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from pathlib import Path
|
|
93
|
+
|
|
94
|
+
from v8unpack_agent import unpack_all_forms, update_forms_index
|
|
95
|
+
from v8unpack_agent.form_artifact import FormArtifact
|
|
96
|
+
from v8unpack_agent.form_identity import FormBinSource
|
|
97
|
+
from v8unpack_agent.scan_forms import scan_forms
|
|
98
|
+
|
|
99
|
+
dump_root = Path("unpacked_cf")
|
|
100
|
+
unpacked_root = Path("text_layer")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def unpack_one(source: FormBinSource, root: Path) -> FormArtifact:
|
|
104
|
+
"""Здесь вызывается реальное извлечение текстов из source.bin_path."""
|
|
105
|
+
return FormArtifact.for_form(root, source.name)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
scan_index = scan_forms(dump_root)
|
|
109
|
+
print(f"Найдено форм: {scan_index.total}")
|
|
110
|
+
|
|
111
|
+
artifacts = unpack_all_forms(dump_root, unpacked_root, unpack_one)
|
|
112
|
+
index = update_forms_index(dump_root, unpacked_root, artifacts)
|
|
113
|
+
index.save(Path("forms_index.json"))
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Распаковщик получает `FormBinSource` и корень текстового слоя — ровно два
|
|
117
|
+
аргумента. Существующая трёхаргументная реализация подключается только через
|
|
118
|
+
`adapt_legacy_unpacker()`. Подробный разбор и отбор по `form_ids` — в
|
|
119
|
+
[`docs/pipeline.md`](docs/pipeline.md), готовые сценарии — в
|
|
120
|
+
[`examples/README.md`](examples/README.md).
|
|
121
|
+
|
|
122
|
+
## Пайплайн
|
|
123
|
+
|
|
124
|
+
| Шаг | Функция | Результат |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| опись форм | `scan_forms()` | `FormScanIndex` с layout-метаданными и индексом ссылочных типов |
|
|
127
|
+
| обнаружение источников | `discover_form_sources()` | `FormBinSource` с каноническим `form_id` |
|
|
128
|
+
| распаковка | `unpack_all_forms()` | `FormArtifact` на каждую форму |
|
|
129
|
+
| структура формы | `parse_elem_json()` | элементы и привязки `data_path`, best-effort |
|
|
130
|
+
| реквизиты объекта | `decode_object_attributes()` | `Properties` и `TabularSections` |
|
|
131
|
+
| классификация | `classify_form()` | `object`, `service` или `unknown` |
|
|
132
|
+
| внешние отчёты | `unpack_erf()` | текстовый слой и запросы СКД |
|
|
133
|
+
| индекс актуальности | `update_forms_index()` | `FormsIndex` с ключом `form_id` |
|
|
134
|
+
| контроль дрейфа | `check_drift()` | `DriftReport` по хешам |
|
|
135
|
+
| контекст для LLM | `build_form_context()` | `FormContext` и промпт-фрагмент |
|
|
136
|
+
|
|
137
|
+
## Ключевые возможности
|
|
138
|
+
|
|
139
|
+
- Одноимённые формы разных владельцев не затирают друг друга: идентичность —
|
|
140
|
+
`form_id`, а не имя.
|
|
141
|
+
- Формы без кода попадают в опись: elem-only ветка заполняет `elem_json_path`.
|
|
142
|
+
- Частичный результат всегда явный: `extraction_ok=False` невозможен без
|
|
143
|
+
непустого `extraction_warnings`.
|
|
144
|
+
- Ссылочные типы реквизитов приводятся к имени объекта метаданных; неизвестный
|
|
145
|
+
UUID остаётся `Ref#<uuid>` и не угадывается.
|
|
146
|
+
- Сервисные формы отделены от объектных, чтобы метрика покрытия не занижалась
|
|
147
|
+
архитектурным паттерном платформы.
|
|
148
|
+
- Дрейф детектируется по хешам модуля и структуры, а не только по времени
|
|
149
|
+
изменения файла.
|
|
150
|
+
- Сериализация индексов переносима: в файлы пишутся только относительные
|
|
151
|
+
POSIX-пути, одинаковые на POSIX и NT.
|
|
152
|
+
|
|
153
|
+
## Версии схем
|
|
154
|
+
|
|
155
|
+
Три независимые версии, которые не сравниваются друг с другом.
|
|
156
|
+
|
|
157
|
+
| Артефакт | Версия | Где описан |
|
|
158
|
+
|---|---:|---|
|
|
159
|
+
| `FormsIndex` | 2 | [`docs/pipeline.md`](docs/pipeline.md) |
|
|
160
|
+
| `FormScanIndex` | 2 при чтении legacy 1 | [`docs/scan_forms.md`](docs/scan_forms.md) |
|
|
161
|
+
| post-run report | 1 | [`docs/run_report.md`](docs/run_report.md) |
|
|
162
|
+
|
|
163
|
+
## Публичная поверхность
|
|
164
|
+
|
|
165
|
+
| Модуль | Основные имена | Канонический документ |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `scan_forms` | `scan_forms`, `FormEntry`, `FormScanIndex`, `scan_warning_code` | [scan_forms](docs/scan_forms.md) |
|
|
168
|
+
| `pipeline` | `unpack_all_forms`, `unpack_erf`, `update_forms_index`, `FormUnpacker` | [pipeline](docs/pipeline.md) |
|
|
169
|
+
| `form_identity` | `FormBinSource`, `discover_form_sources`, `select_sources`, `adapt_legacy_unpacker` | [pipeline](docs/pipeline.md) |
|
|
170
|
+
| `form_artifact` | `FormArtifact` | [pipeline](docs/pipeline.md) |
|
|
171
|
+
| `forms_index` | `FormsIndex`, `FormsIndexEntry`, `is_form_stale` | [pipeline](docs/pipeline.md) |
|
|
172
|
+
| `runner`, `cli` | `RunOptions`, `RunOutcome`, `run_pipeline` | [runner](docs/runner.md) |
|
|
173
|
+
| `run_report` | `PostRunReport`, `ObjectRunResult`, `write_post_run_report` | [run_report](docs/run_report.md) |
|
|
174
|
+
| `elem_parser` | `parse_elem_json`, `ElemIndexResult`, `UnindexedReason` | [elem_parser](docs/elem_parser.md) |
|
|
175
|
+
| `form_classifier` | `classify_form`, `FormClass`, `classify_empty_tree_form` | [form_classifier](docs/form_classifier.md) |
|
|
176
|
+
| `coverage_metric` | `calc_data_path_coverage`, `CoverageReport` | [form_classifier](docs/form_classifier.md) |
|
|
177
|
+
| `object_decoder` | `decode_object_attributes`, `DecodeResult`, `DecodeError` | [object_decoder](docs/object_decoder.md) |
|
|
178
|
+
| `catalog_resolver` | `resolve_data_path`, `ResolvedBinding` | [catalog_resolver](docs/catalog_resolver.md) |
|
|
179
|
+
| `form_context` | `FormContext`, `build_form_context`, `to_llm_prompt_fragment` | [form_context](docs/form_context.md) |
|
|
180
|
+
| `form_summary` | `build_form_summary`, `to_normalized_json` | [form_summary](docs/form_summary.md) |
|
|
181
|
+
| `form_router` | `FormRouter`, `form_paths` | [form_router](docs/form_router.md) |
|
|
182
|
+
| `common_modules` | `scan_common_modules`, `build_common_module_context` | [common_modules](docs/common_modules.md) |
|
|
183
|
+
| `managed_forms` | `discover_elem_forms`, `ElemFormEntry` | [managed_forms_structure](docs/managed_forms_structure.md) |
|
|
184
|
+
| `skd_extractor` | `extract_skd_queries`, `extract_all_skd_queries` | [skd_extractor](docs/skd_extractor.md) |
|
|
185
|
+
| `drift_checker` | `check_drift`, `DriftReport` | [drift_checker](docs/drift_checker.md) |
|
|
186
|
+
|
|
187
|
+
## Документация
|
|
188
|
+
|
|
189
|
+
### Начало работы
|
|
190
|
+
|
|
191
|
+
- [Текущее состояние реализации](docs/IMPLEMENTATION_STATUS.md)
|
|
192
|
+
- [Процесс контрибуции](CONTRIBUTING.md)
|
|
193
|
+
- [История изменений](CHANGELOG.md)
|
|
194
|
+
|
|
195
|
+
### Пайплайн и запуск
|
|
196
|
+
|
|
197
|
+
- [Контракт пайплайна и `FormUnpacker`](docs/pipeline.md)
|
|
198
|
+
- [Production runner, CLI и коды возврата](docs/runner.md)
|
|
199
|
+
- [Схема отчёта о запуске](docs/run_report.md)
|
|
200
|
+
|
|
201
|
+
### Формы и разбор
|
|
202
|
+
|
|
203
|
+
- [Структура элементов и `UnindexedReason`](docs/elem_parser.md)
|
|
204
|
+
- [Классификация форм и метрика покрытия](docs/form_classifier.md)
|
|
205
|
+
- [Сводка по форме](docs/form_summary.md)
|
|
206
|
+
- [Контекст для LLM](docs/form_context.md)
|
|
207
|
+
- [Маршрутизация путей формы](docs/form_router.md)
|
|
208
|
+
- [Структура управляемых форм](docs/managed_forms_structure.md)
|
|
209
|
+
- [Структура внешних обработок и отчётов](docs/external_forms_structure.md)
|
|
210
|
+
- [Запросы СКД](docs/skd_extractor.md)
|
|
211
|
+
|
|
212
|
+
### Метаданные и индексы
|
|
213
|
+
|
|
214
|
+
- [Опись форм и индекс ссылочных типов](docs/scan_forms.md)
|
|
215
|
+
- [Реквизиты объекта из raw-секции `header`](docs/object_decoder.md)
|
|
216
|
+
- [Разрешение `data_path`](docs/catalog_resolver.md)
|
|
217
|
+
- [Общие модули](docs/common_modules.md)
|
|
218
|
+
- [Контроль дрейфа](docs/drift_checker.md)
|
|
219
|
+
|
|
220
|
+
### Исследования
|
|
221
|
+
|
|
222
|
+
Датированные протоколы с агрегатами; выводы не переписываются задним числом.
|
|
223
|
+
|
|
224
|
+
- [Доля неиндексированных форм](docs/research/unindexed_share_issue229.md)
|
|
225
|
+
- [Разрешение ссылочных типов](docs/research/ref_resolver_issue143.md)
|
|
226
|
+
- [Нессылочные типовые грани](docs/research/non_reference_type_facets_issue166.md)
|
|
227
|
+
- [Кросс-конфигурационная проверка типов](docs/research/platform_types_cross_config_issue164.md)
|
|
228
|
+
- [Пустые реквизиты объекта](docs/research/missing_object_attributes_issue163.md)
|
|
229
|
+
- [Структура `Form.bin`](docs/research/form_bin_issue150.md)
|
|
230
|
+
- [Валидация на третьей выгрузке](docs/research/third_configuration_validation.md)
|
|
231
|
+
|
|
232
|
+
### Примеры и политики
|
|
233
|
+
|
|
234
|
+
- [Исполняемые примеры](examples/README.md)
|
|
235
|
+
- [Политика ветвления](docs/branch_protection.md)
|
|
236
|
+
- [Аудит документации](docs/documentation_audit_issue245.md)
|
|
237
|
+
|
|
238
|
+
## Известные ограничения
|
|
239
|
+
|
|
240
|
+
- Обычные (неуправляемые) формы хранят разметку в бинарном виде и частично
|
|
241
|
+
не читаются; такие формы получают `unknown` и исключаются из знаменателя
|
|
242
|
+
метрики.
|
|
243
|
+
- Квалификаторы реквизитов и составные типы не декодируются.
|
|
244
|
+
- Индекс ссылочных типов строится только для видов метаданных с доказанной
|
|
245
|
+
ссылочной формой; остальные UUID остаются `Ref#<uuid>`.
|
|
246
|
+
- В режиме `mode="external"` индекс ссылочных типов не собирается.
|
|
247
|
+
- Распаковщики из `examples/` и тестов — заглушки и не читают бинарный
|
|
248
|
+
формат.
|
|
249
|
+
- Пакет ещё не опубликован в индексе пакетов (issue #149).
|
|
250
|
+
|
|
251
|
+
## Тесты
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
pytest
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Фикстуры синтетические: реальная выгрузка для прогона не требуется. Порядок
|
|
258
|
+
работы с ветками, проверки перед PR и требования к обезличенности описаны в
|
|
259
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
260
|
+
|
|
261
|
+
## Связанное
|
|
262
|
+
|
|
263
|
+
- [`saby-integration/v8unpack`](https://github.com/saby-integration/v8unpack) —
|
|
264
|
+
upstream-распаковщик на Python, лицензия MIT.
|
|
265
|
+
|
|
266
|
+
## Лицензия
|
|
267
|
+
|
|
268
|
+
MIT — см. [LICENSE](LICENSE).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "v8unpack-agent"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Agent-pipeline adapter for v8unpack: path factory, FormArtifact, drift index"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
dependencies = [
|
|
14
|
+
"v8unpack>=1.2.13",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
test = [
|
|
19
|
+
"pytest>=7",
|
|
20
|
+
]
|
|
21
|
+
dev = [
|
|
22
|
+
"mypy==2.3.1",
|
|
23
|
+
"ruff==0.16.4",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
# Production entry point (#198). Альтернативный вызов без установки пакета:
|
|
28
|
+
# python -m v8unpack_agent.cli
|
|
29
|
+
v8unpack-agent-run = "v8unpack_agent.cli:main"
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/MRDK80/v8unpack-agent"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools]
|
|
35
|
+
packages = ["v8unpack_agent"]
|
|
36
|
+
|
|
37
|
+
[tool.pytest.ini_options]
|
|
38
|
+
pythonpath = ["."]
|
|
39
|
+
|
|
40
|
+
[tool.ruff]
|
|
41
|
+
target-version = "py310"
|
|
42
|
+
|
|
43
|
+
# Набор правил не сужается: используется дефолт запиненного ruff 0.16.4.
|
|
44
|
+
# Явный select отключил бы уже обнаруженный долг (ISC004, PLW1510) без разбора,
|
|
45
|
+
# что противоречит scope #161.
|
|
46
|
+
|
|
47
|
+
[tool.ruff.lint.per-file-ignores]
|
|
48
|
+
# Deprecated-шим с PEP 562: имена выдаются модульным __getattr__, а __dir__()
|
|
49
|
+
# возвращает sorted(__all__). Статически ruff этого не видит; удалять имена
|
|
50
|
+
# из __all__ нельзя — сломается контракт устаревших алиасов.
|
|
51
|
+
"v8unpack_agent/managed_form_summary.py" = ["F822"]
|
|
52
|
+
# Примеры запускаются как `python examples/...`; shebang декоративен.
|
|
53
|
+
# Единая смена git-mode каталога в scope #161 не входит.
|
|
54
|
+
"examples/**/*.py" = ["EXE001"]
|
|
55
|
+
|
|
56
|
+
[tool.mypy]
|
|
57
|
+
python_version = "3.10"
|
|
58
|
+
files = ["v8unpack_agent", "examples"]
|
|
59
|
+
show_error_codes = true
|
|
60
|
+
warn_unused_configs = true
|