# Architecture β€” kwork-api ## πŸ“ ΠžΠ±Π·ΠΎΡ€ **kwork-api** β€” асинхронный Python ΠΊΠ»ΠΈΠ΅Π½Ρ‚ для Kwork.ru API с ΠΏΠΎΠ»Π½ΠΎΠΉ Ρ‚ΠΈΠΏΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ ΠΈ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ. --- ## πŸ—οΈ АрхитСктура ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ User Application β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ KworkClient β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Authentication Layer β”‚ β”‚ β”‚ β”‚ - login() / token auth β”‚ β”‚ β”‚ β”‚ - Session management β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ API Groups β”‚ β”‚ β”‚ β”‚ - catalog, projects, user, reference, ... β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ HTTP Layer (httpx) β”‚ β”‚ β”‚ β”‚ - HTTP/2 support β”‚ β”‚ β”‚ β”‚ - Timeout handling β”‚ β”‚ β”‚ β”‚ - Error handling β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Kwork.ru API (HTTPS) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## πŸ“ Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° ``` kwork-api/ β”œβ”€β”€ src/kwork_api/ β”‚ β”œβ”€β”€ __init__.py # Public API β”‚ β”œβ”€β”€ client.py # KworkClient + API groups β”‚ β”œβ”€β”€ models.py # Pydantic models β”‚ └── errors.py # Exception classes β”‚ β”œβ”€β”€ tests/ β”‚ β”œβ”€β”€ test_client.py # Client tests β”‚ β”œβ”€β”€ test_models.py # Model tests β”‚ └── test_all_endpoints.py # Endpoint tests β”‚ β”œβ”€β”€ docs/ β”‚ β”œβ”€β”€ index.md # Quick start β”‚ β”œβ”€β”€ api-reference.md # API docs β”‚ β”œβ”€β”€ RELEASE.md # Release guide β”‚ └── ARCHITECTURE.md # This file β”‚ β”œβ”€β”€ .github/workflows/ β”‚ └── ci.yml # CI/CD pipeline β”‚ β”œβ”€β”€ pyproject.toml # Project config β”œβ”€β”€ uv.lock # Dependencies lock └── README.md # Main documentation ``` --- ## πŸ”‘ ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ### 1. KworkClient **ΠžΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π΅Π½Π½ΠΎΡΡ‚ΡŒ:** ОсновноС взаимодСйствиС с API **Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ:** - АутСнтификация (login / token) - Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ сСссиСй - Π”Π΅Π»Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ API Π³Ρ€ΡƒΠΏΠΏΠ°ΠΌ **API Groups:** ```python client.catalog # CatalogAPI client.projects # ProjectsAPI client.user # UserAPI client.reference # ReferenceAPI client.notifications # NotificationsAPI client.other # OtherAPI ``` --- ### 2. Models (Pydantic) **ΠžΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π΅Π½Π½ΠΎΡΡ‚ΡŒ:** Валидация ΠΈ типизация ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ² API **ΠšΠ°Ρ‚Π΅Π³ΠΎΡ€ΠΈΠΈ:** - **User models:** KworkUser, AuthResponse - **Kwork models:** Kwork, KworkDetails, KworkCategory - **Project models:** Project, ProjectsResponse - **Review models:** Review, ReviewsResponse - **Notification models:** Notification, Dialog - **Reference models:** City, Country, TimeZone, Feature, Badge - **Error models:** ErrorDetail, APIErrorResponse --- ### 3. Errors **ΠžΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π΅Π½Π½ΠΎΡΡ‚ΡŒ:** ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок API **Π˜Π΅Ρ€Π°Ρ€Ρ…ΠΈΡ:** ``` KworkError (base) β”œβ”€β”€ KworkAuthError # 401, 403 β”œβ”€β”€ KworkApiError # 4xx, 5xx β”‚ β”œβ”€β”€ KworkNotFoundError # 404 β”‚ β”œβ”€β”€ KworkRateLimitError # 429 β”‚ └── KworkValidationError # 400 └── KworkNetworkError # Network issues ``` --- ### 4. HTTP Layer (httpx) **ΠžΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π΅Π½Π½ΠΎΡΡ‚ΡŒ:** HTTP запросы **Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ:** - HTTP/2 ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° - Π’Π°ΠΉΠΌΠ°ΡƒΡ‚Ρ‹ - Cookies management - Token authentication - Error handling --- ## πŸ”„ Flow: АутСнтификация ``` User β†’ KworkClient.login(username, password) β”‚ β–Ό POST /signIn (cookies) β”‚ β–Ό POST /getWebAuthToken (token) β”‚ β–Ό Store token + cookies β”‚ β–Ό Return authenticated client ``` --- ## πŸ”„ Flow: API Request ``` User β†’ client.catalog.get_list(page=1) β”‚ β–Ό CatalogAPI.get_list() β”‚ β–Ό KworkClient._request() β”‚ β–Ό httpx.AsyncClient.post() β”‚ β–Ό KworkClient._handle_response() β”‚ β–Ό CatalogResponse.model_validate() β”‚ β–Ό Return typed response ``` --- ## πŸš€ CI/CD Pipeline ``` Push/Tag β†’ GitHub Actions β”‚ β”œβ”€β”€ Test Job β”‚ β”œβ”€β”€ Install UV + Python β”‚ β”œβ”€β”€ Run linters (ruff) β”‚ β”œβ”€β”€ Run tests (pytest) β”‚ └── Upload coverage β”‚ β”œβ”€β”€ Build Job β”‚ β”œβ”€β”€ Build wheel + sdist β”‚ └── Upload artifacts β”‚ β”œβ”€β”€ Publish Job (on tag) β”‚ β”œβ”€β”€ Download artifacts β”‚ └── Publish to Gitea Registry β”‚ └── Docs Job β”œβ”€β”€ Build MkDocs └── Upload site ``` --- ## πŸ“Š Зависимости ### Runtime - `httpx[http2]>=0.26.0` β€” HTTP client - `pydantic>=2.0.0` β€” Data validation - `structlog>=24.0.0` β€” Logging ### Development - `pytest>=8.0.0` β€” Testing - `pytest-cov>=4.0.0` β€” Coverage - `pytest-asyncio>=0.23.0` β€” Async tests - `respx>=0.20.0` β€” HTTP mocking - `ruff>=0.3.0` β€” Linting - `mkdocs + mkdocstrings` β€” Documentation --- ## πŸ”’ Π‘Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ - **Π’ΠΎΠΊΠ΅Π½Ρ‹:** НС ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ΡΡ Π² Π»ΠΎΠ³Π°Ρ… - **ΠŸΠ°Ρ€ΠΎΠ»ΠΈ:** ΠŸΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ login() - **БСссии:** Token + cookies хранятся Π² ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π΅ - **HTTPS:** ВсС запросы Ρ‡Π΅Ρ€Π΅Π· HTTPS --- ## πŸ“ˆ ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ - **Async/Await:** ΠΠ΅Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ запросы - **HTTP/2:** Multiplexing запросов - **Connection pooling:** ΠŸΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ соСдинСний - **Timeouts:** Π—Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ зависаний --- ## πŸ§ͺ ВСстированиС - **Unit тСсты:** 92% coverage - **Mock HTTP:** respx для изоляции - **Async tests:** pytest-asyncio - **CI:** АвтоматичСский ΠΏΡ€ΠΎΠ³ΠΎΠ½ ΠΏΡ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΊΠΎΠΌΠΌΠΈΡ‚Π΅ --- ## πŸ“ ЛицСнзия MIT License β€” свободноС использованиС с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ΠΌ авторства.