Skip to content

Apply better-py skill rules - #256

Merged
Subhransu-De merged 3 commits into
mainfrom
apply-better-py-rules
Oct 14, 2026
Merged

Subhransu-De merged 3 commits into
mainfrom
apply-better-py-rules

Conversation

@Subhransu-De

@Subhransu-De Subhransu-De commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

What changes

Applies the upgraded better-py skill to this repo and fixes the HIGH and MEDIUM findings from an audit of this repo against that skill (the skill lives at skills/software/better-py in the destack repo; the full audit is linked below).

Main changes:

  • ruff.toml/ty.toml no longer hardcode the Python version (read from requires-python), drop TCH, stop ignoring ANN401, and ban typing.Any, typing.TYPE_CHECKING, getattr, setattr and hasattr — with the existing app/auth/openapi.py exception kept as an explicit per-file ignore.
  • Removed every remaining typing.Any: a named OpenAPIDocument alias, pydantic models in the entity API and OpenAPI contract tests and the Keycloak/scenario-test clients, and a typed TokenClaimOverrides/TokenFactory pair for the integration token helpers.
  • The behave scenario-test context is now typed via a runner.pyi stub instead of Any+getattr.
  • Removed the one if TYPE_CHECKING: block (UUID is not a cycle).
  • Flattened the four test classes in tests/unit/settings/test_settings.py into plain functions.
  • Smaller idiom fixes: Self instead of a quoted return type, str.partition instead of str.split, dropped a walrus assignment, keyword-only pagination parameters, named entity field constraints, TypeAdapter instead of cast, a domain OIDCDiscoveryError instead of a bare RuntimeError.
  • seed/__main__.py and app/main.py return an exit code through raise SystemExit(main()).
  • The OpenAPI snapshot update switch is now a pytest --update-openapi-snapshot option instead of an env var read inside the test (make openapi-snapshot updated to match).
  • make lint/make format now also cover .docker/.

Deliberately left unchanged, with the reason in the commit messages: seed/__main__.py's and alembic/env.py's os.environ reads (both run in the migration image, which contains neither app/ nor pydantic-settings) (coupled to its existing import-guard pattern, and I have no Docker here to verify a change to a migration entry point), the Keycloak setup script's remaining env reads (it configures Keycloak, not this app), the integration tests' container-password override (test-only), and the no-init-process audit note (Compose already runs python in exec form as PID 1, so signals are delivered without one). A handful of JUDGEMENT-level audit findings (SQLAlchemy mixins, the FastAPI subclass, package-by-layer under import-linter) are architecture choices this template makes on purpose and are not changed.

Audit this PR is based on: https://manuscript.subhransu.de/3xt6abhd-fastapi-template-vs-better-py-audit-of-where-the-project-dif

Gates

  • make check is green
  • make test-integration is green (required for model, repository, database or migration changes) — not run locally, no Docker available in this environment. This PR touches the integration test helpers and fixtures, so please confirm CI's test-integration job is green before merging.
  • tests/contract/openapi.json is updated and the diff is intended — no API change, snapshot untouched.
  • New Keycloak roles are added to both realm exports in .docker/ — no new roles.

Notes for the reviewer

  • make test-integration could not be run locally (Docker is unavailable in this environment). I'll be watching CI and will act on anything it finds.
  • The PR intentionally does not touch every LOW/JUDGEMENT finding from the audit (logic in some __init__.py files, test helpers reading private attributes, etc.) to keep this change reviewable; happy to follow up separately if wanted.

🤖 Generated with Claude Code. Written by claude-sonnet-5, reviewed and corrected by claude-opus-5-5.

Fixes the HIGH and MEDIUM findings from the audit of this repo against
the better-py skill (skills/software/better-py in destack):

- ruff.toml: drop the hardcoded target-version, remove TCH, stop
  ignoring ANN401, and ban typing.Any, typing.TYPE_CHECKING, getattr,
  setattr and hasattr (with an explicit per-file exception for
  app/auth/openapi.py, matching the existing architecture-test
  allowlist). ty.toml: drop the hardcoded python-version so both tools
  read it from requires-python.
