Repository navigation
test: setting an attribute on pgc_conn or its cursors raises instead of doing nothing (#1420) - #1432
Merged
Merged
Conversation
…of doing nothing (#1420) The watched connection and cursor forward reads through __getattr__ but had no __setattr__, so `pgc_conn.autocommit = False` made an attribute on the wrapper and left the real connection in autocommit: each statement committed and rollback() undid nothing, with no error. Both proxies now keep their own underscore state and refuse any other assignment with an AttributeError that names the attribute and says to use BEGIN and ROLLBACK or a connection of one's own. Red first: the two stub arms in test_writes_wrote_rows.py and the wiring arm in test_connection.py each got 'set' where they wanted 'refused'. No test in the corpus assigns a public attribute on either proxy (an AST scan of all 114 files), and the full corpus passes on PG17: 435 guard tests and 567 cluster tests, the latter serially as CI runs them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OffgridwithJD
approved these changes
Oct 15, 2026
OffgridwithJD
left a comment
Collaborator
There was a problem hiding this comment.
Approved at 28f2e41. Raise rather than forward is the right call: a test that wants a transaction should say so in SQL.
- The fix: both proxies get a
__setattr__. Names starting with_set the proxy's own state, which covers everything their constructors set; any other name raisesAttributeErrorwith a message that says what to do instead. - Red, one proxy at a time (PG18,
__pycache__cleared before each arm, the runtime checked for which class still had__setattr__):- Without the connection's: 2 failed, 1 passed. Both
test_a_setting_on_the_watched_connection_is_refused_not_droppedand the wiring arm on the realpgc_connfail withsetting autocommit on the watched connection is refused, not kept on the wrapper: got 'set' want 'refused'. The cursor arm stays green. - Without the cursor's: only the cursor arm fails,
setting an attribute on a watched cursor is refused, not kept on the wrapper: got 'set' want 'refused'. - Restored: 3 passed.
- Without the connection's: 2 failed, 1 passed. Both
- Nothing else depends on the old behaviour: a grep for assignments to the psycopg connection and cursor attributes (
autocommit,row_factory,isolation_level,read_only,arraysize,prepare_thresholdand so on) acrosstest/pytestfinds only the new tests and the fake_Conn's own__init__. That agrees with your AST scan. - Counts: collection gives guard 435 and cluster 567, matching
expected_tests.txt. - CI: 11 of 15 checks green at the time of review, 4 still running.
🤖 Generated with Claude Code
87 tasks done
This was referenced Oct 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1420. A harness-only change; no product code or suite changes.
The defect
pgc_connand the cursors it hands out are proxies (_WatchedConnection,_WatchedCursorinpgc_vacuity.py). They forward reads through__getattr__but had no__setattr__. Sopgc_conn.autocommit = Falsecreated an attribute on the proxy and left the real connection in autocommit. Every statement committed,rollback()undid nothing, and nothing said so. I hit this writing #1419.The fix
Both proxies get a
__setattr__. Names starting with_are the proxy's own state (_conn,_cur,_nodeid,_pgc_write) and are set on the proxy. Any other name raisesAttributeError. The message names the attribute and says to useBEGIN/ROLLBACK, or a connection of the test's own.Raise, not forward: #1420 left this choice open. I took "raise" because a test that wants a transaction should say so in SQL, as the existing twins do. Forwarding is a one-line change if you prefer it, @OffgridwithJD.
Evidence
Red first, against the unchanged proxies:
test_a_setting_on_the_watched_connection_is_refused_not_dropped: got'set', want'refused'.test_a_setting_on_a_watched_cursor_is_refused_not_dropped: got'set', want'refused'.test_setting_autocommit_on_the_connection_the_tests_use_is_refused(the wiring arm, on the realpgc_conn): got'set', want'refused'.Nothing in the corpus depends on the old behaviour. An AST scan of all 114 files under
test/pytestfinds no assignment of a public attribute on either proxy. A grep couldn't answer this, because it matched SQL text inside strings.Green, on PG17:
--pgc-expect-tests 435.--pgc-expect-tests 567, rc=0. It runs serially, as CI does. Under-n 4the same tests pass, but the run exits 67: each worker checks the decline registry (expected_unrunnable.txt) against only the tests it ran, andtest_format_downgradedeclines under xdist. That happens with or without this change.Counts and docs:
guard_testsgoes 433 -> 435 andcluster_tests566 -> 567, both by collection.🤖 Generated with Claude Code