Typed Amazon raw-data provider services for Keble.
Project description
keble-amz
The source line requires keble-helpers>=1.52.2 so exact Keepa/media/storage
usage quantities resolve identically from Git development pins and public
registry installs. Pricing remains the consuming platform's responsibility.
Release 2.3.0 is the REVIEW2 provider-recovery line. It consumes Data Infra
contract 0.9.0, Helpers 1.54.0, and Keepa 1.4.5 by immutable development
commits while retaining public semver ranges for registry consumers. The
release adds bounded category traversal/ranking recovery without moving retry,
pricing, or HTTP ownership out of Data Infra.
Side effects if changes:
- Data Infra imports these provider usage events through the Amazon manifest.
- Changing the helper floor requires lock, package-contract, and raw API source graph verification together.
keble-amz 2.x is the framework-free Amazon raw-data provider package. The
legacy 1.x monolith remains preserved on maintenance branch 1.0.28; current
source no longer embeds Keepa, cost analysis, ScraperAPI, or bundled wheels.
Version 2.3 owns the public category/traversal contract while a composition
root may inject Shuffle or another private traversal implementation.
The 2.3 provider artifact has a complete public-index dependency graph. It does
not import or declare the private keble-amz-shuffle package, so a bare
pip install keble-amz==2.3.0 can import keble_amz. Data Infra separately
composes the authenticated Shuffle adapter when native trending is enabled.
The remaining runtime bounds use Data Infra contract 0.9.0, keble-db>=1.9.0,
and one-attempt keble-keepa>=1.4.5. The 1.4.5 floor aligns the shared money
and helper contract while preserving exact Decimal capacity evidence when
successful live responses enter Keepa's short-lived Redis cache.
Architecture
keble-data-infra-contract
↑
keble-amz: AmazonServices ──> keble-keepa
│ │ │
│ └──> Amazon-owned typed LLM planner + traversal port
│ ↑
│ private Shuffle adapter (composition only)
└── RedisLeaseManager <- Mongo/Redis cache
AmazonServices exports three baseline operations and conditionally exposes a
fourth when the API composes Shuffle plus the typed model:
lookup_products(ProductLookupQuery)— exact batched ASIN lookup;search_products(ProductSearchQuery)— Keepa title finder plus product load;rank_products(ProductRankingQuery)— current official Amazon category bestseller board.trending_products(ProductTrendingQuery)— category-first, evidence-bearing recent products with native source continuation; never a search/query fallback.
For initial nonblank intent, Amazon selects only real root/child category IDs
through typed Pydantic-AI output. Category and discovery words are removed from
the residual before Product Finder: trending clothing produces a category
plan with no title keyword, while red clothing keeps only red. Blank intent
browses roots without an LLM call. When the universal query supplies a positive
numeric Amazon category, that exact browse node becomes the traversal frontier:
Amazon skips both unrelated root listing and LLM planning, and treats any query
text as the residual product attribute. Non-numeric category values fail with a
typed field error before paid provider work. Shuffle reads raw non-deduped pages, expands
wrapper-collapsed children only after definitive source exhaustion, and stops
at true logical depth three. Data Infra alone owns cross-page entity/family
dedupe.
Official bestseller positions remain in RankedItem.rank; they are not copied
into a fabricated MetricKind.RANK observation. Each item instead carries the
real normalized Keepa D30 sales observation declared by
RankingBasis.ranked_by=SALES_QUANTITY. If a successful product-detail response
cannot supply that evidence, Amazon raises its package-owned invalid-response
error, which maps to provider contact rather than permanent caller correction.
When Keepa omits one requested detail row, surviving products retain the
original ASIN board position; hydration-list position never shifts an official
rank. Search likewise sends the public page_size as Keepa's perPage stride,
so page two begins immediately after page one instead of skipping the unused
tail of an internal 50-item page.
Only Keepa-backed Amazon marketplaces are accepted: US, UK, DE, FR, JP, CA,
IT, ES, and MX. NL, SE, PL, and BE are rejected as typed request failures before
Redis ownership, cache, or provider I/O. Adding a new market requires a reviewed
AmazonMarketplace to DomainId mapping plus preflight coverage.
Every returned product carries structured metrics/timestamps plus a neutral summary explaining why it stands out. Root/child model calls and Keepa finder/ product loads all emit exact usage events; Amazon never attaches prices.
Provider clients execute one physical request and never own delayed retry.
Amazon's manifest exports AmazonFailureAdapter, which maps declared Keepa,
Pydantic-AI planning, invalid-response, timeout, and transport failures into
sanitized DataInfraFailure values with exact capacity, usage, request identity,
and recovery disposition. The planner passes one mutable RunUsage through
all bounded structured-output retries; failed runs therefore retain already-
billed tokens, while an HTTP failure with unavailable token counts emits a
typed usage-unknown event. These finite model exceptions are declared directly
to the adapter—there is no broad catch, exception wrapper, or exception-as-data
task supervisor. Unknown programming failures continue to worker/Sentry
supervision. Quota or an unverified HTTP status never becomes a payment failure.
Keepa reset evidence and HTTP Retry-After are combined conservatively: the
latest future horizon becomes the durable retry time. Planning-model gates use
a separate quota scope from Keepa. Missing planning composition, local lease
contention, and local model-queue saturation are Data Infra runtime failures
with exact-zero usage and no quota scope, so they cannot open a provider gate.
Provider methods return only keble-data-infra-contract values. Keepa DTOs,
cache policy, and usage accounting remain owned by keble-keepa. Shared
Money, AmazonMarketplace, hashing, and Redis owner-token leases are reused
from Keble packages rather than redeclared.
AmazonServices accepts one package-neutral usage recorder and forwards it to
finder, board, and partial-cache product loading. Each real Keepa cache miss
therefore contributes its provider-reported tokensConsumed event; Amazon
does not infer tokens, attach prices, or replay usage for cache hits. The raw
API captures these events and returns them on the shared page contract.
The package exports no FastAPI app or router. keble-data-infra-api consumes
the manifest and owns all paths, OpenAPI, error handlers, and runtime clients.
Cache and concurrency
Keepa remains the only normalized provider cache. Amazon wraps complete
operation requests in RedisLeaseManager single-flight keys. Every contender
re-enters the Keepa handler after acquiring ownership, so it rechecks Mongo and
spends no upstream call after the first owner persists the result.
Owned work has a deadline strictly shorter than the Redis lease TTL. The service rejects an unsafe configuration at construction, cancels work before ownership can expire, and only then lets a successor acquire the key. This prevents two slow owners from overlapping and double-spending Keepa/model capacity. The API composition layer may tune TTL, operation timeout, wait timeout, and polling for deployment capacity, but must preserve that invariant.
Redis lease acquisition and the cache-recheck-or-upstream critical section emit Sentry child spans when the API initializes telemetry. Span names contain only the stable Keepa operation and never ASINs, keywords, request JSON, responses, or credentials.
Lookup delegates to KeepaApiBatchLoader, preserving exact per-ASIN cache
keys, caller order, duplicates, partial hits, negative hits, newest-write-wins
repair, request batching, and usage accounting.
Verification
Python 3.13 and uv are required:
uv lock --check
uv run pytest -q \
-m "not live and not slow and not eval and not local_stack and not db_stack and not container"
KEBLE_BACKEND_ENV_FILE=/path/to/keble.backend/.env \
RUN_INTEGRATION=1 RUN_REAL_DB=1 RUN_LOCAL_STACK=1 \
uv run pytest -q tests/integration
KEBLE_BACKEND_ENV_FILE=/path/to/keble.backend/.env RUN_KEEPA_LIVE=1 \
uv run pytest -q tests/live -m "live and keepa_live"
uv run npx --yes pyright .
uv build
Integration/live tests use unique Redis namespaces and Mongo collections and
clean them after each run. Secrets resolve by explicit name through the shared
backend-env test helper and are never copied into this repository. When tests
run on the host, provide host-reachable Mongo/Redis URIs rather than container-
only aliases such as host.docker.internal embedded for in-container use.
Portable product metadata and release qualification
Amazon product mapping carries brand, description, feature bullets, product type, full category path, rating/review observations, source-language hints, and Keepa release-date precision into the Data Infra contract. Recent-release qualification is emitted only when the complete release interval is inside the requested window. Offer/listing history remains ordering evidence and never stands in for a product release date.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file keble_amz-2.3.0.tar.gz.
File metadata
- Download URL: keble_amz-2.3.0.tar.gz
- Upload date:
- Size: 116.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
843a0732c567886fe668afd4d0e2848fc439460660b39e7961476641cd5794a9
|
|
| MD5 |
ffecef7fd0e2558f194f1ae18428b80b
|
|
| BLAKE2b-256 |
be3a1df71c74b1835b5a65cb435f2a1ec742ea885cf7a3bbcf27c5f348f58038
|
File details
Details for the file keble_amz-2.3.0-py3-none-any.whl.
File metadata
- Download URL: keble_amz-2.3.0-py3-none-any.whl
- Upload date:
- Size: 30.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab78ae0f7079871ca86dca1670365f141c1c175fb28d8edf0513057ce12d49a6
|
|
| MD5 |
8234124d084e117a6d80c60efd56dcfc
|
|
| BLAKE2b-256 |
51fe66e0d35b5e10fa9a34fb68550f65a68055892e8658e450cd49bdfe471644
|