- Remove the remaining typing.Any uses: a named OpenAPIDocument alias
  in app/auth/openapi.py, pydantic models instead of raw dict/.json()
  handling in the entity API tests, the OpenAPI contract test, the
  Keycloak setup script and the scenario-test client, and a typed
  TokenClaimOverrides/TokenFactory pair for the integration token
  helpers instead of **claims: Any.
- Type the behave scenario-test context properly (a runner.pyi stub
  with every attribute used) instead of Any, and replace the getattr
  fallback in environment.py with context.add_cleanup.
- Remove the one remaining if TYPE_CHECKING: block (app/repository/base.py);
  UUID is not a cycle.
- Flatten the four test classes in tests/unit/settings/test_settings.py
  into plain functions, per better-py's testing.md.
- Smaller idiom fixes: Self instead of a quoted return type on two
  alternate constructors, str.partition instead of str.split, drop a
  walrus assignment, make the pagination parameters keyword-only,
  name the repeated entity field constraints, use TypeAdapter instead
  of cast in the exception tests, and raise OIDCDiscoveryError instead
  of a bare RuntimeError from OIDC discovery.
- seed/__main__.py reads DatabaseSettings instead of os.environ
  directly, and main() now returns an int with raise SystemExit(main()),
  matching app/main.py and the skill's script.md.
- The OpenAPI snapshot update flag is now a pytest --update-openapi-snapshot
  option instead of an env var read inside the test.
- Makefile: lint and format now also cover .docker/.

Deliberately left unchanged, with the reason:
- alembic/env.py's os.environ.get("DATABASE_URL") fallback: switching
  it to DatabaseSettings would make the existing
  try/except ModuleNotFoundError fallback (which lets alembic run
  before "app" is importable) inconsistent, and I can't run
  `make test-integration` here (no Docker) to verify a change to a
  migration entry point.
- .docker/configure_keycloak_client.py's remaining os.environ reads:
  it configures Keycloak, not the application, so it doesn't belong
  behind app.settings.
- tests/integration/conftest.py's INTEGRATION_TEST_CONTAINER_PASSWORD
  read: a test-only container password override, not app config.
- Docker Compose services already run python in exec form as PID 1
  (no shell wrapper), so SIGTERM is delivered without an init process.
- Several JUDGEMENT-level findings from the audit (mixins on the
  SQLAlchemy models, the FastAPI subclass, package-by-layer under
  import-linter, session-scoped fixtures, generality the tests alone
  exercise) are architecture choices this template makes on purpose,
  not violations.

Verified: make check (ruff, ruff format, ty --error-on-warning,
import-linter, 167 unit tests), make lint-typos. make test-integration
was not run (needs Docker, unavailable in this environment); it is
required by CI and by this repo's own PR template for database-layer
changes, so CI will need to confirm the seed/__main__.py and
tests/integration/conftest.py and tests/integration/test_entities_api.py
changes.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T19:52:21.236492Z f61f1e0 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

SonarCloud flagged this function's complexity at 19 against the
15 allowed, counted as new code because this PR changed its
annotation line. Extract the per-operation and description-merge
logic into two small functions so the loop body is a single call.

Verified: make check, pytest tests/unit/test_openapi_contract.py.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
@Subhransu-De

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 90e338795f

ℹ️ 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".

Code review fixes:

- seed/__main__.py imported app.settings.DatabaseSettings, but the
  migration image copies only alembic/ and seed/ and installs only the
  migration group, so `docker compose --profile seed run seed` would
  fail with ModuleNotFoundError. CI never runs the seed profile, so it
  would not have caught this. Read DATABASE_URL directly again; the
  int return and raise SystemExit(main()) stay.
- tests/integration/test_entities_api.py declared a ProblemBody model
  that duplicated app.exceptions.ProblemDetails field for field.
  Validate responses with ProblemDetails instead.

Verified: make check.
@Subhransu-De

Copy link
Copy Markdown
Owner Author

@codex review

@sonarqubecloud

Copy link
Copy Markdown

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: f61f1e0bdc

ℹ️ 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".

@Subhransu-De
Subhransu-De merged commit 5b805c1 into main Oct 14, 2026
37 checks passed
@Subhransu-De
Subhransu-De deleted the apply-better-py-rules branch October 14, 2026 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant