Conversation
Extracted from layervai/qurl-integrations (apps/sdk-python/). Includes: - Sync and async QURL API clients - LangChain tool integration - Full test suite - CI, Release Please, and PyPI publish workflows - Claude code review workflow Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CI installs `.[dev]` which doesn't include langchain-core. Without it, BaseTool falls back to `object` and tool classes reject kwargs. Use pytest.importorskip to skip gracefully. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The dev extra doesn't include langchain-core. Install with `.[dev,langchain]` so the langchain tool tests actually run. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add py.typed marker for PEP 561 - Add README badges (PyPI, CI, Python versions, license) - Add CONTRIBUTING.md, SECURITY.md - Add issue and PR templates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`2 ** (attempt - 1)` returns int, making `min()` return type ambiguous under mypy strict mode. Explicit annotation resolves it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add AuthenticationError, AuthorizationError, NotFoundError,
ValidationError, RateLimitError, ServerError subclasses of QURLError
so callers can catch specific HTTP status codes
- Add extend() convenience method to both sync and async clients
- Add debug logging throughout request lifecycle (enable with
logging.getLogger("layerv_qurl").setLevel(logging.DEBUG))
- Improve create() docstring to clarify CreateOutput vs QURL
- Export all new error classes from __init__.py
- Add 11 new tests: error subclasses, extend(), AccessPolicy serialization
- Update README with "Why QURL?" section, granular error handling
examples, debug logging docs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace dataclasses.asdict() with fields()/getattr() to avoid unnecessary deep copy on every request with AccessPolicy - Extract build_list_params() to _utils.py, deduplicating list() query-param building between sync and async clients - Narrow except clauses: Exception → PackageNotFoundError for version lookup, AttributeError → TypeError in parse_error() fallback - Add async_client test fixture to reduce boilerplate across 8 tests - Add sync note to async_client.py module docstring Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- json=body if body is not None else None → json=body (httpx treats None as no-body already) - Replace redundant HTTP call in test_401 with isinstance check Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code Review: feat: initial Python SDK setupOverall this is a well-structured initial SDK. Clean separation of concerns, good error hierarchy, and solid test coverage. Here's detailed feedback: Code Quality & DesignStrengths:
Suggestions:
Potential Bugs & Issues
SecurityGood practices already in place:
Considerations:
Performance
Test CoverageComprehensive coverage including:
Gaps to consider for follow-up:
CI/CD
Minor Nits
VerdictThis is a solid initial SDK. The architecture is clean, security basics are handled well, and test coverage is thorough. The items above are mostly incremental improvements rather than blockers. Ship it! 🤖 Generated with Claude Code |
Summary
layervai/qurl-integrations(apps/sdk-python/)QURLClient) and async (AsyncQURLClient) API clientsQURLToolkit)Test plan
pip install -e '.[dev]'worksruff checkpassespytest tests/ -vpasses🤖 Generated with Claude Code