Skip to content

Commit c3d30e9

Browse files
authored
Swagger check (#4)
Проверка покрытия всего контракта swagger спецификаций
1 parent 11b03ae commit c3d30e9

145 files changed

Lines changed: 8970 additions & 2946 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.local.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,20 @@
3535
"Bash(grep -n \"^\\\\`\\\\`\\\\`\" /Users/n.baryshnikov/Projects/avito_python_api/docs/site/how-to/security-practices.md)",
3636
"Bash(pip show *)",
3737
"Bash(awk -F'|' '{gsub\\(/^ +| +$/,\"\",$2\\); gsub\\(/^ +| +$/,\"\",$6\\); print $2 \":\" $6}')",
38-
"Bash(make qa-docs *)"
38+
"Bash(make qa-docs *)",
39+
"WebFetch(domain:developers.avito.ru)",
40+
"Bash(curl -s -L --max-time 30 -A \"Mozilla/5.0 \\(Macintosh; Intel Mac OS X 10_15_7\\) AppleWebKit/537.36 \\(KHTML, like Gecko\\) Chrome/120.0.0.0 Safari/537.36\" \"https://developers.avito.ru/api-catalog\")",
41+
"Bash(curl -s -L --max-time 30 -A \"Mozilla/5.0 \\(Macintosh; Intel Mac OS X 10_15_7\\) AppleWebKit/537.36 \\(KHTML, like Gecko\\) Chrome/120.0.0.0 Safari/537.36\" \"https://developers.avito.ru/dstatic/build/open-api-dev-portal.16ee9b7cf4f5ce68f019.js\")",
42+
"Bash(grep -oE '\"\\(/[a-z0-9_-]+\\){2,}/[a-z0-9_-]+\"')",
43+
"Bash(curl -s -L --max-time 30 -A \"Mozilla/5.0 \\(Macintosh; Intel Mac OS X 10_15_7\\) AppleWebKit/537.36 \\(KHTML, like Gecko\\) Chrome/120.0.0.0 Safari/537.36\" \"https://developers.avito.ru/web/1/openapi/list\")",
44+
"Bash(curl -s -L --max-time 30 -A \"Mozilla/5.0 \\(Macintosh; Intel Mac OS X 10_15_7\\) AppleWebKit/537.36 \\(KHTML, like Gecko\\) Chrome/120.0.0.0 Safari/537.36\" \"https://developers.avito.ru/web/1/openapi/info/messenger\")",
45+
"Bash(curl -s -L --max-time 30 -A \"Mozilla/5.0 \\(Macintosh; Intel Mac OS X 10_15_7\\) AppleWebKit/537.36 \\(KHTML, like Gecko\\) Chrome/120.0.0.0 Safari/537.36\" \"https://developers.avito.ru/web/1/openapi/info/auth\")",
46+
"Bash(curl -s -o /dev/null -w \"%{http_code}\" --max-time 10 \"https://api.avito.ru/docs/public/messenger.yaml\")",
47+
"Bash(curl -s -o /dev/null -w \"%{http_code}\" --max-time 10 \"https://developers.avito.ru/swagger/messenger.yaml\")",
48+
"Bash(curl -s -o /dev/null -w \"%{http_code}\" --max-time 10 \"https://developers.avito.ru/api-catalog/messenger/swagger.json\")",
49+
"Bash(curl -s --max-time 10 \"https://developers.avito.ru/swagger/messenger.yaml\")",
50+
"Bash(curl -s --max-time 10 \"https://developers.avito.ru/api-catalog/messenger/swagger.json\")",
51+
"Bash(awk -F'|' '{print $15}')"
3952
]
4053
}
4154
}

.github/pull_request_template.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
## Проверки
22

33
- [ ] `make check` проходит локально или в CI.
4-
- [ ] `make docs-strict` проходит, если изменены README, docs, публичные сигнатуры или inventory.
4+
- [ ] `make docs-strict` проходит, если изменены README, docs, публичные сигнатуры или Swagger bindings.
55
- [ ] README/tutorials/how-to примеры соответствуют актуальным публичным сигнатурам SDK.
6-
- [ ] Новая публичная операция добавлена в `docs/avito/inventory.md` и покрыта reference.
6+
- [ ] Новая публичная операция связана со Swagger operation binding и покрыта reference.
77
- [ ] Публичное переименование: alias сохранён, `DeprecationWarning` добавлен, `CHANGELOG.md` обновлён в секции `Deprecated`.

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ jobs:
3131
- name: Install dependencies
3232
run: poetry install --no-interaction --with docs
3333

34+
- name: Run strict Swagger coverage gate
35+
run: make swagger-coverage
36+
3437
- name: Run quality gate
3538
run: make check
3639

