Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,20 @@
"Bash(grep -n \"^\\\\`\\\\`\\\\`\" /Users/n.baryshnikov/Projects/avito_python_api/docs/site/how-to/security-practices.md)",
"Bash(pip show *)",
"Bash(awk -F'|' '{gsub\\(/^ +| +$/,\"\",$2\\); gsub\\(/^ +| +$/,\"\",$6\\); print $2 \":\" $6}')",
"Bash(make qa-docs *)"
"Bash(make qa-docs *)",
"WebFetch(domain:developers.avito.ru)",
"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\")",
"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\")",
"Bash(grep -oE '\"\\(/[a-z0-9_-]+\\){2,}/[a-z0-9_-]+\"')",
"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\")",
"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\")",
"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\")",
"Bash(curl -s -o /dev/null -w \"%{http_code}\" --max-time 10 \"https://api.avito.ru/docs/public/messenger.yaml\")",
"Bash(curl -s -o /dev/null -w \"%{http_code}\" --max-time 10 \"https://developers.avito.ru/swagger/messenger.yaml\")",
"Bash(curl -s -o /dev/null -w \"%{http_code}\" --max-time 10 \"https://developers.avito.ru/api-catalog/messenger/swagger.json\")",
"Bash(curl -s --max-time 10 \"https://developers.avito.ru/swagger/messenger.yaml\")",
"Bash(curl -s --max-time 10 \"https://developers.avito.ru/api-catalog/messenger/swagger.json\")",
"Bash(awk -F'|' '{print $15}')"
]
}
}
4 changes: 2 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Проверки

- [ ] `make check` проходит локально или в CI.
- [ ] `make docs-strict` проходит, если изменены README, docs, публичные сигнатуры или inventory.
- [ ] `make docs-strict` проходит, если изменены README, docs, публичные сигнатуры или Swagger bindings.
- [ ] README/tutorials/how-to примеры соответствуют актуальным публичным сигнатурам SDK.
- [ ] Новая публичная операция добавлена в `docs/avito/inventory.md` и покрыта reference.
- [ ] Новая публичная операция связана со Swagger operation binding и покрыта reference.
- [ ] Публичное переименование: alias сохранён, `DeprecationWarning` добавлен, `CHANGELOG.md` обновлён в секции `Deprecated`.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ jobs:
- name: Install dependencies
run: poetry install --no-interaction --with docs

- name: Run strict Swagger coverage gate
run: make swagger-coverage

- name: Run quality gate
run: make check

Expand Down
24 changes: 2 additions & 22 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,7 @@ jobs:
run: make docs-strict

- name: Build docs reports
run: |
poetry run python scripts/check_inventory_coverage.py --output inventory-coverage-report.json
poetry run python scripts/check_spec_inventory_sync.py --output spec-inventory-report.json
poetry run python scripts/check_reference_public_surface.py --output reference-public-report.json
poetry run python scripts/check_public_docstrings.py --output docstring-contract-report.json
poetry run python scripts/check_changelog_sections.py --output changelog-sections-report.json
poetry run bandit -r avito -lll -f json -o bandit-report.json
poetry run python scripts/build_docs_quality_report.py \
--inventory-report inventory-coverage-report.json \
--spec-report spec-inventory-report.json \
--reference-report reference-public-report.json \
--docstring-report docstring-contract-report.json \
--changelog-report changelog-sections-report.json \
--bandit-report bandit-report.json \
--output docs-quality-report.json
run: make docs-report

- name: Prepare local docs root for link checking
run: ln -s . site/avito_python_api
Expand All @@ -64,13 +50,7 @@ jobs:
with:
name: docs-contract-reports
path: |
inventory-coverage-report.json
spec-inventory-report.json
reference-public-report.json
docstring-contract-report.json
changelog-sections-report.json
bandit-report.json
docs-quality-report.json
swagger-bindings-report.json

- name: Check links
uses: lycheeverse/lychee-action@v2
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ jobs:
TAG_VERSION="${GITHUB_REF_NAME#v}"
poetry version "$TAG_VERSION"

- name: Run strict Swagger coverage gate
run: make swagger-coverage

- name: Run quality gate
run: make check

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
swagger-bindings-report.json
htmlcov/
.tox/
.nox/
Expand Down
50 changes: 42 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
make test # run all tests
make typecheck # mypy strict check on avito/
make lint # ruff check
make swagger-lint # strict Swagger binding coverage check
make fmt # ruff format
make check # test → typecheck → lint → build (full gate)
make check # test → typecheck → lint → swagger-lint → build (full gate)
make build # poetry build

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

**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.

## API coverage and inventory
## API coverage

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

