From d6db0a3a36988ddd3c012fdb2e7226bb8119fdd3 Mon Sep 17 00:00:00 2001 From: zhao vistart Date: Wed, 11 Nov 2026 21:41:13 +0800 Subject: [PATCH 1/3] feat!: declare models by overriding accessors, not by dunder Breaking, following rhosocial-activerecord: model fixtures and examples now override table_name(), primary_key(), pk_auto_generated(), read_only() and the locator methods instead of assigning __table_name__ and friends. The framework stopped reading those dunders, so a model still declaring them would fail with NotImplementedError at the first read. Produced by the core repository's declaration sweep (scripts/ d5_migrate_declarations.py), so every repository in the family carries the same shape. No new lint findings: the totals drop where the removed assignments took their imports with them. CI for this branch installs the family from the matching feature/declaration-surface ref, so a run exercises one revision across core, testsuite and the backend under test rather than a mixture of two. --- .github/workflows/test.yml | 36 +++++++-------- tests/providers/basic_connection.py | 11 +++-- tests/providers/query_connection.py | 11 +++-- .../feature/backend/test_async_concurrency.py | 41 ++++++++++++----- .../feature/backend/test_ddl_source_mixin.py | 44 ++++++++++++++----- 5 files changed, 99 insertions(+), 44 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5204def7..8814be1f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,8 +54,8 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/error-taxonomy" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/error-taxonomy" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies run: | @@ -144,8 +144,8 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/error-taxonomy" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/error-taxonomy" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies run: | @@ -234,8 +234,8 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/error-taxonomy" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/error-taxonomy" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies run: | @@ -324,8 +324,8 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/error-taxonomy" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/error-taxonomy" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies run: | @@ -414,8 +414,8 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/error-taxonomy" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/error-taxonomy" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies run: | @@ -504,8 +504,8 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/error-taxonomy" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/error-taxonomy" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies run: | @@ -595,8 +595,8 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/error-taxonomy" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/error-taxonomy" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies run: | @@ -685,8 +685,8 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/error-taxonomy" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/error-taxonomy" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies run: | @@ -784,8 +784,8 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/error-taxonomy" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/error-taxonomy" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies run: | diff --git a/tests/providers/basic_connection.py b/tests/providers/basic_connection.py index 9e17fa05..e2c65f7d 100644 --- a/tests/providers/basic_connection.py +++ b/tests/providers/basic_connection.py @@ -9,7 +9,6 @@ from rhosocial.activerecord.model import ActiveRecord, AsyncActiveRecord from rhosocial.activerecord.backend.impl.sqlserver.backend import SQLServerBackend -from rhosocial.activerecord.backend.impl.sqlserver.config import SQLServerConnectionConfig from rhosocial.activerecord.connection.pool import BackendPool, AsyncBackendPool, PoolConfig from rhosocial.activerecord.backend.options import ExecutionOptions from rhosocial.activerecord.backend.schema import StatementType @@ -20,7 +19,10 @@ class SyncTestUser(ActiveRecord): """Sync test user model for connection pool tests.""" - __table_name__ = "test_users" + @classmethod + def table_name(cls): + return "test_users" + id: Optional[int] = None name: str email: str @@ -28,7 +30,10 @@ class SyncTestUser(ActiveRecord): class AsyncTestUser(AsyncActiveRecord): """Async test user model for connection pool tests.""" - __table_name__ = "test_users" + @classmethod + def table_name(cls): + return "test_users" + id: Optional[int] = None name: str email: str diff --git a/tests/providers/query_connection.py b/tests/providers/query_connection.py index 56e0c4d8..4959243f 100644 --- a/tests/providers/query_connection.py +++ b/tests/providers/query_connection.py @@ -9,7 +9,6 @@ from rhosocial.activerecord.model import ActiveRecord, AsyncActiveRecord from rhosocial.activerecord.backend.impl.sqlserver.backend import SQLServerBackend -from rhosocial.activerecord.backend.impl.sqlserver.config import SQLServerConnectionConfig from rhosocial.activerecord.connection.pool import BackendPool, AsyncBackendPool, PoolConfig from rhosocial.activerecord.backend.options import ExecutionOptions from rhosocial.activerecord.backend.schema import StatementType @@ -20,7 +19,10 @@ class SyncQueryTestUser(ActiveRecord): """Sync test user model for query connection pool tests.""" - __table_name__ = "test_users" + @classmethod + def table_name(cls): + return "test_users" + id: Optional[int] = None name: str email: str @@ -28,7 +30,10 @@ class SyncQueryTestUser(ActiveRecord): class AsyncQueryTestUser(AsyncActiveRecord): """Async test user model for query connection pool tests.""" - __table_name__ = "test_users" + @classmethod + def table_name(cls): + return "test_users" + id: Optional[int] = None name: str email: str diff --git a/tests/rhosocial/activerecord_sqlserver_test/feature/backend/test_async_concurrency.py b/tests/rhosocial/activerecord_sqlserver_test/feature/backend/test_async_concurrency.py index 433df703..ffac6d48 100644 --- a/tests/rhosocial/activerecord_sqlserver_test/feature/backend/test_async_concurrency.py +++ b/tests/rhosocial/activerecord_sqlserver_test/feature/backend/test_async_concurrency.py @@ -41,7 +41,10 @@ class ConcurrentUser(AsyncActiveRecord): """User model for concurrency testing.""" - __table_name__ = "concurrent_users" + @classmethod + def table_name(cls): + return "concurrent_users" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None @@ -53,7 +56,10 @@ class ConcurrentUser(AsyncActiveRecord): class ConcurrentTask(AsyncActiveRecord): """Task model for concurrency testing with status tracking.""" - __table_name__ = "concurrent_tasks" + @classmethod + def table_name(cls): + return "concurrent_tasks" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None @@ -269,7 +275,10 @@ async def isolated_worker_task(task_id: int): # Configure a task-specific model class class WorkerUser(AsyncActiveRecord): - __table_name__ = "concurrent_users" + @classmethod + def table_name(cls): + return "concurrent_users" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None username: str @@ -329,7 +338,7 @@ class WorkerUser(AsyncActiveRecord): await backend.execute("DROP TABLE IF EXISTS concurrent_users") await backend.disconnect() - print(f"\nSUCCESS: All 10 concurrent tasks with independent backends completed") + print("\nSUCCESS: All 10 concurrent tasks with independent backends completed") # --- Test 4: Transaction Isolation with Independent Backends --- @@ -360,7 +369,10 @@ async def transaction_task(task_id: int, should_commit: bool): await backend.connect() class TxUser(AsyncActiveRecord): - __table_name__ = "concurrent_users" + @classmethod + def table_name(cls): + return "concurrent_users" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None username: str @@ -436,7 +448,7 @@ class TxUser(AsyncActiveRecord): await backend.execute("DROP TABLE IF EXISTS concurrent_users") await backend.disconnect() - print(f"\nConfirmed: Transaction isolation works with independent backends") + print("\nConfirmed: Transaction isolation works with independent backends") print(f" Committed: {results['committed']}") print(f" Rolled back: {results['rolled_back']}") @@ -467,7 +479,10 @@ async def test_sequential_vs_concurrent_comparison(mysql_config): await shared_backend.connect() class SharedUser(AsyncActiveRecord): - __table_name__ = "concurrent_users" + @classmethod + def table_name(cls): + return "concurrent_users" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None username: str @@ -496,7 +511,10 @@ async def concurrent_insert(task_id: int): await backend.connect() try: class ConcurrentUser(AsyncActiveRecord): - __table_name__ = "concurrent_users" + @classmethod + def table_name(cls): + return "concurrent_users" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None username: str @@ -532,7 +550,7 @@ class ConcurrentUser(AsyncActiveRecord): assert len(users) == 20 - print(f"\nPerformance Comparison:") + print("\nPerformance Comparison:") print(f" Sequential (shared backend): {sequential_time:.3f}s") print(f" Concurrent (independent backends): {concurrent_time:.3f}s") @@ -579,7 +597,10 @@ async def safe_concurrent_task(task_id: int): await backend.connect() try: class SafeUser(AsyncActiveRecord): - __table_name__ = "concurrent_users" + @classmethod + def table_name(cls): + return "concurrent_users" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None username: str diff --git a/tests/rhosocial/activerecord_sqlserver_test/feature/backend/test_ddl_source_mixin.py b/tests/rhosocial/activerecord_sqlserver_test/feature/backend/test_ddl_source_mixin.py index 50cf8f4b..aaf4c303 100644 --- a/tests/rhosocial/activerecord_sqlserver_test/feature/backend/test_ddl_source_mixin.py +++ b/tests/rhosocial/activerecord_sqlserver_test/feature/backend/test_ddl_source_mixin.py @@ -214,8 +214,13 @@ def table_tablespace(cls): class SyncModel(DeclarationMixin, ActiveRecord): - __table_name__ = "ddl_source_sync" - __primary_key__ = "id" + @classmethod + def table_name(cls): + return "ddl_source_sync" + + @classmethod + def primary_key(cls): + return "id" pk_field: PK_TYPE value_field: VALUE_TYPE = DEFAULT_VALUE @@ -224,8 +229,13 @@ class SyncModel(DeclarationMixin, ActiveRecord): class AsyncModel(DeclarationMixin, AsyncActiveRecord): - __table_name__ = "ddl_source_async" - __primary_key__ = "id" + @classmethod + def table_name(cls): + return "ddl_source_async" + + @classmethod + def primary_key(cls): + return "id" pk_field: PK_TYPE value_field: VALUE_TYPE = DEFAULT_VALUE @@ -234,8 +244,13 @@ class AsyncModel(DeclarationMixin, AsyncActiveRecord): class CompositeModel(DeclarationMixin, ActiveRecord): - __table_name__ = "ddl_source_composite" - __primary_key__ = ("left_col", "right_col") + @classmethod + def table_name(cls): + return "ddl_source_composite" + + @classmethod + def primary_key(cls): + return ("left_col", "right_col") left_field: Annotated[int, UseColumn("left_col")] right_field: Annotated[int, UseColumn("right_col")] @@ -243,8 +258,13 @@ class CompositeModel(DeclarationMixin, ActiveRecord): class AsyncCompositeModel(DeclarationMixin, AsyncActiveRecord): - __table_name__ = "ddl_source_async_composite" - __primary_key__ = ("left_col", "right_col") + @classmethod + def table_name(cls): + return "ddl_source_async_composite" + + @classmethod + def primary_key(cls): + return ("left_col", "right_col") left_field: Annotated[int, UseColumn("left_col")] right_field: Annotated[int, UseColumn("right_col")] @@ -252,14 +272,18 @@ class AsyncCompositeModel(DeclarationMixin, AsyncActiveRecord): class PlainModel(ActiveRecord): - __table_name__ = "ddl_source_plain" + @classmethod + def table_name(cls): + return "ddl_source_plain" id: int optional: Optional[str] = None class AsyncPlainModel(AsyncActiveRecord): - __table_name__ = "ddl_source_async_plain" + @classmethod + def table_name(cls): + return "ddl_source_async_plain" id: int optional: Optional[str] = None From 2a6306edf250ec924cabd0bdad1d7ee6fb34e1e8 Mon Sep 17 00:00:00 2001 From: zhao vistart Date: Thu, 12 Nov 2026 14:29:53 +0800 Subject: [PATCH 2/3] ci: track the released core instead of the feature branch Workflow 'test.yml' installs this backend's dependencies from the other repositories in the family. Core's PR #140 is merged into release/v1.0.0.dev30, so the core ref now names that branch: a run of this repository tests the released core rather than a feature branch that no longer exists. The testsuite ref is unchanged and still names feature/declaration-surface: its migration has no merge yet, and pointing it at release/v1.0.0.dev17 would install fixtures that still declare the removed dunders. --- .check_expression_baseline.json | 213 ++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 18 +-- 2 files changed, 222 insertions(+), 9 deletions(-) create mode 100644 .check_expression_baseline.json diff --git a/.check_expression_baseline.json b/.check_expression_baseline.json new file mode 100644 index 00000000..d450d5ae --- /dev/null +++ b/.check_expression_baseline.json @@ -0,0 +1,213 @@ +{ + "entries": { + "0278ac9b2d99f243": 2, + "1182e6a5168fad4d": 2, + "15d8c1ad5f05215a": 3, + "2207e5f45a158db2": 1, + "25138787f4f3c292": 1, + "26f48745c86bcb6c": 3, + "3a76dbbb69039561": 1, + "481c9c33d29a2930": 1, + "4a00de96e7c111a8": 1, + "687f736f87568fa7": 1, + "6881e297193f53fb": 2, + "9cede0bc2031de72": 1, + "a316d4185f6c5372": 1, + "adbe0ad37f3fd6c9": 1, + "aebaaac3f9ed8118": 1, + "cc38ae350540075e": 1, + "d55e960506f63189": 1, + "df7098df4eaf8eba": 1, + "e6738eb70915f158": 1, + "e775979689c0aa90": 2, + "ee65f2c95cb20172": 2, + "f0868da2f55f9884": 1, + "f27dd66925c1fb96": 1, + "fabe6126b76a1058": 1, + "fad924c61e4a2756": 1, + "fc1ce8dd882c87df": 2 + }, + "findings": [ + { + "found": "sparse: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/expression/column.py", + "rule": "ED-10.2" + }, + { + "found": "rowguidcol: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/expression/column.py", + "rule": "ED-10.2" + }, + { + "found": "sparse: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/expression/column.py", + "rule": "ED-10.2" + }, + { + "found": "rowguidcol: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/expression/column.py", + "rule": "ED-10.2" + }, + { + "found": "slots", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/expression/objects.py", + "rule": "ED-KWARGS" + }, + { + "found": "getattr(expr, \"cascade\", False)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"restrict\", False)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'definition_kind', type(expr).__name__)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'definition_kind', type(expr).__name__)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'action_kind', type(expr).__name__)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr.options, \"schemabinding\", False)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/ddl_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(clause, \"with_ties\", False)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/dql.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"partition_scheme\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/partition.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"select_into_table\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/protocol_support.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"or_alter\", False)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"schema\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"parameters\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"body\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"returns\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"or_alter\", False)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"schema\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"parameters\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"body\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"kind\", \"PROCEDURE\")", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"if_exists\", False)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"schema\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/routine.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"table_name\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"table\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"timing\", \"AFTER\")", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"events\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"body\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"or_alter\", False)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"schema\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"schema\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"if_exists\", False)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"schema\", None)", + "path": "src/rhosocial/activerecord/backend/impl/sqlserver/mixins/trigger.py", + "rule": "ED-11.2" + } + ], + "format": 1 +} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8814be1f..120d9947 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,7 +54,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies @@ -144,7 +144,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies @@ -234,7 +234,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies @@ -324,7 +324,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies @@ -414,7 +414,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies @@ -504,7 +504,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies @@ -595,7 +595,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies @@ -685,7 +685,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies @@ -784,7 +784,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | - pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR - name: Install dependencies From 8410f874b18d37872761dddd42a26688c3a8f432 Mon Sep 17 00:00:00 2001 From: zhao vistart Date: Thu, 12 Nov 2026 15:20:06 +0800 Subject: [PATCH 3/3] ci: track the merged testsuite instead of the feature branch The testsuite's PR #32 is merged into release/v1.0.0.dev17, so the testsuite ref now names that branch. Every cross-repository install in a run therefore resolves to a released artifact: core from release/v1.0.0.dev30, the testsuite from release/v1.0.0.dev17, and this repository from its own feature branch. --- .github/workflows/test.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 120d9947..d2b2af66 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -55,7 +55,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17" # NOSONAR - name: Install dependencies run: | @@ -145,7 +145,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17" # NOSONAR - name: Install dependencies run: | @@ -235,7 +235,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17" # NOSONAR - name: Install dependencies run: | @@ -325,7 +325,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17" # NOSONAR - name: Install dependencies run: | @@ -415,7 +415,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17" # NOSONAR - name: Install dependencies run: | @@ -505,7 +505,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17" # NOSONAR - name: Install dependencies run: | @@ -596,7 +596,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17" # NOSONAR - name: Install dependencies run: | @@ -686,7 +686,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17" # NOSONAR - name: Install dependencies run: | @@ -785,7 +785,7 @@ jobs: - name: Install activerecord and testsuite from PyPI run: | pip install "rhosocial-activerecord @ git+https://github.com/rhosocial/python-activerecord.git@release/v1.0.0.dev30" # NOSONAR - pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@feature/declaration-surface" # NOSONAR + pip install "rhosocial-activerecord-testsuite @ git+https://github.com/rhosocial/python-activerecord-testsuite.git@release/v1.0.0.dev17" # NOSONAR - name: Install dependencies run: |