Skip to main content

adapterkit

Тонкий коннектор сетевых адаптеров поверх librarykit. adapterkit отвечает на один вопрос: «как подключить сетевой адаптер к приложению». Он даёт декларативный контракт плагина, реестр с автодискавери через entry-points и базовый фасад адаптера — а весь сетевой движок (transport/auth/retry/errmap/ pagination/sessions/antibot/browser) реэкспортирует из librarykit, не дублируя его. Пишется один раз, переиспользуется любым доменным пакетом.

librarykit   ← КОРЕНЬ: весь сетевой движок (transport/auth/retry/errmap/
                        pagination/sessions/antibot/browser)
   ▲
adapterkit   ← ЭТОТ КИТ: контракт NetworkAdapter + registry (entry-points) +
                        BaseAdapter + orchestration_api.
                        Остальное — тонкий реэкспорт-шим из librarykit.
   ▲
домен        ← конкретные адаптеры (endpoint-таблица + мапперы на сеть)

Зависимости направлены только внутрь: adapterkit зависит только от librarykit, но НЕ от домена и НЕ от clikit (онион-граф librarykit <- adapterkit <- clikit: clikit — слой ВЫШЕ, adapterkit его не импортит). Адаптеры кодируются против стабильных typing.Protocol из adapterkit.contract (структурный контракт, а не наследование от домена). Композиция конкретных реализаций — единственный composition root на приложение.

Установка

uv add s-adapterkit

Имя дистрибутива — s-adapterkit, имя для импорта — adapterkit. librarykit подтянется автоматически как транзитивная зависимость.

Опциональные extra:

uv add "s-adapterkit[browser]"   # Playwright — browser-login
uv add "s-adapterkit[antibot]"   # curl-cffi — JA3-impersonate
uv add "s-adapterkit[oauth]"     # authlib — OAuth2-flows

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

Описать адаптер декларативно и зарегистрировать его в реестре:

from adapterkit import BaseAdapter, Endpoint, register_adapter

class TwitterAdapter(BaseAdapter):
    api_version = 1
    endpoints = {
        "search": Endpoint(name="search", method="GET", path="/2/tweets/search/recent"),
    }

register_adapter("twitter", TwitterAdapter)

Либо отдать адаптер на автодискавери — объявить entry-point в своём pyproject.toml, и любой потребитель adapterkit подхватит его без явного импорта:

[project.entry-points."adapterkit.adapters"]
twitter = "my_package.adapter:TwitterAdapter"
from adapterkit import discover_adapters, get_adapter_class

discover_adapters()                       # загрузить все плагины из entry-points
cls = get_adapter_class("twitter")        # получить класс по имени сервиса

Карта модулей

Модуль Назначение Реализация
contract.py граничные Protocol (NetworkAdapter/Transport/Auth/ErrorMapper/Paginator/SessionStoreProtocol) + DTO (Endpoint/RequestSpec/SessionRef/Creds) + ADAPTER_API_VERSION/MIN_SUPPORTED_API_VERSION контракт коннектора
registry.py AdapterRegistry + автодискавери через entry-points adapterkit.adapters, ленивая загрузка, ручная регистрация код коннектора
base.py BaseAdapter (описание запроса build_request + исполнение execute) + ресурс-под-сервисы (ContentResource/CommentsResource/MetricsResource/SearchResource) — Stripe-стиль фасад код коннектора
throttle.py ядро само троттлит плагин по его метаданным: @ratelimit, ServiceThrottle, ManagedExecutor, шов ExecutionContext код коннектора
orchestration_api.py тонкий registry-driven API: onboard_all / health_check_all (без импортов домена) код коннектора
onboarding_contract.py онбординг/health-контракты (LoginMode/OnboardingProtocol/HealthProtocol, api_version 2) реэкспорт librarykit.protocols
errors.py единая иерархия ошибок реэкспорт librarykit.errors
retry.py header-driven RetryPolicy реэкспорт librarykit.retry
transport.py / client.py HttpxTransport + choke-point HttpClient реэкспорт librarykit.transport
auth.py TokenAuth/OAuth2Auth/CookieSessionAuth/BrowserLoginAuth реэкспорт librarykit.auth
errmap.py декларативная карта ответ → доменная ошибка реэкспорт librarykit.errmap
pagination.py CursorPaginator (offset/cursor/page) реэкспорт librarykit.pagination
sessions.py envelope-шифрованный SessionStore реэкспорт librarykit.sessions
antibot.py выбор транспорта Tier 0-4 (curl-cffi JA3 / CDP) ленивый реэкспорт librarykit.antibot
browser.py warm/cold-login (требует extra browser) ленивый реэкспорт librarykit.browser

Всё, что помечено «реэкспорт», — тонкий shim: единая реализация живёт в librarykit, adapterkit лишь предоставляет её под привычным именем. Собственный код коннектора — только contract/registry/base/throttle/orchestration_api.

Ядро само держит лимиты плагина

Плагин объявляет лимиты ОДНОЙ строкой метаданных и не пишет кода лимитов, ретраев и удержания сессии — очередь запросов и exponential backoff делает ядро:

from adapterkit import BaseAdapter, Endpoint, ratelimit

@ratelimit(calls=2, period=1)          # ← всё, что плагин пишет про лимиты
class ExampleAdapter(BaseAdapter):
    service = "example"
    endpoints = {"get_item": Endpoint("get_item", "GET", "/items/{item_id}",
                                      required_params=("item_id",))}

