Conversation
Sensitive Change Detection (shadow mode)This PR modifies control-plane files:
|
There was a problem hiding this comment.
25 issues found across 109 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="Makefile">
<violation number="1" location="Makefile:333">
P2: `py-check` duplicates the mypy invocation from `py-typecheck` instead of listing it as a prerequisite. If `py-typecheck` flags change later (e.g. adding `--strict`), this copy will silently diverge. Use the same pattern as `ts-check: ts-typecheck ts-test`.</violation>
</file>
<file name="python/src/basecamp/services/authorization.py">
<violation number="1" location="python/src/basecamp/services/authorization.py:22">
P1: Blocking synchronous HTTP call (`httpx.get`) inside the async service. `discover()` uses synchronous `httpx.get()`, so calling it from the async code path will block the event loop. Either provide an `async_discover` variant that uses `httpx.AsyncClient`, or run the synchronous call in an executor (e.g., `asyncio.to_thread`).</violation>
</file>
<file name="python/tests/test_http.py">
<violation number="1" location="python/tests/test_http.py:172">
P2: `Retry-After: 1` causes a real 1-second `time.sleep` during this test, and the test doesn't assert on timing behavior. Either mock `time.sleep` and assert it was called with `1.0` (which would actually verify the header is "respected"), or use a sub-second approach to avoid needlessly slowing the suite.</violation>
</file>
<file name="python/src/basecamp/errors.py">
<violation number="1" location="python/src/basecamp/errors.py:147">
P2: The 429 branch discards the parsed response body `message`. Every other branch forwards it. Pass `message` so callers see the API's specific rate-limit explanation instead of the generic default.</violation>
</file>
<file name="python/src/basecamp/client.py">
<violation number="1" location="python/src/basecamp/client.py:45">
P1: Empty `access_token` string silently bypasses authentication. The `is not None` check in the validation counts it as provided, but the truthiness check `if access_token:` skips creating the `StaticTokenProvider`, leaving `auth=None`. Use `if access_token is not None:` to stay consistent with the validation, and optionally reject empty strings early.</violation>
</file>
<file name="python/pyproject.toml">
<violation number="1" location="python/pyproject.toml:56">
P2: The `"pass"` coverage exclusion pattern is an unanchored regex that will match any line containing the substring `pass` (e.g., `password = get_input()`, `bypass_cache = True`). This silently removes those lines from coverage reporting. Use an anchored pattern instead.</violation>
</file>
<file name="python/src/basecamp/_security.py">
<violation number="1" location="python/src/basecamp/_security.py:40">
P3: `"[::1]"` in the localhost set is unreachable. `urlparse(...).hostname` strips IPv6 brackets, so it always returns `"::1"`, never `"[::1]"`. Remove the dead entry to avoid giving the false impression that bracketed addresses are handled as a distinct case.</violation>
</file>
<file name="python/src/basecamp/config.py">
<violation number="1" location="python/src/basecamp/config.py:40">
P2: Missing validation for `base_delay` and `max_jitter`. The other numeric config fields are validated, but these two retry-timing fields are not, allowing nonsensical values (e.g., negative delay) to silently produce broken backoff behavior.</violation>
</file>
<file name="scripts/check-python-service-drift.sh">
<violation number="1" location="scripts/check-python-service-drift.sh:33">
P2: Redirecting stderr to `/dev/null` on the generation commands means a generator failure causes a silent exit (due to `set -e`) with no diagnostic output. Redirect only stdout so Python tracebacks and error messages remain visible.</violation>
</file>
<file name="python/src/basecamp/async_client.py">
<violation number="1" location="python/src/basecamp/async_client.py:45">
P2: `if access_token:` uses truthiness, which silently skips auth setup for `access_token=""`. Since the `is not None` validation above accepts empty strings as a valid choice, use `if access_token is not None:` to stay consistent and avoid passing `auth=None` to `AsyncHttpClient`.</violation>
</file>
<file name="python/src/basecamp/_pagination.py">
<violation number="1" location="python/src/basecamp/_pagination.py:9">
P3: `_NEXT_LINK_RE` is compiled at module level but never used. `parse_next_link` uses an inline `re.search` pattern instead. Remove the unused regex or refactor `parse_next_link` to use it.</violation>
</file>
<file name="python/src/basecamp/async_auth.py">
<violation number="1" location="python/src/basecamp/async_auth.py:116">
P2: The `on_refresh` callback is called synchronously. In this async provider, users will naturally pass `async` callbacks, which would silently not execute (the returned coroutine is never awaited). Use `inspect.iscoroutinefunction` to detect async callbacks and `await` them.</violation>
</file>
<file name="python/conformance/runner/python/pyproject.toml">
<violation number="1" location="python/conformance/runner/python/pyproject.toml:11">
P1: Incorrect relative path for the editable SDK source. From `python/conformance/runner/python/`, `../../../python` resolves to `python/python/` (which doesn't exist), so `uv sync` will fail. The path should be `../../..` to reach the SDK root at `python/`.</violation>
</file>
<file name="python/scripts/generate_metadata.py">
<violation number="1" location="python/scripts/generate_metadata.py:23">
P2: Pass `encoding="utf-8"` to `open()` and `write_text()`. On Python <3.15 the default encoding is platform-dependent, which can corrupt non-ASCII content on systems with non-UTF-8 locales.</violation>
</file>
<file name="python/src/basecamp/download.py">
<violation number="1" location="python/src/basecamp/download.py:51">
P2: The range `301 <= status_code <= 308` incorrectly treats HTTP 304 (Not Modified), 305, and 306 as redirects. A 304 response would hit the `no Location header` error path with a misleading message. Use an explicit set of redirect codes instead.</violation>
</file>
<file name="python/scripts/generate_services.py">
<violation number="1" location="python/scripts/generate_services.py:373">
P2: Body params skip `safe_python_name`, so a body property named after a Python keyword (e.g. `from`) would generate invalid syntax. Query params already handle this correctly — apply the same treatment here.</violation>
</file>
<file name=".pre-commit-config.yaml">
<violation number="1" location=".pre-commit-config.yaml:80">
P2: Inconsistent file filter: `python-test-short` uses `types: [python]` while the other two Python hooks use `files: ^python/.*\.py$`. Use `files:` here too so all three hooks trigger on the same set of files.</violation>
</file>
<file name="python/tests/test_auth.py">
<violation number="1" location="python/tests/test_auth.py:175">
P2: The thread-safety assertion `>= 1` is too weak — it passes even without any locking. The comment explains the lock should serialize access so refresh is called only once, but `>= 1` will always pass regardless. Use `== 1` to actually verify the lock prevents redundant refreshes.</violation>
</file>
<file name="python/src/basecamp/oauth/exchange.py">
<violation number="1" location="python/src/basecamp/oauth/exchange.py:117">
P2: If the token endpoint returns valid JSON that isn't a dict (e.g., a JSON array or string), `data.get(...)` will raise an unhandled `AttributeError` instead of a clean `OAuthError`. Add a type check after parsing.</violation>
</file>
<file name="python/src/basecamp/oauth/discovery.py">
<violation number="1" location="python/src/basecamp/oauth/discovery.py:41">
P2: `check_body_size` raises `ApiError`, not `OAuthError`. Since `OAuthError` and `ApiError` are sibling classes (both extend `BasecampError`), callers catching `OAuthError` from `discover()` will miss this error path. Wrap the call so the exception type is consistent with the rest of the function.</violation>
</file>
<file name="python/src/basecamp/oauth/errors.py">
<violation number="1" location="python/src/basecamp/oauth/errors.py:13">
P2: `code` is hardcoded to `"api_error"` regardless of `oauth_type`, so `error.code` and `error.exit_code` are wrong for validation/network/auth OAuth errors. The `oauth_type` should propagate to the parent's `code` parameter (with a mapping for `"auth"` → `"auth_required"` to match `ErrorCode`).</violation>
</file>
<file name=".github/workflows/release-python.yml">
<violation number="1" location=".github/workflows/release-python.yml:114">
P1: Substring match on version can falsely skip a release. `grep -q "$VERSION"` matches `0.2.1` inside `0.2.10`, so publishing `0.2.1` would be silently skipped if any `0.2.1x` version already exists on PyPI. Use word-boundary matching to require an exact version match.</violation>
</file>
<file name="python/conformance/runner/python/runner.py">
<violation number="1" location="python/conformance/runner/python/runner.py:164">
P3: Unused variable `pattern`: this compiled regex is never referenced. The route on line 176 builds its own regex inline.</violation>
<violation number="2" location="python/conformance/runner/python/runner.py:225">
P2: The `statusCode` assertion silently passes when an error is raised but `expected < 400` and the error has no `http_status` attribute. Add a branch to catch this case (error present, success status expected).</violation>
</file>
<file name="python/src/basecamp/auth.py">
<violation number="1" location="python/src/basecamp/auth.py:109">
P1: Missing refresh token rotation: `_perform_refresh` doesn't update `self._refresh_token` from the response. The Go sibling SDK explicitly handles this (`if tokenResp.RefreshToken != "" { creds.RefreshToken = tokenResp.RefreshToken }`). If the server rotates refresh tokens, subsequent refreshes will fail with the stale token.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b794de9a8f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
This PR introduces a new, generated Python SDK for the Basecamp API into the monorepo, along with CI, conformance runner wiring, and repo automation updates (version syncing, drift checks, and release workflow).
Changes:
- Add Python SDK source (sync + async clients, OAuth helpers, webhooks helpers, pagination/errors/hooks utilities) plus generated services/types/metadata.
- Add Python unit tests and a Python conformance runner package; wire Python into the top-level Makefile, pre-commit, gitignore, and CI.
- Extend version bump/sync scripts and GitHub release automation to include Python.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 58 out of 109 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| scripts/sync-api-version.sh | Sync Python API version constant into python/src/basecamp/_version.py. |
| scripts/bump-version.sh | Bump Python package version in pyproject.toml and SDK _version.py. |
| scripts/check-python-service-drift.sh | Add a drift-check script that regenerates Python artifacts and diffs them. |
| Makefile | Add Python build/test/typecheck/generate/drift targets; include Python in check, clean, and conformance. |
| .pre-commit-config.yaml | Add Python ruff, mypy, and pytest hooks using uv. |
| .gitignore | Ignore Python build/test artifacts and uv locks/venvs. |
| .github/workflows/test.yml | Add test-python job and run Python conformance in the conformance workflow. |
| .github/workflows/release-python.yml | Add PyPI trusted-publishing workflow for the Python SDK. |
| .github/workflows/release-github.yml | Include Python release workflow in global release orchestration and release notes. |
| python/pyproject.toml | Define the Python package, deps, and tooling config (ruff/mypy/pytest/coverage). |
| python/conformance/runner/python/pyproject.toml | Define a conformance runner env that installs SDK editable and runs the Python runner. |
| python/scripts/generate_types.py | Generate TypedDict types from OpenAPI schemas. |
| python/scripts/generate_metadata.py | Generate metadata.json (idempotency + retry config) from OpenAPI + behavior model. |
| python/src/basecamp/init.py | Expose public Python SDK API surface from the package root. |
| python/src/basecamp/_version.py | Add Python SDK version and API version constants. |
| python/src/basecamp/config.py | Add Python SDK runtime configuration (timeouts/retry knobs/base URL rules). |
| python/src/basecamp/errors.py | Add structured error types and HTTP response → error mapping. |
| python/src/basecamp/_security.py | Add helpers for HTTPS enforcement, same-origin, truncation, body-size checks, header redaction. |
| python/src/basecamp/_pagination.py | Add pagination result container + Link/X-Total-Count parsing utilities. |
| python/src/basecamp/hooks.py | Add hook interfaces and console/chaining helpers for observability. |
| python/src/basecamp/auth.py | Add sync auth strategies + token providers (static + OAuth refresh). |
| python/src/basecamp/async_auth.py | Add async auth strategies + token providers (static + OAuth refresh). |
| python/src/basecamp/_http.py | Add sync httpx client wrapper with retry/error mapping/auth injection. |
| python/src/basecamp/_async_http.py | Add async httpx client wrapper with retry/error mapping/auth injection. |
| python/src/basecamp/download.py | Add sync/async download helper that handles Basecamp rewrite + redirect to signed URL. |
| python/src/basecamp/services/init.py | Export the handwritten authorization service(s). |
| python/src/basecamp/services/authorization.py | Add account-independent authorization service (sync + async). |
| python/src/basecamp/oauth/init.py | Export OAuth helpers (discovery, exchange, PKCE, authorize URL building). |
| python/src/basecamp/oauth/config.py | Add OAuth discovery config model. |
| python/src/basecamp/oauth/discovery.py | Add OAuth discovery implementation with HTTPS/localhost rules. |
| python/src/basecamp/oauth/exchange.py | Add OAuth token exchange/refresh implementation and response parsing. |
| python/src/basecamp/oauth/errors.py | Add OAuth-specific error type with a classifier field. |
| python/src/basecamp/oauth/pkce.py | Add PKCE + state generation. |
| python/src/basecamp/oauth/token.py | Add OAuth token model with expiration helpers. |
| python/src/basecamp/webhooks/init.py | Export webhook verification/receiver utilities and error types. |
| python/src/basecamp/webhooks/verify.py | Add HMAC signature compute/verify helpers. |
| python/src/basecamp/webhooks/receiver.py | Add framework-agnostic webhook receiver with pattern handlers, middleware, and deduplication. |
| python/src/basecamp/webhooks/events.py | Add convenience constants and event-kind parsing helper. |
| python/src/basecamp/webhooks/errors.py | Add webhook signature verification error type. |
| python/src/basecamp/generated/services/init.py | Export generated service classes (sync + async). |
| python/src/basecamp/generated/services/*.py | Add generated service clients for API operations (sampled in diff). |
| python/src/basecamp/py.typed | Mark package as typed for downstream type checkers. |
| python/tests/conftest.py | Add shared pytest fixtures for the Python SDK tests. |
| python/tests/test_auth.py | Add auth/token-provider tests including refresh and concurrency checks. |
| python/tests/test_client.py | Add client construction and service property tests. |
| python/tests/test_config.py | Add config defaults/env/validation/HTTPS enforcement tests. |
| python/tests/test_download.py | Add download rewrite/redirect behavior tests. |
| python/tests/test_errors.py | Add error mapping/parsing and Retry-After parsing tests. |
| python/tests/test_hooks.py | Add hook behavior tests (noop/chain/console/safe hook). |
| python/tests/test_http.py | Add sync HTTP client tests (success/error mapping/retry/header injection). |
| python/tests/test_pagination.py | Add pagination helper tests. |
| python/tests/test_security.py | Add security helper tests (same-origin/HTTPS/localhost/truncate/redaction/body-size). |
| python/tests/oauth/test_discovery.py | Add OAuth discovery tests including HTTPS enforcement and network failure mapping. |
| python/tests/oauth/test_exchange.py | Add OAuth exchange/refresh tests including legacy format support. |
| python/tests/oauth/test_pkce.py | Add PKCE/state generation tests. |
| python/tests/webhooks/test_verify.py | Add webhook HMAC compute/verify tests. |
| python/tests/webhooks/test_receiver.py | Add webhook receiver tests (signature, patterns, on_any, dedup, middleware). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
3 issues found across 30 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="python/scripts/generate_services.py">
<violation number="1" location="python/scripts/generate_services.py:637">
P2: Binary body branch unconditionally passes `operation=` instead of using `operation_kwarg(op)`. Every other branch delegates to the helper that gates on `is_mutation`. Use `operation_kwarg(op)` here for consistency.</violation>
</file>
<file name="python/src/basecamp/errors.py">
<violation number="1" location="python/src/basecamp/errors.py:147">
P2: The parsed `message` is not wrapped in `_truncate()` here, unlike the 404, 400/422, and default branches. Since `message` comes from the API response body and can be arbitrarily long, apply `_truncate` for consistency and to cap error-message size.</violation>
</file>
<file name=".github/workflows/release-python.yml">
<violation number="1" location=".github/workflows/release-python.yml:114">
P2: Read `VERSION` from the environment inside Python (`os.environ['VERSION']`) instead of splicing it into the source via shell expansion (`'${VERSION}'`). This avoids a code-injection vector and is more robust against malformed version strings.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
Pull request overview
Adds a first-class Python SDK to the Basecamp monorepo (sync + async clients on httpx), including OAuth + webhooks utilities, generated services/types/metadata, tests, and CI/release automation.
Changes:
- Introduces the Python package (
python/) with core runtime modules (HTTP, auth, pagination, hooks, OAuth, webhooks) plus generated services/types/metadata. - Adds Python unit tests, Makefile targets, drift-check tooling, and pre-commit hooks.
- Wires Python into CI (test matrix + conformance) and adds PyPI release workflow + GitHub release notes update.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 58 out of 109 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/sync-api-version.sh | Updates API version sync script to also bump Python API_VERSION. |
| scripts/check-python-service-drift.sh | Adds a Python generated-artifact drift check script. |
| scripts/bump-version.sh | Extends version bump script to update Python pyproject.toml and _version.py. |
| python/tests/webhooks/test_verify.py | Adds tests for webhook HMAC signature compute/verify. |
| python/tests/webhooks/test_receiver.py | Adds tests for webhook receiver routing, middleware, and deduping. |
| python/tests/webhooks/init.py | Test package marker for webhook tests. |
| python/tests/test_security.py | Adds tests for URL/origin security helpers, truncation, redaction, size checks. |
| python/tests/test_pagination.py | Adds tests for pagination helpers and ListResult metadata. |
| python/tests/test_http.py | Adds tests for HTTP client behavior (retries, error mapping, headers). |
| python/tests/test_hooks.py | Adds tests for hook chaining, console hooks, and safe hook execution. |
| python/tests/test_errors.py | Adds tests for error hierarchy, parsing, and retry-after handling. |
| python/tests/test_download.py | Adds tests for download URL rewriting and redirect handling. |
| python/tests/test_config.py | Adds tests for config defaults, env parsing, and HTTPS enforcement. |
| python/tests/test_client.py | Adds tests for client construction, account scoping, and context manager behavior. |
| python/tests/test_auth.py | Adds tests for auth strategies and token refresh behavior (thread safety). |
| python/tests/services/init.py | Test package marker for service tests. |
| python/tests/oauth/test_pkce.py | Adds tests for PKCE verifier/challenge and state generation. |
| python/tests/oauth/test_exchange.py | Adds tests for OAuth token exchange/refresh requests and error mapping. |
| python/tests/oauth/test_discovery.py | Adds tests for OAuth discovery and HTTPS/localhost enforcement. |
| python/tests/oauth/init.py | Test package marker for OAuth tests. |
| python/tests/conftest.py | Adds pytest fixtures for client/config/auth/hooks. |
| python/tests/init.py | Test package marker. |
| python/src/basecamp/webhooks/verify.py | Implements webhook signature compute/verify utilities. |
| python/src/basecamp/webhooks/receiver.py | Implements webhook receiver: signature check, JSON parse, routing, dedupe, middleware. |
| python/src/basecamp/webhooks/events.py | Adds webhook event kind constants + parsing helper. |
| python/src/basecamp/webhooks/errors.py | Adds webhook-specific error type. |
| python/src/basecamp/webhooks/init.py | Exposes webhook module public API. |
| python/src/basecamp/services/authorization.py | Adds manual authorization service (sync/async) with Launchpad fallback. |
| python/src/basecamp/services/init.py | Exposes manual services package exports. |
| python/src/basecamp/py.typed | Marks package as typed for type checkers. |
| python/src/basecamp/oauth/token.py | Adds OAuthToken model with computed expires_at and expiry checks. |
| python/src/basecamp/oauth/pkce.py | Adds PKCE/state generators. |
| python/src/basecamp/oauth/exchange.py | Implements OAuth code exchange/refresh with validation and error handling. |
| python/src/basecamp/oauth/errors.py | Adds OAuth-specific error wrapper. |
| python/src/basecamp/oauth/discovery.py | Implements OAuth discovery with HTTPS enforcement and response validation. |
| python/src/basecamp/oauth/config.py | Adds OAuth discovery config dataclass. |
| python/src/basecamp/oauth/authorize.py | Adds authorization URL builder. |
| python/src/basecamp/oauth/init.py | Exposes OAuth module public API. |
| python/src/basecamp/hooks.py | Adds hooks interfaces + chaining + console hooks. |
| python/src/basecamp/generated/services/webhooks_service.py | Generated Webhooks service client (sync/async). |
| python/src/basecamp/generated/services/vaults.py | Generated Vaults service client (sync/async). |
| python/src/basecamp/generated/services/uploads.py | Generated Uploads service client (sync/async). |
| python/src/basecamp/generated/services/tools.py | Generated Tools service client (sync/async). |
| python/src/basecamp/generated/services/todosets.py | Generated Todosets service client (sync/async). |
| python/src/basecamp/generated/services/todos.py | Generated Todos service client (sync/async). |
| python/src/basecamp/generated/services/todolists.py | Generated Todolists service client (sync/async). |
| python/src/basecamp/generated/services/todolist_groups.py | Generated TodolistGroups service client (sync/async). |
| python/src/basecamp/generated/services/timesheets.py | Generated Timesheets service client (sync/async). |
| python/src/basecamp/generated/services/timeline.py | Generated Timeline service client (sync/async). |
| python/src/basecamp/generated/services/templates.py | Generated Templates service client (sync/async). |
| python/src/basecamp/generated/services/subscriptions.py | Generated Subscriptions service client (sync/async). |
| python/src/basecamp/generated/services/search.py | Generated Search service client (sync/async). |
| python/src/basecamp/generated/services/schedules.py | Generated Schedules service client (sync/async). |
| python/src/basecamp/generated/services/reports.py | Generated Reports service client (sync/async). |
| python/src/basecamp/generated/services/recordings.py | Generated Recordings service client (sync/async). |
| python/src/basecamp/generated/services/projects.py | Generated Projects service client (sync/async). |
| python/src/basecamp/generated/services/people.py | Generated People service client (sync/async). |
| python/src/basecamp/generated/services/messages.py | Generated Messages service client (sync/async). |
| python/src/basecamp/generated/services/message_types.py | Generated MessageTypes service client (sync/async). |
| python/src/basecamp/generated/services/message_boards.py | Generated MessageBoards service client (sync/async). |
| python/src/basecamp/generated/services/lineup.py | Generated Lineup service client (sync/async). |
| python/src/basecamp/generated/services/forwards.py | Generated Forwards service client (sync/async). |
| python/src/basecamp/generated/services/events.py | Generated Events service client (sync/async). |
| python/src/basecamp/generated/services/documents.py | Generated Documents service client (sync/async). |
| python/src/basecamp/generated/services/comments.py | Generated Comments service client (sync/async). |
| python/src/basecamp/generated/services/client_visibility.py | Generated ClientVisibility service client (sync/async). |
| python/src/basecamp/generated/services/client_replies.py | Generated ClientReplies service client (sync/async). |
| python/src/basecamp/generated/services/client_correspondences.py | Generated ClientCorrespondences service client (sync/async). |
| python/src/basecamp/generated/services/client_approvals.py | Generated ClientApprovals service client (sync/async). |
| python/src/basecamp/generated/services/cards.py | Generated Cards service client (sync/async). |
| python/src/basecamp/generated/services/card_tables.py | Generated CardTables service client (sync/async). |
| python/src/basecamp/generated/services/card_steps.py | Generated CardSteps service client (sync/async). |
| python/src/basecamp/generated/services/card_columns.py | Generated CardColumns service client (sync/async). |
| python/src/basecamp/generated/services/campfires.py | Generated Campfires service client (sync/async). |
| python/src/basecamp/generated/services/boosts.py | Generated Boosts service client (sync/async). |
| python/src/basecamp/generated/services/automation.py | Generated Automation service client (sync/async). |
| python/src/basecamp/generated/services/attachments.py | Generated Attachments service client (sync/async). |
| python/src/basecamp/generated/services/init.py | Generated barrel exports for all generated services. |
| python/src/basecamp/generated/init.py | Generated package marker. |
| python/src/basecamp/errors.py | Adds shared SDK error hierarchy + parsing helpers. |
| python/src/basecamp/download.py | Adds sync/async download helper with redirect-following signed URLs. |
| python/src/basecamp/config.py | Adds SDK config (timeouts, retries, HTTPS enforcement, env loading). |
| python/src/basecamp/auth.py | Adds sync auth strategies + token providers (static + OAuth refresh). |
| python/src/basecamp/async_auth.py | Adds async auth strategies + token providers (static + OAuth refresh). |
| python/src/basecamp/_version.py | Adds Python SDK VERSION/API_VERSION constants. |
| python/src/basecamp/_security.py | Adds shared security helpers (origin checks, truncation, body size, header redaction). |
| python/src/basecamp/_pagination.py | Adds pagination helpers + ListResult metadata container. |
| python/src/basecamp/_http.py | Adds sync httpx client wrapper with retries and error mapping. |
| python/src/basecamp/_async_http.py | Adds async httpx client wrapper with retries and error mapping. |
| python/src/basecamp/init.py | Defines Python package public exports. |
| python/scripts/generate_types.py | Adds generator for TypedDict types from OpenAPI schemas. |
| python/scripts/generate_metadata.py | Adds generator for per-operation retry/idempotency metadata. |
| python/scripts/generate_services.py | Adds generator for Python service clients from OpenAPI operations. |
| python/pyproject.toml | Adds Python package metadata and dev tool configuration. |
| python/conformance/runner/python/pyproject.toml | Adds Python conformance runner package wiring via editable path dependency. |
| Makefile | Adds Python targets and includes Python in top-level check and conformance. |
| .pre-commit-config.yaml | Adds Python lint/typecheck/test hooks using uv. |
| .gitignore | Ignores Python build artifacts/venvs/uv lockfiles. |
| .github/workflows/test.yml | Adds Python test job and runs Python conformance in CI. |
| .github/workflows/release-python.yml | Adds PyPI publish workflow with trusted publishing (OIDC). |
| .github/workflows/release-github.yml | Includes Python release workflow and adds pip install snippet to release notes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 78eb7317b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Adds a first-class Python SDK to the Basecamp API monorepo (sync + async clients, OAuth + webhooks helpers, generated services/types/metadata), and wires it into the repo’s versioning scripts, Makefile targets, CI, conformance, and release automation.
Changes:
- Introduces the Python package (
python/src/basecamp) with HTTP/auth/error/pagination/security plumbing plus OAuth + webhooks modules, and a corresponding pytest suite. - Adds Python code generation + drift-check scripts and Makefile targets (generate, drift, lint/typecheck/test, conformance).
- Integrates Python into CI (
test-python, Python conformance), version bump/sync scripts, pre-commit, and GitHub/PyPI release workflows.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 58 out of 110 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/sync-api-version.sh | Extends API version sync to update Python’s _version.py. |
| scripts/check-python-service-drift.sh | Adds a script to regenerate+diff Python generated artifacts (services/metadata/types). |
| scripts/bump-version.sh | Extends version bump automation to update Python pyproject.toml and _version.py. |
| python/tests/webhooks/test_verify.py | Tests HMAC signature compute/verify helpers. |
| python/tests/webhooks/test_receiver.py | Tests webhook routing, signature verification, glob matching, middleware, and deduplication. |
| python/tests/webhooks/init.py | Marks webhook tests package. |
| python/tests/test_security.py | Tests security utilities (origin checks, HTTPS enforcement, redaction, body size limits). |
| python/tests/test_pagination.py | Tests pagination types + header parsing. |
| python/tests/test_http.py | Tests sync HTTP client success/error mapping and retry behavior. |
| python/tests/test_hooks.py | Tests hooks interfaces and chaining/safety helpers. |
| python/tests/test_errors.py | Tests error hierarchy and response parsing utilities. |
| python/tests/test_download.py | Tests download URL rewrite + redirect-to-signed-url handling. |
| python/tests/test_config.py | Tests config defaults, env loading, validation, and HTTPS enforcement. |
| python/tests/test_client.py | Tests client construction, account scoping, and service caching. |
| python/tests/test_auth.py | Tests token providers, bearer auth, refresh behavior, and thread safety. |
| python/tests/services/init.py | Marks services tests package. |
| python/tests/oauth/test_pkce.py | Tests PKCE verifier/challenge/state generation. |
| python/tests/oauth/test_exchange.py | Tests OAuth code exchange + refresh flows. |
| python/tests/oauth/test_discovery.py | Tests OAuth discovery and validation/error handling. |
| python/tests/oauth/init.py | Marks oauth tests package. |
| python/tests/conftest.py | Shared pytest fixtures for config/auth/client/account. |
| python/tests/init.py | Marks tests package. |
| python/src/basecamp/webhooks/verify.py | Webhook HMAC signature compute/verify implementation. |
| python/src/basecamp/webhooks/receiver.py | Framework-agnostic webhook receiver (verify, parse, dedupe, dispatch, middleware). |
| python/src/basecamp/webhooks/events.py | Webhook kind constants + kind parsing helper. |
| python/src/basecamp/webhooks/errors.py | Webhook-specific error type. |
| python/src/basecamp/webhooks/init.py | Exposes webhook public API. |
| python/src/basecamp/services/authorization.py | Account-independent authorization discovery service (sync/async). |
| python/src/basecamp/services/init.py | Exports authorization services. |
| python/src/basecamp/py.typed | Marks package as typed for type checkers. |
| python/src/basecamp/oauth/token.py | OAuth token model + expiry helper. |
| python/src/basecamp/oauth/pkce.py | PKCE/state generation utilities. |
| python/src/basecamp/oauth/exchange.py | OAuth token exchange/refresh with validation and error handling. |
| python/src/basecamp/oauth/errors.py | OAuth-specific error wrapper and type mapping. |
| python/src/basecamp/oauth/discovery.py | OAuth discovery client + validation. |
| python/src/basecamp/oauth/config.py | OAuth discovery config model. |
| python/src/basecamp/oauth/authorize.py | Builds authorization URLs (with optional PKCE/scope). |
| python/src/basecamp/oauth/init.py | Exposes OAuth public API. |
| python/src/basecamp/hooks.py | Observability hooks interfaces + chaining/console/safe call helpers. |
| python/src/basecamp/generated/services/webhooks_service.py | Generated Webhooks service (sync/async). |
| python/src/basecamp/generated/services/vaults.py | Generated Vaults service (sync/async). |
| python/src/basecamp/generated/services/uploads.py | Generated Uploads service (sync/async). |
| python/src/basecamp/generated/services/tools.py | Generated Tools service (sync/async). |
| python/src/basecamp/generated/services/todosets.py | Generated Todosets service (sync/async). |
| python/src/basecamp/generated/services/todos.py | Generated Todos service (sync/async). |
| python/src/basecamp/generated/services/todolists.py | Generated Todolists service (sync/async). |
| python/src/basecamp/generated/services/todolist_groups.py | Generated TodolistGroups service (sync/async). |
| python/src/basecamp/generated/services/timesheets.py | Generated Timesheets service (sync/async). |
| python/src/basecamp/generated/services/timeline.py | Generated Timeline service (sync/async). |
| python/src/basecamp/generated/services/templates.py | Generated Templates service (sync/async). |
| python/src/basecamp/generated/services/subscriptions.py | Generated Subscriptions service (sync/async). |
| python/src/basecamp/generated/services/search.py | Generated Search service (sync/async). |
| python/src/basecamp/generated/services/schedules.py | Generated Schedules service (sync/async). |
| python/src/basecamp/generated/services/reports.py | Generated Reports service (sync/async). |
| python/src/basecamp/generated/services/recordings.py | Generated Recordings service (sync/async). |
| python/src/basecamp/generated/services/projects.py | Generated Projects service (sync/async). |
| python/src/basecamp/generated/services/people.py | Generated People service (sync/async). |
| python/src/basecamp/generated/services/messages.py | Generated Messages service (sync/async). |
| python/src/basecamp/generated/services/message_types.py | Generated MessageTypes service (sync/async). |
| python/src/basecamp/generated/services/message_boards.py | Generated MessageBoards service (sync/async). |
| python/src/basecamp/generated/services/lineup.py | Generated Lineup service (sync/async). |
| python/src/basecamp/generated/services/hill_charts.py | Generated HillCharts service (sync/async). |
| python/src/basecamp/generated/services/forwards.py | Generated Forwards service (sync/async). |
| python/src/basecamp/generated/services/events.py | Generated Events service (sync/async). |
| python/src/basecamp/generated/services/documents.py | Generated Documents service (sync/async). |
| python/src/basecamp/generated/services/comments.py | Generated Comments service (sync/async). |
| python/src/basecamp/generated/services/client_visibility.py | Generated ClientVisibility service (sync/async). |
| python/src/basecamp/generated/services/client_replies.py | Generated ClientReplies service (sync/async). |
| python/src/basecamp/generated/services/client_correspondences.py | Generated ClientCorrespondences service (sync/async). |
| python/src/basecamp/generated/services/client_approvals.py | Generated ClientApprovals service (sync/async). |
| python/src/basecamp/generated/services/cards.py | Generated Cards service (sync/async). |
| python/src/basecamp/generated/services/card_tables.py | Generated CardTables service (sync/async). |
| python/src/basecamp/generated/services/card_steps.py | Generated CardSteps service (sync/async). |
| python/src/basecamp/generated/services/card_columns.py | Generated CardColumns service (sync/async). |
| python/src/basecamp/generated/services/campfires.py | Generated Campfires service (sync/async). |
| python/src/basecamp/generated/services/boosts.py | Generated Boosts service (sync/async). |
| python/src/basecamp/generated/services/automation.py | Generated Automation service (sync/async). |
| python/src/basecamp/generated/services/attachments.py | Generated Attachments service (sync/async). |
| python/src/basecamp/generated/services/init.py | Generated services export surface. |
| python/src/basecamp/generated/init.py | Marks generated package. |
| python/src/basecamp/errors.py | Core error types, mapping, and response parsing. |
| python/src/basecamp/download.py | Download helper implementing Basecamp redirect-to-signed-url flow. |
| python/src/basecamp/config.py | Client config (env loading, validation, HTTPS rules, defaults). |
| python/src/basecamp/auth.py | Sync token providers + bearer auth strategy. |
| python/src/basecamp/async_auth.py | Async token providers + bearer auth strategy. |
| python/src/basecamp/_version.py | Python SDK + API version constants. |
| python/src/basecamp/_security.py | Shared security helpers (HTTPS, origin, truncation, redaction, size limits). |
| python/src/basecamp/_pagination.py | Pagination metadata container + header parsers. |
| python/src/basecamp/_http.py | Sync httpx client wrapper with retry, hooks, and error mapping. |
| python/src/basecamp/_async_http.py | Async httpx client wrapper with retry, hooks, and error mapping. |
| python/src/basecamp/init.py | Public package exports. |
| python/scripts/generate_types.py | Generates TypedDicts from OpenAPI schemas. |
| python/scripts/generate_metadata.py | Generates per-operation metadata (retry/idempotency) from behavior model. |
| python/pyproject.toml | Python package metadata, dependencies, ruff/mypy/coverage config. |
| python/conformance/runner/python/pyproject.toml | Adds Python conformance runner project definition. |
| Makefile | Adds Python targets and wires Python into check, clean, and conformance. |
| .pre-commit-config.yaml | Adds Python ruff/mypy/pytest hooks via uv. |
| .gitignore | Ignores Python SDK and Python conformance runner build artifacts. |
| .github/workflows/test.yml | Adds test-python matrix job and runs Python conformance in CI. |
| .github/workflows/release-python.yml | Adds PyPI trusted publishing workflow for the Python SDK. |
| .github/workflows/release-github.yml | Updates GitHub release notes to include Python install instructions and waits for Python release workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
1 issue found across 14 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="python/src/basecamp/download.py">
<violation number="1" location="python/src/basecamp/download.py:23">
P1: `unquote` after the `/`-split can decode `%2F` → `/` and `%2E` → `.`, yielding directory-traversal filenames like `../../etc/passwd`. Strip directory components after decoding to ensure the result is always a bare filename.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
Pull request overview
Adds a new Python SDK to the Basecamp monorepo, generated from the shared OpenAPI spec, with CI + conformance integration and supporting tooling (version sync, drift checks, release workflow).
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Changes:
- Introduces Python SDK core modules (HTTP client, auth, pagination, security helpers), plus OAuth + webhooks utilities and extensive unit tests.
- Adds Python code generation drift checking + Makefile/pre-commit targets to keep generated artifacts in sync.
- Integrates Python into GitHub Actions (test matrix + conformance runner) and adds a PyPI release workflow.
Reviewed changes
Copilot reviewed 58 out of 110 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/sync-api-version.sh | Syncs API version into Python _version.py. |
| scripts/bump-version.sh | Bumps Python package versions alongside other SDKs. |
| scripts/check-python-service-drift.sh | Adds a Python generated-artifact drift detector script. |
| python/pyproject.toml | Defines the Python package, dependencies, and tooling config. |
| python/conformance/runner/python/pyproject.toml | Adds a Python conformance runner package with editable SDK source. |
| python/src/basecamp/_http.py | Implements sync HTTP client with retries/auth/hooks. |
| python/src/basecamp/auth.py | Implements token providers + bearer auth (sync). |
| python/src/basecamp/async_auth.py | Implements token providers + bearer auth (async). |
| python/src/basecamp/errors.py | Adds SDK error hierarchy and HTTP->error mapping. |
| python/src/basecamp/_security.py | Adds URL/HTTPS helpers, header redaction, size limits. |
| python/src/basecamp/_pagination.py | Adds list result wrapper + pagination header parsing. |
| python/src/basecamp/download.py | Adds signed-download flow (sync/async). |
| python/src/basecamp/hooks.py | Adds observability hooks + chaining/console hooks. |
| python/src/basecamp/oauth/* | Adds OAuth discovery, PKCE/state, authorize URL builder, token exchange. |
| python/src/basecamp/webhooks/* | Adds webhook signature verification + receiver/dispatch utilities. |
| python/src/basecamp/generated/services/* | Adds generated service classes (sync + async) from OpenAPI. |
| python/tests/* | Adds unit tests for auth/http/errors/pagination/security/download/oauth/webhooks. |
| Makefile | Adds Python targets and wires Python into check, clean, and conformance. |
| .pre-commit-config.yaml | Adds Python ruff/mypy/pytest hooks. |
| .gitignore | Ignores Python build/uv artifacts. |
| .github/workflows/test.yml | Adds test-python job and runs Python conformance in conformance job. |
| .github/workflows/release-python.yml | Adds PyPI trusted-publishing release workflow for Python. |
| .github/workflows/release-github.yml | Includes Python in GitHub release orchestration + install snippet. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Adds a new Python SDK to the Basecamp API monorepo, including generated service clients/types/metadata, OAuth + webhooks helpers, and full CI/release/conformance integration alongside existing SDKs.
Changes:
- Introduces Python sync + async client foundations (httpx-based) plus shared utilities (errors, pagination, security helpers, downloads, hooks, webhooks).
- Adds Python build/test/typecheck/drift/conformance targets and wires them into CI + pre-commit.
- Extends version bump/sync scripts and release automation to include the Python package.
Pull request overview
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 58 out of 110 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/sync-api-version.sh | Syncs API version constant into Python _version.py. |
| scripts/check-python-service-drift.sh | Adds Python generated-artifact drift verification script. |
| scripts/bump-version.sh | Extends version bumping to Python pyproject.toml + _version.py. |
| python/tests/webhooks/test_verify.py | Tests webhook signature computation/verification. |
| python/tests/webhooks/test_receiver.py | Tests webhook receiver routing, middleware, deduplication, signature verification. |
| python/tests/webhooks/init.py | Declares webhooks test package. |
| python/tests/test_security.py | Tests security helpers (origin checks, HTTPS enforcement, truncation, redaction, body sizing). |
| python/tests/test_pagination.py | Tests pagination parsing and ListResult behavior. |
| python/tests/test_http.py | Tests http client behavior: retries, error mapping, headers, retry-after. |
| python/tests/test_hooks.py | Tests hooks chaining, console hooks, and safe hook execution. |
| python/tests/test_errors.py | Tests error hierarchy, parsing, and retry-after parsing logic. |
| python/tests/test_download.py | Tests download URL rewrite/redirect handling and filename extraction. |
| python/tests/test_config.py | Tests config defaults, env loading, validation, HTTPS enforcement. |
| python/tests/test_client.py | Tests core client construction and account scoping behavior. |
| python/tests/test_auth.py | Tests auth providers, refresh behavior, and thread safety. |
| python/tests/services/init.py | Declares services test package. |
| python/tests/oauth/test_pkce.py | Tests PKCE/state generation. |
| python/tests/oauth/test_exchange.py | Tests token exchange/refresh flows and legacy formats. |
| python/tests/oauth/test_discovery.py | Tests OAuth discovery behaviors and error cases. |
| python/tests/oauth/init.py | Declares oauth test package. |
| python/tests/conftest.py | Adds shared pytest fixtures for Python SDK tests. |
| python/tests/init.py | Declares tests package. |
| python/src/basecamp/webhooks/verify.py | Implements webhook HMAC signature computation/verification. |
| python/src/basecamp/webhooks/receiver.py | Implements framework-agnostic webhook receiver with routing + middleware + dedup. |
| python/src/basecamp/webhooks/events.py | Adds webhook kind constants and kind parsing helper. |
| python/src/basecamp/webhooks/errors.py | Defines webhook-specific error type. |
| python/src/basecamp/webhooks/init.py | Public webhooks module exports. |
| python/src/basecamp/services/authorization.py | Adds (a)sync authorization service wrapper with discovery fallback. |
| python/src/basecamp/services/init.py | Exposes authorization services. |
| python/src/basecamp/py.typed | Marks package as typed for type checkers. |
| python/src/basecamp/oauth/token.py | Defines OAuth token model and expiration logic. |
| python/src/basecamp/oauth/pkce.py | Implements PKCE + state helpers. |
| python/src/basecamp/oauth/exchange.py | Implements token exchange/refresh flows with validation and error mapping. |
| python/src/basecamp/oauth/errors.py | Defines OAuth-specific error wrapper mapping to SDK error codes. |
| python/src/basecamp/oauth/discovery.py | Implements OAuth discovery for issuer endpoints. |
| python/src/basecamp/oauth/config.py | Defines OAuth discovery config model. |
| python/src/basecamp/oauth/authorize.py | Builds authorization URL with optional PKCE/scope. |
| python/src/basecamp/oauth/init.py | Public OAuth module exports. |
| python/src/basecamp/hooks.py | Adds observability hook interfaces, chaining, and console hooks. |
| python/src/basecamp/generated/services/webhooks_service.py | Generated service client for webhook operations. |
| python/src/basecamp/generated/services/vaults.py | Generated service client for vault operations. |
| python/src/basecamp/generated/services/uploads.py | Generated service client for upload operations. |
| python/src/basecamp/generated/services/tools.py | Generated service client for tools operations. |
| python/src/basecamp/generated/services/todosets.py | Generated service client for todosets operations. |
| python/src/basecamp/generated/services/todos.py | Generated service client for todos operations. |
| python/src/basecamp/generated/services/todolists.py | Generated service client for todolists operations. |
| python/src/basecamp/generated/services/todolist_groups.py | Generated service client for todolist group operations. |
| python/src/basecamp/generated/services/timesheets.py | Generated service client for timesheet operations. |
| python/src/basecamp/generated/services/timeline.py | Generated service client for timeline operations. |
| python/src/basecamp/generated/services/templates.py | Generated service client for templates operations. |
| python/src/basecamp/generated/services/subscriptions.py | Generated service client for subscriptions operations. |
| python/src/basecamp/generated/services/search.py | Generated service client for search operations. |
| python/src/basecamp/generated/services/schedules.py | Generated service client for schedule operations. |
| python/src/basecamp/generated/services/reports.py | Generated service client for reports operations. |
| python/src/basecamp/generated/services/recordings.py | Generated service client for recordings operations. |
| python/src/basecamp/generated/services/projects.py | Generated service client for projects operations. |
| python/src/basecamp/generated/services/people.py | Generated service client for people operations. |
| python/src/basecamp/generated/services/messages.py | Generated service client for messages operations. |
| python/src/basecamp/generated/services/message_types.py | Generated service client for message type operations. |
| python/src/basecamp/generated/services/message_boards.py | Generated service client for message board operations. |
| python/src/basecamp/generated/services/lineup.py | Generated service client for lineup operations. |
| python/src/basecamp/generated/services/hill_charts.py | Generated service client for hill chart operations. |
| python/src/basecamp/generated/services/forwards.py | Generated service client for forwards operations. |
| python/src/basecamp/generated/services/events.py | Generated service client for events operations. |
| python/src/basecamp/generated/services/documents.py | Generated service client for documents operations. |
| python/src/basecamp/generated/services/comments.py | Generated service client for comments operations. |
| python/src/basecamp/generated/services/client_visibility.py | Generated service client for client visibility operations. |
| python/src/basecamp/generated/services/client_replies.py | Generated service client for client replies operations. |
| python/src/basecamp/generated/services/client_correspondences.py | Generated service client for client correspondences operations. |
| python/src/basecamp/generated/services/client_approvals.py | Generated service client for client approvals operations. |
| python/src/basecamp/generated/services/checkins.py | Generated service client for check-in operations. |
| python/src/basecamp/generated/services/cards.py | Generated service client for cards operations. |
| python/src/basecamp/generated/services/card_tables.py | Generated service client for card tables operations. |
| python/src/basecamp/generated/services/card_steps.py | Generated service client for card steps operations. |
| python/src/basecamp/generated/services/card_columns.py | Generated service client for card columns operations. |
| python/src/basecamp/generated/services/campfires.py | Generated service client for campfire operations. |
| python/src/basecamp/generated/services/boosts.py | Generated service client for boosts operations. |
| python/src/basecamp/generated/services/automation.py | Generated service client for automation operations. |
| python/src/basecamp/generated/services/attachments.py | Generated service client for attachments operations. |
| python/src/basecamp/generated/services/init.py | Generated exports for all generated service clients. |
| python/src/basecamp/generated/init.py | Declares generated package. |
| python/src/basecamp/errors.py | Implements SDK error types, mapping, and parsing helpers. |
| python/src/basecamp/download.py | Implements authenticated download hop + signed URL fetch behavior. |
| python/src/basecamp/config.py | Adds client configuration with validation and HTTPS enforcement. |
| python/src/basecamp/auth.py | Implements sync auth/token providers including refreshable OAuth provider. |
| python/src/basecamp/async_auth.py | Implements async auth/token providers including refreshable OAuth provider. |
| python/src/basecamp/_version.py | Defines SDK version + API version constants. |
| python/src/basecamp/_security.py | Provides security utilities (HTTPS enforcement, origin checks, truncation, redaction, size checks). |
| python/src/basecamp/_pagination.py | Provides pagination helpers and ListResult metadata container. |
| python/src/basecamp/_http.py | Implements sync HTTP client with retries, auth injection, hooks, and error mapping. |
| python/src/basecamp/init.py | Defines Python package public API exports. |
| python/scripts/generate_types.py | Generates TypedDict types from OpenAPI schemas. |
| python/scripts/generate_metadata.py | Generates metadata.json from OpenAPI + behavior model for retry/idempotency. |
| python/pyproject.toml | Defines Python package metadata, dependencies, test/lint/typecheck config. |
| conformance/runner/python/pyproject.toml | Adds Python conformance runner environment definition. |
| Makefile | Adds Python build/test/typecheck/drift/conformance targets and includes in top-level check/clean. |
| .pre-commit-config.yaml | Adds Python ruff/mypy/pytest hooks. |
| .gitignore | Ignores Python build/venv/uv artifacts. |
| .github/workflows/test.yml | Adds Python CI matrix + wires Python conformance into main conformance job. |
| .github/workflows/release-python.yml | Adds PyPI publish workflow with tag verification and dry-run mode. |
| .github/workflows/release-github.yml | Includes Python release workflow in aggregate and documents pip install in release notes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 58 out of 111 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 58 out of 111 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 58 out of 111 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 113 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 292e42dcb5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 113 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8e9ad252fc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 113 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b18e2e6571
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 113 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 82315f8015
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 113 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Sixth language SDK for the Basecamp API, generated from the shared OpenAPI spec and passing the shared conformance test suite — setting the stricter bar on metadata-driven retry, totalCount, and truncated that Ruby currently skips. SDK (python/src/basecamp/): - Sync Client + AsyncClient with httpx, both from day one - 40 generated service files (181 operations) with sync+async classes - Full error hierarchy matching sibling SDKs (ErrorCode, ExitCode) - Metadata-driven retry: GETs always retry, idempotent mutations (PUT/DELETE marked in behavior-model.json) retry too - Eager ListResult(list) with .meta (total_count, truncated) - OAuth module: discovery, PKCE, code exchange, token refresh with rotation - Webhooks module: HMAC-SHA256 verification, glob-pattern receiver, sliding-window dedup, middleware chain - 149 TypedDict classes for IDE/mypy support, py.typed PEP 561 marker Quality gates (exceeds siblings): - mypy type checking in CI — first interpreted-language SDK with it - Generated code drift check in CI — regenerates all 3 artifact types (services, metadata.json, types.py), formats, and diffs - ruff format enforcement in CI and pre-commit - pytest-cov coverage enforcement at 60% (currently 68%) - 186 unit tests across core, OAuth, and webhooks modules - 3.14 canary with continue-on-error (matches Ruby's head) - Pre-commit hooks: ruff lint+format (commit), mypy + pytest (push) Monorepo integration: - CI: test-python job (3.11/3.12/3.13/3.14 matrix), conformance - Release: release-python.yml with PyPI OIDC trusted publishing, build attestations, idempotency guard via PyPI JSON API, wired into release-github.yml wait loop and install snippets - Makefile: py-generate (with ruff format), py-build, py-test, py-typecheck, py-check, py-check-drift, py-clean, conformance-python - Version management: bump-version.sh, sync-api-version.sh - uv.lock committed for reproducible builds - .gitignore, pre-commit hooks
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 60 out of 113 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1f497d82de
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Summary
Client+AsyncClientwith httpx, both from day oneQuality gates
Exceeds sibling SDKs on: mypy in CI (first interpreted-language SDK), generated code drift check covers services + metadata.json + types.py (most thorough), ruff format enforcement, 3.14 canary with continue-on-error.
Monorepo integration
test-pythonjob (3.11/3.12/3.13/3.14 matrix) with lint, format, typecheck, drift check, coverageconformance-pythonin CI and Makefilerelease-python.ymlwith PyPI OIDC trusted publishing, build attestations, idempotency guard via PyPI JSON APIbump-version.sh,sync-api-version.sh,releasetarget verificationpy-generate(with ruff format),py-build,py-test,py-typecheck,py-check,py-check-drift,py-cleanTest plan
cd python && uv sync --dev && uv run pytest --cov --cov-fail-under=60— 186 passed, 68%cd python && uv run ruff check src/ tests/— All checks passedcd python && uv run mypy src/basecamp/ --ignore-missing-imports— Success: no issues found in 29 source filesmake py-check(drift + tests + lint + typecheck) — all greenmake py-generate && git diff --exit-code python/src/basecamp/generated/(idempotent) — no difftest-pythonjob passes on all matrix legs — 3.11, 3.12, 3.13, 3.14 all successconformancejob passes with Python runner — success