.github/workflows/docs.yml

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,21 +40,7 @@ jobs:
4040
run: make docs-strict
4141

4242
- name: Build docs reports
43-
run: |
44-
poetry run python scripts/check_inventory_coverage.py --output inventory-coverage-report.json
45-
poetry run python scripts/check_spec_inventory_sync.py --output spec-inventory-report.json
46-
poetry run python scripts/check_reference_public_surface.py --output reference-public-report.json
47-
poetry run python scripts/check_public_docstrings.py --output docstring-contract-report.json
48-
poetry run python scripts/check_changelog_sections.py --output changelog-sections-report.json
49-
poetry run bandit -r avito -lll -f json -o bandit-report.json
50-
poetry run python scripts/build_docs_quality_report.py \
51-
--inventory-report inventory-coverage-report.json \
52-
--spec-report spec-inventory-report.json \
53-
--reference-report reference-public-report.json \
54-
--docstring-report docstring-contract-report.json \
55-
--changelog-report changelog-sections-report.json \
56-
--bandit-report bandit-report.json \
57-
--output docs-quality-report.json
43+
run: make docs-report
5844

5945
- name: Prepare local docs root for link checking
6046
run: ln -s . site/avito_python_api
@@ -64,13 +50,7 @@ jobs:
6450
with:
6551
name: docs-contract-reports
6652
path: |
67-
inventory-coverage-report.json
68-
spec-inventory-report.json
69-
reference-public-report.json
70-
docstring-contract-report.json
71-
changelog-sections-report.json
72-
bandit-report.json
73-
docs-quality-report.json
53+
swagger-bindings-report.json
7454
7555
- name: Check links
7656
uses: lycheeverse/lychee-action@v2

.github/workflows/release.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ jobs:
3737
TAG_VERSION="${GITHUB_REF_NAME#v}"
3838
poetry version "$TAG_VERSION"
3939
40+
- name: Run strict Swagger coverage gate
41+
run: make swagger-coverage
42+
4043
- name: Run quality gate
4144
run: make check
4245

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pip-log.txt
4242
pip-delete-this-directory.txt
4343

4444
# Unit test / coverage reports
45+
swagger-bindings-report.json
4546
htmlcov/
4647
.tox/
4748
.nox/

CLAUDE.md

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
88
make test # run all tests
99
make typecheck # mypy strict check on avito/
1010
make lint # ruff check
11+
make swagger-lint # strict Swagger binding coverage check
1112
make fmt # ruff format
12-
make check # test → typecheck → lint → build (full gate)
13+
make check # test → typecheck → lint → swagger-lint → build (full gate)
1314
make build # poetry build
1415

1516
# single test
@@ -41,18 +42,48 @@ poetry run pytest tests/test_facade.py::test_name
4142

4243
**Testing**: `tests/fake_transport.py` provides `FakeTransport` — inject it instead of real HTTP. Tests are Arrange/Act/Assert, one scenario per test. Test names describe behavior, not the method under test.
4344

44-
## API coverage and inventory
45+
## API coverage
4546

4647
`docs/avito/api/` contains Swagger/OpenAPI specs (23 documents, 204 operations) — the authoritative source of truth for all API contracts.
48+
The canonical SDK coverage map is built from Swagger operation bindings discovered on public domain methods, not from markdown inventory files.
4749

48-
`docs/avito/inventory.md` is the canonical mapping of every API operation to its SDK domain object and public method. Before implementing any new method, check the inventory to find:
49-
- which `пакет_sdk` and `доменный_объект` it belongs to
50-
- the expected `публичный_метод_sdk`, request/response type names
51-
- whether the operation is deprecated (`deprecated: да` → wrap in a legacy domain object)
50+
Public SDK methods are documented in `docs/site/reference/` and generated by the MkDocs reference builder from the actual package surface. All 204 operations from the specs must be covered. A missing method is a defect.
5251

53-
**When adding a new API method**: add it to the `## Операции` table in `docs/avito/inventory.md` (between the `operations-table:start/end` markers) following the existing format.
52+
## Swagger binding subsystem
5453

