Skip to content

Commit 31bb2f8

Browse files
authored
Stabling (#1)
Полное покрытие API Обработка ошибок Пагинация
1 parent 2c45b20 commit 31bb2f8

131 files changed

Lines changed: 8944 additions & 5958 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: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(python3 *)",
5+
"Bash(find *)",
6+
"Bash(make typecheck *)",
7+
"Bash(make test *)",
8+
"Bash(make check *)",
9+
"Bash(.venv/bin/ruff check *)",
10+
"Bash(.venv/bin/ruff format *)",
11+
"Bash(.venv/bin/pytest tests/ -q)",
12+
"Bash(python *)",
13+
"Bash(git stash *)",
14+
"Bash(poetry run *)",
15+
"Bash(make lint *)"
16+
]
17+
}
18+
}

AGENTS.md

Lines changed: 0 additions & 53 deletions
This file was deleted.

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CLAUDE.md

CHANGELOG.md

Lines changed: 0 additions & 28 deletions
This file was deleted.

CLAUDE.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Commands
6+
7+
```bash
8+
make test # run all tests
9+
make typecheck # mypy strict check on avito/
10+
make lint # ruff check
11+
make fmt # ruff format
12+
make check # test → typecheck → lint → build (full gate)
13+
make build # poetry build
14+
15+
# single test
16+
poetry run pytest tests/test_facade.py::test_name
17+
```
18+
19+
## Architecture
20+
21+
**Entry point**: `avito/client.py``AvitoClient` is the single public facade. It exposes factory methods (`account()`, `ad()`, `chat()`, etc.) that return domain objects.
22+
23+
**Layers** (strict separation, no mixing):
24+
25+
| Layer | Location | Responsibility |
26+
|---|---|---|
27+
| `AvitoClient` | `avito/client.py` | Public facade, factory methods |
28+
| `SectionClient` | `avito/<domain>/client.py` | HTTP calls for one API section |
29+
| `Transport` | `avito/core/transport.py` | httpx, retries, error mapping, token injection |
30+
| `AuthProvider` | `avito/auth/provider.py` | Token cache, refresh, 401 handling |
31+
| `Mapper` | `avito/<domain>/mappers.py` | JSON → typed dataclass |
32+
| Config | `avito/config.py`, `avito/auth/settings.py` | `AvitoSettings`, `AuthSettings` |
33+
34+
**Domain packages** follow a uniform structure: `__init__.py`, `domain.py` (DomainObject subclass), `client.py` (SectionClient), `models.py` (frozen dataclasses), `mappers.py`, optional `enums.py`.
35+
36+
**Public models** are `@dataclass(slots=True, frozen=True)`, inherit `SerializableModel` (provides `to_dict()` / `model_dump()`), and never expose transport fields.
37+
38+
**Exceptions** live in `avito/core/exceptions.py`. `AvitoError` is the base. HTTP codes map to specific types: 401→`AuthenticationError`, 403→`AuthorizationError`, 429→`RateLimitError`, etc. These two are siblings, not parent/child.
39+
40+
**Pagination**: `PaginatedList[T]` is lazy. First page loads on creation; subsequent pages load on iteration. `materialize()` loads all pages.
41+
42+
**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.
43+
44+
## API coverage and inventory
45+
46+
`docs/` contains Swagger/OpenAPI specs (23 documents, 204 operations) — the authoritative source of truth for all API contracts.
47+
48+
`docs/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)
52+
53+
**When adding a new API method**: add it to the `## Операции` table in `docs/inventory.md` (between the `operations-table:start/end` markers) following the existing format.
54+
55+
All 204 operations from the specs must be covered. A missing method is a defect.
56+
57+
## STYLEGUIDE.md — strict compliance is mandatory
58+
59+
`STYLEGUIDE.md` is a normative document. All code changes **must** comply with it. When there is a conflict between any consideration and the STYLEGUIDE, the STYLEGUIDE takes priority.
60+
61+
The most critical prohibitions that must never be violated:
62+
63+
- Mixing layers: transport/auth/parsing/domain logic in one class.
64+
- Returning `dict` or `Any` from public methods.
65+
- Using `resource_id` instead of concrete names (`item_id`, `order_id`).
66+
- Annotating `list[T]` where `PaginatedList[T]` is returned at runtime.
67+
- Making `AuthenticationError` a subclass of `AuthorizationError` (or vice versa).
68+
- Writing error messages in mixed languages (Russian only).
69+
- Injecting methods via `setattr`/`globals()` at runtime.
70+
- Duplicating behavior through two different public methods without deprecation.
71+
- Leaking internal-layer request-DTOs into public signatures.
72+
- Adding dead code: unused imports, type aliases, TypeVars.
73+
74+
## Key conventions (from STYLEGUIDE.md)
75+
76+
- All public methods return typed SDK models, never raw `dict`.
77+
- Field names are concrete: `item_id`, `user_id` — never `resource_id`.
78+
- Public method arguments are primitives or domain models — internal request-DTOs must not leak out.
79+
- Write-operations that accept `dry_run: bool = False` must build the same payload in both modes; with `dry_run=True` transport must not be called.
80+
- `Any` is forbidden except at JSON boundary layers (with a local comment).
81+
- Error messages are written in Russian only — no mixed languages.
82+
- No dynamic method injection (`setattr`, `globals()` patching).
83+
- `PaginatedList[T]` annotation must match runtime — never annotate as `list[T]` if you return `PaginatedList[T]`.
84+
- `AuthenticationError` (401) and `AuthorizationError` (403) must not be in an inheritance relation.
85+
- Dead code (unused imports, aliases, TypeVars) must be removed.
86+
- Request-objects of the internal layer must not appear in public domain-method signatures.

0 commit comments

Comments
 (0)