Полная инструкция (формы декларации, оси квот QuotaScope, инварианты, чек-лист для кодогенератора) — docs/PLUGIN_LIMITS.md. Адаптер БЕЗ объявленных лимитов работает ровно как раньше: исполнитель ядра не собирается, запросы уходят в клиент напрямую.

Плагины-способности: единая группа skillery.plugins

Кроме ПОЛНОГО адаптера сети кит несёт вторую, независимую ось подключения — capability: одна способность, один-два метода, ресурсы приходят аргументом ctx: ExecutionContext (плагин не читает окружение).

from adapterkit import PluginRegistry, PublisherProtocol

registry = PluginRegistry()
registry.capabilities()                              # имена БЕЗ импорта чужих пакетов
registry.plugins_supporting(PublisherProtocol)       # {capability_id: КЛАСС}, без инстанцирования

Формы (PluginProtocol / PublisherProtocol / TranscriberProtocol / IngestProtocol), версия-гейт PLUGIN_API_VERSION, мост AdapterCapability поверх существующего адаптера и чек-лист публикации — docs/PLUGIN_CONTRACT.md. Прежние группы (adapterkit.adapters, transcribe.channels) не переименованы и работают как раньше — новая ось добавлена рядом, а не вместо.

Ядро не тянет EXTENSIONS (ленивые слои)

Антибот и браузер — тяжёлые опциональные слои (extras antibot/browser), поэтому import adapterkit их не загружает: реэкспорт идёт через module-level __getattr__ (PEP 562) и срабатывает на первом обращении к имени. Практически:

import adapterkit                      # librarykit.antibot / .browser НЕ загружены
adapterkit.HttpClient                  # ядро — как раньше
adapterkit.CurlCffiTransport           # ← вот здесь подгрузится librarykit.antibot
from adapterkit.browser import warm_or_autologin   # ← и здесь librarykit.browser

Публичный API не изменился: from adapterkit import CurlCffiTransport, from adapterkit.antibot import ..., from adapterkit.browser import ..., from adapterkit import * и dir(adapterkit) работают идентично. Инвариант закреплён fitness-тестами в tests/test_lazy_extensions.py (замер sys.modules в отдельном интерпретаторе).

Архитектурные гейты

Канон держится инструментом, а не договорённостью. Онион-граф, ленивая граница ЯДРО/РАСШИРЕНИЯ и отсутствие скрытых зависимостей проверяются одной командой:

uv run --extra dev lint-imports

Базовый слой — зрелый import-linter; два измерения, которых у него нет, добавлены его же механизмом плагинов (adapterkit.gates.contracts):

  • eager_forbidden — ядро не поднимает librarykit.browser / librarykit.antibot в момент импорта. Ленивый доступ (импорт внутри функции, PEP 562 __getattr__, if TYPE_CHECKING:) нарушением не считается — встроенный forbidden этого не различает;
  • declared_dependencies — всё импортируемое объявлено в pyproject.toml (dependencies либо любой extra).

Рядом — conformance-наборы, которые чужой репозиторий подключает тремя строками: AdapterContractTests (контракт NetworkAdapter) и PluginConformanceTests (контракт способности: capability_id = имя entry-point, ctx первым аргументом, лимиты метаданными, никакой инфраструктуры внутри плагина).

Полное описание, инструкция «как подключить у себя» и таблица «сработало — что делать» — docs/ARCHITECTURE_GATES.md.

Новый навык за одну команду

python -m adapterkit new-skill myskill --capability publish

Порождает пакет, который уже соблюдает канон: способность с ctx-аргументом, лимиты через @ratelimit, entry-point в группе skillery.plugins под тем же именем, что capability_id, все четыре гейта в pyproject.toml и готовый conformance-тест. Сгенерированный навык проходит pytest, ruff и lint-imports без единой правки — это закреплено тестами скаффолда.

Разработка

uv sync --extra dev
uv run --extra dev pytest -q
uv run --extra dev ruff check adapterkit
uv run --extra dev lint-imports

librarykit тянется из публичной группы gitlab.com/S-kits. Для локальной правки кита временно укажите path-источник в [tool.uv.sources] (см. комментарий в pyproject.toml) и выполните uv lock --upgrade.

Лицензия

MIT © 2026 Dmitry.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

s_adapterkit-0.1.6.tar.gz (259.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

s_adapterkit-0.1.6-py3-none-any.whl (166.5 kB view details)

Uploaded Python 3

File details

Details for the file s_adapterkit-0.1.6.tar.gz.

File metadata

  • Download URL: s_adapterkit-0.1.6.tar.gz
  • Upload date:
  • Size: 259.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for s_adapterkit-0.1.6.tar.gz
Algorithm Hash digest
SHA256 b89968ac0fefb0c0ed3533b127a9296afc585280e3000be4a7346631d02d4c4c
MD5 a9bf9e835b0b49b8858be21a30c62440
BLAKE2b-256 964ab3b5405b8adce6c8dfa4d12ff542e3001929fd364bfccda8dd3835f4cd2a

See more details on using hashes here.

File details

Details for the file s_adapterkit-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: s_adapterkit-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 166.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for s_adapterkit-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 521ba49bae829b412883677c17970e7561702affc52fcbedc7bfad5eee8423b7
MD5 e52ff645282d5490238787c93507857e
BLAKE2b-256 9638fa166bcbff811332aba7e2b44098fd876b1af6f59feb0283f562957ea1e3

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.15

2 files

0.1.14

2 files

0.1.13

2 files

0.1.12

2 files

0.1.11

2 files

0.1.10

2 files

0.1.9

2 files

0.1.8

2 files

0.1.7

2 files

This release

0.1.6 This release

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page