Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6e0d648
feat(introspection)!: postgres takes its own status families home, an…
vistart Oct 31, 2026
354050e
fix(postgres): run psycopg's async mode on the event loop it can wait…
vistart Nov 1, 2026
4cbacab
refactor(introspection)!: name the PostgreSQL introspectors after the…
vistart Nov 1, 2026
1450850
docs(introspection): say what supports_extensions promises, and stop …
vistart Nov 2, 2026
5d25ae9
feat(introspection): PostgreSQL answers per-table usage counters
vistart Nov 2, 2026
d7a141d
fix(introspection): PostgreSQL renders the unused-indexes listing ins…
vistart Nov 2, 2026
d84e1c1
fix(introspection): answer supports_extensions without splitting the …
vistart Nov 2, 2026
5c80137
feat(introspection): PostgreSQL answers the four operational families
vistart Nov 2, 2026
3e7e10e
fix(introspection): read table_name in the four formatters that take one
vistart Nov 2, 2026
2e983e6
test(roundtrip): register the data-profile family as a declared gap
vistart Nov 3, 2026
6c785a4
feat(postgres): answer the profile from pg_stats, and label it an est…
vistart Nov 3, 2026
bf15e1b
test(postgres): measure the profile against a real server
vistart Nov 3, 2026
d32ea51
fix(postgres): read pg_stats arrays through array_to_json
vistart Nov 3, 2026
c9b4dc0
fix(postgres): admit when the vintage of an estimate is not recorded
vistart Nov 3, 2026
cab9e1c
feat(postgres): measure the two-sided coverage, the family's last probe
vistart Nov 3, 2026
b165273
feat(postgres): let the CLI ask every family the dialect answers
vistart Nov 3, 2026
67744a4
test(ci): install the testsuite from the release line, not from a fea…
vistart Nov 5, 2026
04b078e
fix(roundtrip): answer for the set-operation node core now ships
vistart Nov 6, 2026
28a2475
test(postgres): cite measured servers by scenario, not by address
vistart Nov 7, 2026
7c47488
refactor: one definition for every value two places were writing
vistart Nov 7, 2026
304c302
fix(packaging): name the core line this code actually imports
vistart Nov 7, 2026
ad3d488
refactor(cli): decide the NAME rule where a table can be asserted
vistart Nov 7, 2026
ea90ce7
ci: install the core branch before the requirements that would resolv…
vistart Nov 8, 2026
8bc4022
docs: state what PostgreSQL answers, including what pg_stats cannot give
vistart Nov 8, 2026
0322fbb
docs: state what PostgreSQL answers, including what pg_stats cannot give
vistart Nov 8, 2026
bce17e4
ci: pin core to release/v1.0.0.dev30
vistart Nov 8, 2026
3516612
chore: add changelog fragments for PR #64
vistart Nov 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,16 @@ jobs:
with:
python-version: "3.15"

- name: Install activerecord and testsuite
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt

- name: Install activerecord and testsuite
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@fix/column-constraint-gates"

- name: Create postgres scenario config
run: |
cat > postgres_scenarios.yaml << EOF
Expand Down Expand Up @@ -276,16 +276,16 @@ jobs:
python-version: ${{ matrix.python-version }}
freethreaded: ${{ matrix.freethreaded }}

- name: Install activerecord and testsuite
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt

- name: Install activerecord and testsuite
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@fix/column-constraint-gates"

- name: Create postgres scenario config
run: |
cat > postgres_scenarios.yaml << EOF
Expand Down Expand Up @@ -383,6 +383,11 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install activerecord and testsuite
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

- name: Install dependencies
run: |
if [ "${{ matrix.python-version }}" == "3.8" ]; then
Expand All @@ -393,11 +398,6 @@ jobs:
pip install -r requirements-dev.txt
fi

- name: Install activerecord and testsuite
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@fix/column-constraint-gates"

- name: Create postgres scenario config
run: |
cat > postgres_scenarios.yaml << EOF
Expand Down Expand Up @@ -486,16 +486,16 @@ jobs:
with:
python-version: "3.14"

- name: Install activerecord and testsuite
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17"

- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt

- name: Install activerecord and testsuite
run: |
pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30"
pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@fix/column-constraint-gates"

- name: Create postgres scenario config
run: |
cat > postgres_scenarios.yaml << EOF
Expand Down
24 changes: 24 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,30 @@ This project is under active development. Key features implemented:

This project adheres to the same version control, branching, commit message, and changelog management standards as the main `python-activerecord` project.

## Async Backend and the Windows Event Loop

psycopg's async mode waits on the libpq socket with `loop.add_reader` /
`loop.add_writer`, which on Windows the platform default event loop
(`ProactorEventLoop`, since 3.8) does not implement. Therefore:

- The sync path is unaffected everywhere.
- `AsyncPostgresBackend` requires a selector-based event loop on Windows
(`SelectorEventLoop(SelectSelector())`). psycopg 3.3+ detects the
mismatch at connect time and raises with the fix named; older versions
surface asyncio's raw `NotImplementedError`.
- To run async code on Windows, use the helper this backend ships:
`run_coroutine(coro)` from
`rhosocial.activerecord.backend.impl.postgres.async_support` -- it
constructs the required loop and gives it `asyncio.run`-grade
lifecycle (cancel on `KeyboardInterrupt`, shutdown of async generators,
close, detach). It may only be called when no loop is running.
- The CLI's `--async` modes (`introspect`, `query`, `status`) already use
it, so they work on Windows out of the box.
- Do NOT "fix" this by switching the global event loop policy:
`WindowsSelectorEventLoopPolicy` is deprecated for removal in Python
3.16, and a selector loop on Windows cannot serve asyncio subprocess or
pipe I/O, which would break other parts of the process.

## Search Scope

- Use `rg` for repository searches; never use `grep`.
Expand Down
1 change: 1 addition & 0 deletions changelog.d/64.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Own the status families core moved out -- `WALInfo`, `ReplicationInfo`, `ArchiveInfo` and `SecurityInfo` -- beside `PostgreSQLServerOverview`, keeping `get_overview()`'s signature through a covariant return. Render `pg_relation_size` and `pg_indexes_size` as expression nodes bound to the listing row's oid so the total rides the table listing; a row count prefers `reltuples`, falls back to `n_live_tup` and normalizes `-1` to `None`; `table-storage` becomes a CLI type because the capability had to be askable. Answer the operational families from `pg_stat_user_indexes`, `pg_stat_user_tables`, `pg_stat_activity` and `pg_depend` (`pg_stat_statements` is deliberately not read), and profile columns and samples from `pg_stats`, labelled `ESTIMATE` or `UNKNOWN` by vintage, with arrays through `to_jsonb` and exact join coverage. DDL extraction is declared but answers without text: `get_ddl_statement` returns `None`, the CLI exits 1 with "no DDL available", and `supports_ddl_extraction_native()` is `False`. Ten CLI types derive from `_TYPE_CAPABILITIES`, `supports_extensions` delegates so one capability is one answer, and `async_support.py` supplies `run_coroutine()` for the CLI's three `--async` modes on Windows.
1 change: 1 addition & 0 deletions changelog.d/64.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Rename `SyncPostgreSQLIntrospector` to `PostgreSQLIntrospector` and `SyncPostgreSQLStatusIntrospector` to `PostgreSQLStatusIntrospector`. Backend developers subclassing the old names must attach to core's `AbstractIntrospector` and `AbstractStatusIntrospector` through `IntrospectorExecutor`.
Loading
Loading