55-
All 204 operations from the specs must be covered. A missing method is a defect.
54+
The persistent subsystem context is documented in `docs/site/explanations/swagger-binding-subsystem.md`.
55+
56+
Core invariant:
57+
58+
```text
59+
each Swagger operation -> exactly one discovered binding
60+
each discovered SDK method -> exactly one Swagger operation
61+
```
62+
63+
Multiple Swagger bindings on one public SDK method are forbidden. If one public scenario covers different upstream modes, expose separate documented SDK methods and keep compatibility wrappers unbound.
64+
65+
When adding or changing a public method that corresponds to Avito API:
66+
67+
- consult `docs/avito/api/*.json` first;
68+
- add or update the public domain method, section client call, mapper and typed public models;
69+
- add `@swagger_operation(...)` on the public domain method;
70+
- do not put schemas, statuses, content types, request models, response models, error models, path params, or query params into the decorator;
71+
- add or update class-level Swagger metadata when introducing a domain class;
72+
- write a reference-ready docstring for the public method: business action, arguments, return model, pagination/dry-run/idempotency behavior when relevant, and common SDK exceptions;
73+
- update `docs/site/how-to/` or `docs/site/explanations/` if the method introduces a workflow or a non-obvious contract;
74+
- update `docs/site/explanations/swagger-binding-subsystem.md` when changing discovery, linter, JSON report, `SwaggerFakeTransport`, deprecated/legacy policy, or multi-operation binding policy.
75+
76+
Minimum verification for API-related changes:
77+
78+
```bash
79+
make swagger-lint
80+
poetry run pytest tests/core/test_swagger*.py tests/contracts/test_swagger_contracts.py
81+
poetry run pytest tests/domains/<domain>/
82+
poetry run mypy avito
83+
poetry run ruff check .
84+
```
85+
86+
Before completing an API-surface change, run `make check`. If generated docs, docs snippets, coverage pages, or reference output changed, also run `make docs-strict`.
5687

5788
## STYLEGUIDE.md — strict compliance is mandatory
5889

@@ -64,6 +95,9 @@ The most critical prohibitions that must never be violated:
6495
- Returning `dict` or `Any` from public methods.
6596
- Using `resource_id` instead of concrete names (`item_id`, `order_id`).
6697
- Annotating `list[T]` where `PaginatedList[T]` is returned at runtime.
98+
- Adding or changing an Avito API public method without a `@swagger_operation(...)` binding.
99+
- Adding or changing an Avito API public method without a reference-ready docstring.
100+
- Duplicating Swagger contract data inside binding decorators.
67101
- Making `AuthenticationError` a subclass of `AuthorizationError` (or vice versa).
68102
- Writing error messages in mixed languages (Russian only).
69103
- Injecting methods via `setattr`/`globals()` at runtime.

CONTRIBUTING.md

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,7 @@ TTFC показывает, за сколько минут новый польз
4141
4. Запустите секундомер.
4242
5. Выполните tutorial `getting-started.md` до успешного `get_self()`.
4343
6. Остановите секундомер и запишите результат в минутах.
44-
7. Перед сборкой отчёта передайте значение одним из способов:
44+
7. Запишите результат в release notes или changelog релиза.
4545

46-
```bash
47-
TTFC_MINUTES=8.5 make docs-report
48-
```
49-
50-
или:
51-
52-
```bash
53-
printf "8.5\n" > ttfc-minutes.txt
54-
make docs-report
55-
```
56-
57-
`ttfc-minutes.txt` не коммитится. В CI релизного прогона можно передать
58-
`--ttfc-minutes <value>` в `scripts/build_docs_quality_report.py`.
46+
`make docs-report` генерирует machine-readable Swagger bindings report для
47+
reference coverage; TTFC остаётся ручной release-проверкой.

Makefile

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export
44
REGISTRY=10.11.0.9:5000
55
MKDOCS_ENV=DISABLE_MKDOCS_2_WARNING=true NO_MKDOCS_2_WARNING=1
66

7-
check: test typecheck lint build
7+
check: test typecheck lint swagger-coverage build
88

99
build: clean
1010
poetry build
@@ -30,6 +30,15 @@ fmt:
3030
lint:
3131
poetry run ruff check .
3232

33+
swagger-update:
34+
poetry run python scripts/download_avito_api_specs.py --clean
35+
36+
swagger-lint: swagger-update
37+
poetry run python scripts/lint_swagger_bindings.py --strict
38+
39+
swagger-coverage: swagger-lint
40+
poetry run pytest tests/core/test_swagger.py tests/core/test_swagger_discovery.py tests/core/test_swagger_linter.py tests/core/test_swagger_report.py tests/core/test_swagger_registry.py tests/contracts/test_swagger_contracts.py
41+
3342
minor: check
3443
poetry version minor
3544

@@ -47,20 +56,13 @@ docs-serve:
4756

4857
docs-strict:
4958
$(MKDOCS_ENV) poetry run mkdocs build --strict
50-
poetry run python scripts/check_readme_domain_coverage.py
59+
poetry run python scripts/lint_swagger_bindings.py --strict
5160
poetry run pytest tests/docs/
5261

5362
docs-build: docs-strict
5463