`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:
- which `пакет_sdk` and `доменный_объект` it belongs to
- the expected `публичный_метод_sdk`, request/response type names
- whether the operation is deprecated (`deprecated: да` → wrap in a legacy domain object)
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.

**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.
## Swagger binding subsystem

All 204 operations from the specs must be covered. A missing method is a defect.
The persistent subsystem context is documented in `docs/site/explanations/swagger-binding-subsystem.md`.

Core invariant:

```text
each Swagger operation -> exactly one discovered binding
each discovered SDK method -> exactly one Swagger operation
```

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.

When adding or changing a public method that corresponds to Avito API:

- consult `docs/avito/api/*.json` first;
- add or update the public domain method, section client call, mapper and typed public models;
- add `@swagger_operation(...)` on the public domain method;
- do not put schemas, statuses, content types, request models, response models, error models, path params, or query params into the decorator;
- add or update class-level Swagger metadata when introducing a domain class;
- 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;
- update `docs/site/how-to/` or `docs/site/explanations/` if the method introduces a workflow or a non-obvious contract;
- update `docs/site/explanations/swagger-binding-subsystem.md` when changing discovery, linter, JSON report, `SwaggerFakeTransport`, deprecated/legacy policy, or multi-operation binding policy.

Minimum verification for API-related changes:

```bash
make swagger-lint
poetry run pytest tests/core/test_swagger*.py tests/contracts/test_swagger_contracts.py
poetry run pytest tests/domains/<domain>/
poetry run mypy avito
poetry run ruff check .
```

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`.

## STYLEGUIDE.md — strict compliance is mandatory

Expand All @@ -64,6 +95,9 @@ The most critical prohibitions that must never be violated:
- Returning `dict` or `Any` from public methods.
- Using `resource_id` instead of concrete names (`item_id`, `order_id`).
- Annotating `list[T]` where `PaginatedList[T]` is returned at runtime.
- Adding or changing an Avito API public method without a `@swagger_operation(...)` binding.
- Adding or changing an Avito API public method without a reference-ready docstring.
- Duplicating Swagger contract data inside binding decorators.
- Making `AuthenticationError` a subclass of `AuthorizationError` (or vice versa).
- Writing error messages in mixed languages (Russian only).
- Injecting methods via `setattr`/`globals()` at runtime.
Expand Down
17 changes: 3 additions & 14 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,7 @@ TTFC показывает, за сколько минут новый польз
4. Запустите секундомер.
5. Выполните tutorial `getting-started.md` до успешного `get_self()`.
6. Остановите секундомер и запишите результат в минутах.
7. Перед сборкой отчёта передайте значение одним из способов:
7. Запишите результат в release notes или changelog релиза.

```bash
TTFC_MINUTES=8.5 make docs-report
```

или:

```bash
printf "8.5\n" > ttfc-minutes.txt
make docs-report
```

`ttfc-minutes.txt` не коммитится. В CI релизного прогона можно передать
`--ttfc-minutes <value>` в `scripts/build_docs_quality_report.py`.
`make docs-report` генерирует machine-readable Swagger bindings report для
reference coverage; TTFC остаётся ручной release-проверкой.
22 changes: 12 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export
REGISTRY=10.11.0.9:5000
MKDOCS_ENV=DISABLE_MKDOCS_2_WARNING=true NO_MKDOCS_2_WARNING=1

check: test typecheck lint build
check: test typecheck lint swagger-coverage build

build: clean
poetry build
Expand All @@ -30,6 +30,15 @@ fmt:
lint:
poetry run ruff check .

swagger-update:
poetry run python scripts/download_avito_api_specs.py --clean

swagger-lint: swagger-update
poetry run python scripts/lint_swagger_bindings.py --strict

swagger-coverage: swagger-lint
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

minor: check
poetry version minor

Expand All @@ -47,20 +56,13 @@ docs-serve:

docs-strict:
$(MKDOCS_ENV) poetry run mkdocs build --strict
poetry run python scripts/check_readme_domain_coverage.py
poetry run python scripts/lint_swagger_bindings.py --strict
poetry run pytest tests/docs/

docs-build: docs-strict

docs-report:
poetry run python scripts/check_inventory_coverage.py --output inventory-coverage-report.json
poetry run python scripts/check_spec_inventory_sync.py --output spec-inventory-report.json
poetry run python scripts/check_reference_public_surface.py --output reference-public-report.json
poetry run python scripts/check_public_docstrings.py --output docstring-contract-report.json
poetry run python scripts/check_changelog_sections.py --output changelog-sections-report.json
poetry run python scripts/check_docs_examples.py --output reference-explanation-examples-report.json
poetry run bandit -r avito -lll -f json -o bandit-report.json
poetry run python scripts/build_docs_quality_report.py
poetry run python scripts/lint_swagger_bindings.py --json --strict --output swagger-bindings-report.json

docs-check: docs-strict
ln -sfn . site/avito_python_api
Expand Down
44 changes: 17 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,28 @@
[![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)
[![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)
[![PyPI Downloads](https://img.shields.io/pypi/dm/avito-py.svg)](https://pypi.org/project/avito-py/)
[![API coverage](https://img.shields.io/badge/API%20coverage-204%2F204-success)](docs/avito/inventory.md)
[![Docs](https://img.shields.io/badge/docs-latest-blue)](https://p141592.github.io/avito_python_api/)

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

Цели SDK:
## Быстрый старт

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

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

Каталог [docs/avito/api](docs/avito/api) рассматривается как upstream API contract. Эти файлы не редактируются вручную при развитии SDK: публичные модели, мапперы и тесты должны подстраиваться под documented shape из `docs/avito/api/*`.
with AvitoClient.from_env() as avito:
profile = avito.account().get_self()
ad = avito.ad(item_id=42, user_id=123).get()

print(profile.name)
print(ad.title)
```

По умолчанию настройки читаются из переменных окружения с префиксом `AVITO_`.

`avito-py` — синхронный Python SDK для работы с Avito API через единый объектный фасад `AvitoClient`.

## Установка

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

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

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

Получение ключей — https://www.avito.ru/professionals/api

```python
from avito import AvitoClient

with AvitoClient.from_env() as avito:
profile = avito.account().get_self()
ad = avito.ad(item_id=42, user_id=123).get()

print(profile.name)
print(ad.title)
```

По умолчанию настройки читаются из переменных окружения с префиксом `AVITO_`.

## Инициализация клиента

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

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