feat: synchronous Psycopg 3 support via the psycopg_sync driver#222
Conversation
Parameterize psycopgBase by an async flag - the sqlite_base pattern - so both psycopg flavors share one implementation: the sync flavor emits plain functions, psycopg.Connection/Cursor annotations, a called-not-awaited QueryResults, and :copyfrom via a synchronous cursor.copy(). Widen every psycopg gate (SQL rewrite, reserved locals, LiteralString constants, imports, docstrings) through a new SQLDriver.IsPsycopg helper, add the test/driver_psycopg_sync fixture tree with ported runtime suites, and wire up nox sessions, CI, build scripts, docs, and the shared postgres cleanup.
📝 WalkthroughWalkthroughAdds the 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
@coderabbitai full-review |
|
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. Your recent PR review activity is in the 95th percentile or higher among CodeRabbit users, so adaptive limits apply. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 1 minute. |
|
@coderabbitai full-review |
|
✅ Action performedFull review finished. |
|
@coderabbitai full-review |
|
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. Your recent PR review activity is in the 95th percentile or higher among CodeRabbit users, so adaptive limits apply. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 55 minutes. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/ci.yml:
- Line 341: Remove the spaces immediately inside the inline needs sequence in
the workflow’s needs declaration, preserving all listed job dependencies and
comma spacing so the YAML passes lint.
In `@test/driver_psycopg_sync/attrs/test_psycopg_sync_attrs_classes.py`:
- Around line 43-53: Extract the duplicated _NoRowCursor and _NoRowConn stubs
into one shared test helper, preserving fetchone returning None and execute
returning the no-row cursor. In
test/driver_psycopg_sync/attrs/test_psycopg_sync_attrs_classes.py#L43-L53,
test/driver_psycopg_sync/dataclass/test_psycopg_sync_dataclass_classes.py#L44-L54,
and test/driver_psycopg_sync/omit_tc/test_omit_typechecking_runtime.py#L52-L62,
remove the local definitions and import the shared helper.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 8fec8cac-3f1c-4c7f-b164-2123d96b5fd8
⛔ Files ignored due to path filters (78)
test/driver_aiosqlite/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasmtest/driver_asyncpg/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasmtest/driver_psycopg_async/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasmtest/driver_psycopg_sync/attrs/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries_copy_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries_field_namings.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries_copy_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries_field_namings.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries_copy_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries_field_namings.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_converters.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_copy_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_field_namings.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries_copy_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries_field_namings.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries_copy_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries_field_namings.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/omit_tc/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/omit_tc/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/omit_tc/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/omit_tc/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/omit_tc/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/omit_tc/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/omit_tc/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/omit_tc/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries_copy_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries_field_namings.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries_copy_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries_field_namings.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasmtest/driver_sqlite3/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasm
📒 Files selected for processing (66)
.changes/unreleased/Added-20260724-120000.yaml.github/workflows/ci.ymlREADME.mddocs/content/_index.mddocs/content/docs/_index.mddocs/content/docs/getting-started.mddocs/content/docs/guide/configuration.mddocs/content/docs/guide/drivers.mddocs/content/docs/guide/enums.mddocs/content/docs/guide/writing-queries.mddocs/content/docs/reference/configuration-options.mddocs/content/docs/reference/feature-support.mdinternal/config/constants.gointernal/config/constants_test.gointernal/driver/asyncpg.gointernal/driver/common.gointernal/driver/driver.gointernal/driver/driver_test.gointernal/driver/psycopg.gointernal/driver/psycopg_test.gointernal/render/imports.gointernal/render/imports_test.gointernal/render/queries.gointernal/render/render_queries_test.gointernal/transform/queries.gointernal/transform/queries_test.gointernal/writer/docstrings.gointernal/writer/docstrings_test.gonoxfile.pyscripts/build/build.batscripts/build/build.shsqlc.yamltest/conftest.pytest/driver_aiosqlite/sqlc.yamltest/driver_asyncpg/sqlc.yamltest/driver_psycopg_async/sqlc.yamltest/driver_psycopg_sync/__init__.pytest/driver_psycopg_sync/attrs/__init__.pytest/driver_psycopg_sync/attrs/ruff.tomltest/driver_psycopg_sync/attrs/test_psycopg_sync_attrs_classes.pytest/driver_psycopg_sync/attrs/test_psycopg_sync_attrs_functions.pytest/driver_psycopg_sync/dataclass/__init__.pytest/driver_psycopg_sync/dataclass/ruff.tomltest/driver_psycopg_sync/dataclass/test_psycopg_sync_dataclass_classes.pytest/driver_psycopg_sync/dataclass/test_psycopg_sync_dataclass_functions.pytest/driver_psycopg_sync/msgspec/__init__.pytest/driver_psycopg_sync/msgspec/ruff.tomltest/driver_psycopg_sync/msgspec/test_psycopg_sync_msgspec_classes.pytest/driver_psycopg_sync/msgspec/test_psycopg_sync_msgspec_functions.pytest/driver_psycopg_sync/omit_tc/__init__.pytest/driver_psycopg_sync/omit_tc/ruff.tomltest/driver_psycopg_sync/omit_tc/test_omit_typechecking_import.pytest/driver_psycopg_sync/omit_tc/test_omit_typechecking_runtime.pytest/driver_psycopg_sync/pydantic/__init__.pytest/driver_psycopg_sync/pydantic/ruff.tomltest/driver_psycopg_sync/pydantic/test_psycopg_sync_pydantic_classes.pytest/driver_psycopg_sync/pydantic/test_psycopg_sync_pydantic_functions.pytest/driver_psycopg_sync/queries.sqltest/driver_psycopg_sync/queries_converters.sqltest/driver_psycopg_sync/queries_copy_override.sqltest/driver_psycopg_sync/queries_enum_override.sqltest/driver_psycopg_sync/queries_field_namings.sqltest/driver_psycopg_sync/queries_invalid_identifiers.sqltest/driver_psycopg_sync/schema.sqltest/driver_psycopg_sync/sqlc.yamltest/driver_sqlite3/sqlc.yaml
Deduplicate the no-row connection stubs from all nine sync test files into a shared test/driver_psycopg_sync/no_row_conn.py helper, and drop the yamllint-offending spaces inside the ci-done needs brackets.
|
@coderabbitai full-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changes/unreleased/Added-20260724-120000.yaml:
- Line 2: Update the release-note body for psycopg_sync to qualify that it
supports the same supported commands as psycopg_async, or explicitly state that
:execlastid is excluded; keep the remaining feature description unchanged.
In `@docs/content/docs/getting-started.md`:
- Around line 41-50: Update the Psycopg installation commands in both the
psycopg_async and psycopg_sync tabs to require Psycopg version 3.2 or newer,
matching the documented and package metadata minimum.
In `@test/driver_psycopg_sync/dataclass/test_psycopg_sync_dataclass_functions.py`:
- Line 779: Update the inline suppression on the total assertion in the
dataclass test to use valid Ruff syntax, specifically noqa: PLR2004 or ruff:
ignore[PLR2004], while preserving the assertion and its expected value.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: b6e738ff-22cf-4a7c-bb52-6f39fbf32631
⛔ Files ignored due to path filters (78)
test/driver_aiosqlite/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasmtest/driver_asyncpg/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasmtest/driver_psycopg_async/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasmtest/driver_psycopg_sync/attrs/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries_copy_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries_field_namings.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/classes/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/attrs/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries_copy_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries_field_namings.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/attrs/functions/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries_copy_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries_field_namings.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/classes/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/dataclass/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_converters.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_copy_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_field_namings.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/dataclass/functions/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries_copy_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries_field_namings.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/classes/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/msgspec/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries_copy_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries_field_namings.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/msgspec/functions/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/omit_tc/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/omit_tc/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/omit_tc/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/omit_tc/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/omit_tc/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/omit_tc/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/omit_tc/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/omit_tc/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/classes/__init__.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/enums.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/models.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries_copy_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries_enum_override.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries_field_namings.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/classes/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/classes/**test/driver_psycopg_sync/pydantic/functions/__init__.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/enums.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/models.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries_copy_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries_enum_override.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries_field_namings.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/pydantic/functions/queries_invalid_identifiers.pyis excluded by!test/driver_*/*/functions/**test/driver_psycopg_sync/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasmtest/driver_sqlite3/sqlc-gen-better-python.wasmis excluded by!**/*.wasm,!**/*.wasm
📒 Files selected for processing (67)
.changes/unreleased/Added-20260724-120000.yaml.github/workflows/ci.ymlREADME.mddocs/content/_index.mddocs/content/docs/_index.mddocs/content/docs/getting-started.mddocs/content/docs/guide/configuration.mddocs/content/docs/guide/drivers.mddocs/content/docs/guide/enums.mddocs/content/docs/guide/writing-queries.mddocs/content/docs/reference/configuration-options.mddocs/content/docs/reference/feature-support.mdinternal/config/constants.gointernal/config/constants_test.gointernal/driver/asyncpg.gointernal/driver/common.gointernal/driver/driver.gointernal/driver/driver_test.gointernal/driver/psycopg.gointernal/driver/psycopg_test.gointernal/render/imports.gointernal/render/imports_test.gointernal/render/queries.gointernal/render/render_queries_test.gointernal/transform/queries.gointernal/transform/queries_test.gointernal/writer/docstrings.gointernal/writer/docstrings_test.gonoxfile.pyscripts/build/build.batscripts/build/build.shsqlc.yamltest/conftest.pytest/driver_aiosqlite/sqlc.yamltest/driver_asyncpg/sqlc.yamltest/driver_psycopg_async/sqlc.yamltest/driver_psycopg_sync/__init__.pytest/driver_psycopg_sync/attrs/__init__.pytest/driver_psycopg_sync/attrs/ruff.tomltest/driver_psycopg_sync/attrs/test_psycopg_sync_attrs_classes.pytest/driver_psycopg_sync/attrs/test_psycopg_sync_attrs_functions.pytest/driver_psycopg_sync/dataclass/__init__.pytest/driver_psycopg_sync/dataclass/ruff.tomltest/driver_psycopg_sync/dataclass/test_psycopg_sync_dataclass_classes.pytest/driver_psycopg_sync/dataclass/test_psycopg_sync_dataclass_functions.pytest/driver_psycopg_sync/msgspec/__init__.pytest/driver_psycopg_sync/msgspec/ruff.tomltest/driver_psycopg_sync/msgspec/test_psycopg_sync_msgspec_classes.pytest/driver_psycopg_sync/msgspec/test_psycopg_sync_msgspec_functions.pytest/driver_psycopg_sync/no_row_conn.pytest/driver_psycopg_sync/omit_tc/__init__.pytest/driver_psycopg_sync/omit_tc/ruff.tomltest/driver_psycopg_sync/omit_tc/test_omit_typechecking_import.pytest/driver_psycopg_sync/omit_tc/test_omit_typechecking_runtime.pytest/driver_psycopg_sync/pydantic/__init__.pytest/driver_psycopg_sync/pydantic/ruff.tomltest/driver_psycopg_sync/pydantic/test_psycopg_sync_pydantic_classes.pytest/driver_psycopg_sync/pydantic/test_psycopg_sync_pydantic_functions.pytest/driver_psycopg_sync/queries.sqltest/driver_psycopg_sync/queries_converters.sqltest/driver_psycopg_sync/queries_copy_override.sqltest/driver_psycopg_sync/queries_enum_override.sqltest/driver_psycopg_sync/queries_field_namings.sqltest/driver_psycopg_sync/queries_invalid_identifiers.sqltest/driver_psycopg_sync/schema.sqltest/driver_psycopg_sync/sqlc.yamltest/driver_sqlite3/sqlc.yaml
Qualify the changelog body to say the same supported commands with :execlastid excluded, and pin the psycopg install tabs to the documented minimum of psycopg 3.2.
Adds the synchronous flavor of the Psycopg 3 driver:
sql_driver: "psycopg_sync"generates plain synchronous code for psycopg with full command parity topsycopg_async-:one,:many,:exec,:execresult,:execrows, and:copyfrom(streamed through a synchronouscursor.copy()).:execlastidstays unsupported, as on the other PostgreSQL drivers.One implementation, two flavors.
psycopgBaseis now parameterized by an async flag - thesqlite_base.gopattern - since psycopg's sync API mirrors the async one method for method. The sync flavor emitspsycopg.Connection[psycopg.rows.TupleRow]/psycopg.Cursorannotations, dropsawait/async with, and its:onecollapses to a plain chainedconn.execute(...).fetchone(). The async flavor's output is byte-identical to before (all four existing fixture trees passsqlc diffunder the rebuilt wasm).Shared psycopg contract. Everything flavor-independent is reused as-is via a new
SQLDriver.IsPsycopg()helper: the%(pN)splaceholder rewrite, named-dict binding,typing.Final[typing.LiteralString]constants, the json/jsonb raw-text loader registration, reserved generated locals, and theQueryResultsnamed-params variant (sync gets__call__/__iter__/__next__instead of__await__/__aiter__/__anext__).Testing. New
test/driver_psycopg_synctree with the full model-type matrix plusomit_tc, generated fixtures checked by pyright strict + ruff, sync emission goldens in Go, and all ten runtime pytest suites ported to sync style (full suite: 2367 passed). The shared-table id constant for the persistenttest_invalid_identifiers/3rd_party_statstables gets its own per-tree value (806060), and the shared postgres session cleanup now also covers the enum tables.Docs: drivers guide section, getting-started tabs, feature-support matrix (including a sync
prepare_thresholdexample), configuration references, README.