5564
docs-report:
56-
poetry run python scripts/check_inventory_coverage.py --output inventory-coverage-report.json
57-
poetry run python scripts/check_spec_inventory_sync.py --output spec-inventory-report.json
58-
poetry run python scripts/check_reference_public_surface.py --output reference-public-report.json
59-
poetry run python scripts/check_public_docstrings.py --output docstring-contract-report.json
60-
poetry run python scripts/check_changelog_sections.py --output changelog-sections-report.json
61-
poetry run python scripts/check_docs_examples.py --output reference-explanation-examples-report.json
62-
poetry run bandit -r avito -lll -f json -o bandit-report.json
63-
poetry run python scripts/build_docs_quality_report.py
65+
poetry run python scripts/lint_swagger_bindings.py --json --strict --output swagger-bindings-report.json
6466

6567
docs-check: docs-strict
6668
ln -sfn . site/avito_python_api

README.md

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,28 @@
33
[![CI](https://github.com/p141592/avito_python_api/actions/workflows/ci.yml/badge.svg)](https://github.com/p141592/avito_python_api/actions/workflows/ci.yml)
44
[![Coverage Status](https://coveralls.io/repos/github/p141592/avito_python_api/badge.svg?branch=main)](https://coveralls.io/github/p141592/avito_python_api?branch=main)
55
[![PyPI Downloads](https://img.shields.io/pypi/dm/avito-py.svg)](https://pypi.org/project/avito-py/)
6-
[![API coverage](https://img.shields.io/badge/API%20coverage-204%2F204-success)](docs/avito/inventory.md)
76
[![Docs](https://img.shields.io/badge/docs-latest-blue)](https://p141592.github.io/avito_python_api/)
87

9-
`avito-py` — синхронный Python SDK для работы с Avito API через единый объектный фасад `AvitoClient`.
8+
Отчёт покрытия Avito API: [покрытие API](https://p141592.github.io/avito_python_api/reference/api-report/).
109

11-
Цели SDK:
10+
## Быстрый старт
1211

13-
- скрыть transport, OAuth и retry-логику от пользовательского кода;
14-
- возвращать типизированные `dataclass`-модели вместо сырого JSON;
15-
- дать единый вход в доменные сценарии вида `avito.ad(...).get()` и `avito.chat(...).send_message(...)`;
16-
- покрыть все swagger-документы из каталога [docs/avito/api](docs/avito/api).
12+
Получение ключей — https://www.avito.ru/professionals/api
1713

18-
SDK является синхронным. Любая асинхронная поддержка, если она появится, будет жить в отдельном namespace `avito.aio` и никогда не будет смешана с sync-классами в одном модуле.
14+
```python
15+
from avito import AvitoClient
1916

20-
Каталог [docs/avito/api](docs/avito/api) рассматривается как upstream API contract. Эти файлы не редактируются вручную при развитии SDK: публичные модели, мапперы и тесты должны подстраиваться под documented shape из `docs/avito/api/*`.
17+
with AvitoClient.from_env() as avito:
18+
profile = avito.account().get_self()
19+
ad = avito.ad(item_id=42, user_id=123).get()
20+
21+
print(profile.name)
22+
print(ad.title)
23+
```
24+
25+
По умолчанию настройки читаются из переменных окружения с префиксом `AVITO_`.
26+
27+
`avito-py` — синхронный Python SDK для работы с Avito API через единый объектный фасад `AvitoClient`.
2128

2229
## Установка
2330

@@ -33,23 +40,6 @@ pip install avito-py
3340

3441
Требование к интерпретатору: Python `3.14` и выше в рамках ветки `3.x`. Репозиторий и релизный контур валидируются именно на Python `3.14`.
3542

36-
## Быстрый старт
37-
38-
Получение ключей — https://www.avito.ru/professionals/api
39-
40-
```python
41-
from avito import AvitoClient
42-
43-
with AvitoClient.from_env() as avito:
44-
profile = avito.account().get_self()
45-
ad = avito.ad(item_id=42, user_id=123).get()
46-
47-
print(profile.name)
48-
print(ad.title)
49-
```
50-
51-
По умолчанию настройки читаются из переменных окружения с префиксом `AVITO_`.
52-
5343
## Инициализация клиента
5444

5545
SDK предоставляет три нормативных способа создания клиента — от самого простого к самому явному.
@@ -374,4 +364,4 @@ git push origin v1.0.2
374364
## Документация репозитория
375365

376366
- [STYLEGUIDE.md](STYLEGUIDE.md) — нормативные архитектурные правила
377-
- [docs/avito/inventory.md](docs/avito/inventory.md)матрица соответствия swagger-операций и публичного API SDK
367+
- [docs/site/reference](docs/site/reference)справочник публичного API SDK

0 commit comments

Comments
 (0)