Finish package: fix packaging, modernize, add public API, CI and docs - #3
Conversation
Make the package professional and installable as the basis for the Home Assistant integration and a future MCP server. Packaging (blocking fixes): - Include the rohlik_api.services subpackage in builds (was omitted, so installed wheels would ImportError) - Use PEP 639 SPDX license metadata (license = "MIT") with setuptools>=77; the previous table form broke the build - Single-source the version from rohlik_api.__version__ (dynamic in pyproject, read via importlib.metadata for the User-Agent) - Target Python 3.11+, real author email, Beta status API & code quality: - Add public RohlikAPI.login()/logout() plus user_id/address_id properties so callers no longer need private _auth access - Modern typing (PEP 604 unions, builtin generics) across all modules - Consistent exception chaining (raise ... from err) and %-style logging - Add format_price helper to remove duplicated price formatting - Remove unused models.py dead code Tooling, tests & docs: - Add GitHub Actions CI (ruff, black, mypy, pytest) on 3.11-3.13 - Clean pass: ruff, black, mypy all green; 115 tests passing - Add tests for login/logout, client properties and helpers - Rewrite the outdated example.py against the current service API - Update README (error contract, requirements, development) and PUBLISHING Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PmotTwydT558t4JHd5Cnwm
Service methods that parse responses now return typed dataclasses instead of raw dictionaries, giving callers (the Home Assistant integration and the upcoming MCP server) a fully type-hinted, self-documenting API. - Add rohlik_api/models.py with dataclasses (slots) for cart, products, composition, prices, recipes, ingredient products and shopping lists, each with a from_api parser; exported from the package root - cart.get_content -> Cart, products.search -> SearchResults, get_ai_summary/get_composition/get_price -> typed models, recipes.* -> typed models, account.get_shopping_list -> ShoppingList - cart.add_items now returns list[int]; delete_item returns None and raises on failure; search returns an empty SearchResults (not None) when there are no hits, reserving None for request failures - Raw passthrough endpoints (orders, delivery, premium/bags/announcements, get_data) keep returning decoded JSON dicts/lists; documented in the README - Bump minimum Python to 3.13; update classifiers, tool targets and CI matrix - Update tests to attribute access, example.py and README accordingly All green: ruff, black, mypy; 116 tests passing (87% coverage), twine check passes and the wheel ships models.py and py.typed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PmotTwydT558t4JHd5Cnwm
|
@claude review |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
|
@claude review |
|
Claude finished @dvejsada's task in 3m 3s —— View job Code Review
This is a solid modernization pass overall — the packaging fixes are correct, the service-based architecture is clean, and the typed models are a clear improvement. A few issues worth addressing before merging, from most to least impactful. 🔴 High: Python version claim vs. realityThe PR description says "Target Python 3.11+" and "CI on 3.11-3.13", but the actual code only requires/tests 3.13:
The code itself would likely work on 3.10+ (all union types are guarded by 🟡 Medium: Inconsistent error contracts across servicesServices handle errors in two incompatible ways:
Callers must know which pattern applies per service, which is fragile and forces Recommend picking one convention. Raising is generally more Pythonic (callers can always catch if they want to ignore failures). If the 🟡 Medium:
|
- auth: cache the real login response and return it on subsequent login() calls instead of a synthetic dict, so get_data()["login"] is meaningful - auth: reset user_id/address_id (and cached response) on logout via _reset_session(), so reusing an instance across logins re-fetches a possibly-changed delivery address - client: drop the duplicate credential validation (AuthManager owns it) - client: log best-effort logout-on-close failures at WARNING, not ERROR - services/base: document the error-handling convention (reads return None, critical/mutating ops raise APIRequestFailedError) - tests: remove redundant @pytest.mark.asyncio decorators (asyncio_mode=auto) and add coverage for login caching and logout session reset Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PmotTwydT558t4JHd5Cnwm
|
Thanks for the review — addressed in
118 tests green; ruff / black / mypy clean. Generated by Claude Code |
Make the README friendlier (clearer intro, table of contents, a credentials & security section, tidier API reference) and add a prominent "unofficial, personal use only, not endorsed by Rohlik.cz" callout at the top plus a dedicated Disclaimer section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PmotTwydT558t4JHd5Cnwm
|
@claude review Generated by Claude Code |
|
Claude finished @dvejsada's task in 2m 51s —— View job Code Review (Re-review)
All seven acted-upon items from the first review are correctly addressed. A few smaller issues remain worth noting. ✅ Previous Feedback — Verified
🟡 Medium:
|
- Log optional read failures (return-None paths) at WARNING instead of ERROR
across base/products/recipes/orders/delivery and the swallowed per-item cart
add, to avoid spurious alerts in monitoring setups
- Simplify login() ID extraction: drop the now-dead "if not" guards (cleared by
_reset_session) and replace try/except AttributeError with an explicit
`or {}` guard for a null address
- Comment the deliberate explicit _ensure_logged_in() in get_next_slots
- Enforce strict typing for the package (disallow_untyped_defs /
disallow_incomplete_defs) to honour the py.typed promise; exclude tests
118 tests passing; ruff, black and (strict) mypy all green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PmotTwydT558t4JHd5Cnwm
|
Re-review items addressed in
118 tests green; ruff, black and strict mypy all clean. CI was green on the previous push. Generated by Claude Code |
|
@claude review Generated by Claude Code |
|
Claude finished @dvejsada's task in 1m 20s —— View job Code Review (Third Pass)
All three items from the second review are correctly addressed. No new issues found. ✅ Previous Feedback — Verified
Commit qualityThe Ready to merge ✅This PR is in excellent shape. Five rounds of review have tightened a solid initial modernization into something production-ready. All blocking and advisory findings are resolved. |
Make the package professional and installable as the basis for the Home Assistant integration and a future MCP server.
Packaging (blocking fixes)
rohlik_api.servicessubpackage in builds (was omitted, so installed wheels would ImportError)license = "MIT") withsetuptools>=77rohlik_api.__version__(dynamic in pyproject, read via importlib.metadata for the User-Agent)API & typed models
RohlikAPI.login()/logout()plususer_id/address_idpropertiesCart,SearchResults,ProductPrice,RecipeDetail, …) instead of raw dicts; raw passthrough endpoints (orders / delivery / account /get_data) still return decoded JSON%-style loggingformat_pricehelper removes duplicated price formattingTooling, tests & docs
example.pyagainst the current API; updated README and PUBLISHINGReview follow-ups (addressed in 4c2b0c0)
authcaches the real login response;logoutresets cached user/address IDsBaseService