From 9f6060e33219ee6da751dd0001343786a278f5a2 Mon Sep 17 00:00:00 2001 From: zhao vistart Date: Wed, 11 Nov 2026 21:41:37 +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 | 16 +++---- tests/providers/basic_connection.py | 12 +++-- tests/providers/query_connection.py | 10 ++++- .../feature/backend/test_async_dml_deep.py | 10 ++++- .../feature/backend/test_ddl_source_mixin.py | 44 ++++++++++++++----- .../feature/backend/test_introspector_deep.py | 14 ++++-- .../backend/test_schema_qualified_dml.py | 31 ++++++++++--- 7 files changed, 100 insertions(+), 37 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f36d7eb7..dbe066ac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,8 +47,8 @@ jobs: - name: Install activerecord and testsuite from git 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: | @@ -175,8 +175,8 @@ jobs: - name: Install activerecord and testsuite from git 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: | @@ -303,8 +303,8 @@ jobs: - name: Install activerecord and testsuite from git 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: | @@ -439,8 +439,8 @@ jobs: - name: Install activerecord and testsuite from git 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 c387359c..2efb1d1a 100644 --- a/tests/providers/basic_connection.py +++ b/tests/providers/basic_connection.py @@ -12,8 +12,6 @@ from rhosocial.activerecord.backend.impl.oracle.backend import OracleBackend from rhosocial.activerecord.backend.impl.oracle.backend.async_backend import AsyncOracleBackend from rhosocial.activerecord.connection.pool import BackendPool, AsyncBackendPool, PoolConfig -from rhosocial.activerecord.backend.options import ExecutionOptions -from rhosocial.activerecord.backend.schema import StatementType from rhosocial.activerecord.testsuite.feature.basic.connection.interfaces import IBasicConnectionProvider from .scenarios import get_scenario, get_enabled_scenarios @@ -38,7 +36,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 @@ -47,7 +48,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 54089814..92aa7048 100644 --- a/tests/providers/query_connection.py +++ b/tests/providers/query_connection.py @@ -35,7 +35,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 @@ -44,7 +47,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_oracle_test/feature/backend/test_async_dml_deep.py b/tests/rhosocial/activerecord_oracle_test/feature/backend/test_async_dml_deep.py index 49b0a4ba..7875e49a 100644 --- a/tests/rhosocial/activerecord_oracle_test/feature/backend/test_async_dml_deep.py +++ b/tests/rhosocial/activerecord_oracle_test/feature/backend/test_async_dml_deep.py @@ -26,8 +26,14 @@ class AsyncCustomer(AsyncActiveRecord): - __table_name__ = "customers" - __schema_name__ = "ar_crm" + @classmethod + def table_name(cls): + return "customers" + + @classmethod + def schema_name(cls): + return "ar_crm" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None diff --git a/tests/rhosocial/activerecord_oracle_test/feature/backend/test_ddl_source_mixin.py b/tests/rhosocial/activerecord_oracle_test/feature/backend/test_ddl_source_mixin.py index 0c91a7af..75693400 100644 --- a/tests/rhosocial/activerecord_oracle_test/feature/backend/test_ddl_source_mixin.py +++ b/tests/rhosocial/activerecord_oracle_test/feature/backend/test_ddl_source_mixin.py @@ -206,8 +206,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 @@ -216,8 +221,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 @@ -226,8 +236,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")] @@ -235,8 +250,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")] @@ -244,14 +264,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 diff --git a/tests/rhosocial/activerecord_oracle_test/feature/backend/test_introspector_deep.py b/tests/rhosocial/activerecord_oracle_test/feature/backend/test_introspector_deep.py index 4ece24bd..fde686fd 100644 --- a/tests/rhosocial/activerecord_oracle_test/feature/backend/test_introspector_deep.py +++ b/tests/rhosocial/activerecord_oracle_test/feature/backend/test_introspector_deep.py @@ -46,8 +46,14 @@ class DeepCustomer(ActiveRecord): - __table_name__ = "customers" - __schema_name__ = "ar_crm" + @classmethod + def table_name(cls): + return "customers" + + @classmethod + def schema_name(cls): + return "ar_crm" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None @@ -1009,8 +1015,8 @@ def test_the_26ai_scenario_is_a_23_line_server(self): ) backend.introspect_and_adapt() assert full is not None, ( - f"oracle_26ai reports no VERSION_FULL, so the release-update " - f"number that tells 23ai from 26ai cannot be demonstrated" + "oracle_26ai reports no VERSION_FULL, so the release-update " + "number that tells 23ai from 26ai cannot be demonstrated" ) # Both true at once, and neither read from the other: the product # name says 26 while the version says 23. diff --git a/tests/rhosocial/activerecord_oracle_test/feature/backend/test_schema_qualified_dml.py b/tests/rhosocial/activerecord_oracle_test/feature/backend/test_schema_qualified_dml.py index 3ead9781..2659fde6 100644 --- a/tests/rhosocial/activerecord_oracle_test/feature/backend/test_schema_qualified_dml.py +++ b/tests/rhosocial/activerecord_oracle_test/feature/backend/test_schema_qualified_dml.py @@ -13,7 +13,6 @@ from rhosocial.activerecord.base.field_proxy import FieldProxy from rhosocial.activerecord.backend.options import ExecutionOptions from rhosocial.activerecord.backend.schema import StatementType -from typing import Optional from rhosocial.activerecord.model import ActiveRecord from rhosocial.activerecord.backend.errors import DatabaseError @@ -28,8 +27,14 @@ class SchemaCustomer(ActiveRecord): - __table_name__ = "customers" - __schema_name__ = "ar_crm" + @classmethod + def table_name(cls): + return "customers" + + @classmethod + def schema_name(cls): + return "ar_crm" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None @@ -37,8 +42,14 @@ class SchemaCustomer(ActiveRecord): class SchemaOrder(ActiveRecord): - __table_name__ = "orders" - __schema_name__ = "ar_shop" + @classmethod + def table_name(cls): + return "orders" + + @classmethod + def schema_name(cls): + return "ar_shop" + c: ClassVar[FieldProxy] = FieldProxy() id: Optional[int] = None @@ -161,8 +172,14 @@ async def test_async_insert_is_scoped(provisioned): from rhosocial.activerecord.model import AsyncActiveRecord class AsyncSchemaCustomer(AsyncActiveRecord): - __table_name__ = "customers" - __schema_name__ = "ar_crm" + @classmethod + def table_name(cls): + return "customers" + + @classmethod + def schema_name(cls): + return "ar_crm" + c: ClassVar[FieldProxy] = FieldProxy() id: _Optional[int] = None From 8ef4f645eccea1ac7aa8599c5378f70bb12f5499 Mon Sep 17 00:00:00 2001 From: zhao vistart Date: Thu, 12 Nov 2026 14:29:59 +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 | 618 ++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 8 +- 2 files changed, 622 insertions(+), 4 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..fe9d8bc7 --- /dev/null +++ b/.check_expression_baseline.json @@ -0,0 +1,618 @@ +{ + "entries": { + "0ca045747bf0d070": 1, + "0d15642818e247d6": 1, + "0d2fde28039bddab": 4, + "10dd081c19b9ad50": 1, + "110bece17006543d": 1, + "136c12ef6a762823": 1, + "171ec88723cbfb17": 2, + "1aa5e7be7eda00fb": 1, + "2599c2d7a5e6a437": 1, + "30f104c03fdc5af1": 3, + "38f003578c1ce4e0": 1, + "3b22f5789f4d5a8c": 1, + "3ecf0364411b56e5": 1, + "41619161a5b02dfc": 1, + "42aa838a058a3304": 2, + "460b0e45cc5589b0": 1, + "46ae24f0ee9e5724": 1, + "47d07919ea64851e": 1, + "4a69402b3ae2aceb": 1, + "4c9de7db636ea2cf": 1, + "4f4ae7d9445321ee": 1, + "51047621986ac2a1": 1, + "53dde7be4512717e": 3, + "553144c02041e54f": 1, + "554aadc1e8ebc637": 1, + "562e58512a4186bc": 2, + "5928312313cab20f": 1, + "5dc4a48b6cca6ad3": 1, + "5f2c6969efc172cf": 2, + "61a6c9897c85466e": 1, + "62117bc2979b65f9": 1, + "66984a3917f127f2": 1, + "6aae0e726d5aa404": 2, + "6c21898825dba34b": 1, + "736cd45766598cb0": 2, + "73c51d301fa1a572": 1, + "7467d4f03ac56b7f": 1, + "7847f487f20f17c0": 1, + "81738bddbf039488": 3, + "891f1ab7d153770b": 1, + "8c5a6fc3dfb2a602": 3, + "8e1eb04bf40ece26": 1, + "9224152bf2f52544": 1, + "96069c6dbc748b9a": 1, + "971fcdbfd85b0898": 1, + "988953ec10a4a018": 1, + "9ff31c7c9315b9e3": 1, + "a01e086e1d838394": 1, + "a1645a256f65c3a2": 1, + "a43968cf9670bbc6": 3, + "a459ebdeb70cf5d3": 1, + "a6a4477fff0d9725": 1, + "a92ff37d36c7a1e1": 1, + "acbd9d8f93bd81e1": 1, + "ad429e67038e1517": 1, + "ae7ebdbc8e0aea2f": 1, + "b2fc245e62979f30": 1, + "b8d365752d668d04": 1, + "bc58ab3116be6c28": 1, + "bcc7ffb4387e6b9b": 1, + "bce7adfd9ae4c224": 1, + "bd355b4169fbc56b": 1, + "bdd9cf88b2bab7a7": 1, + "c0d394e63a112f83": 1, + "c731e548772596bf": 1, + "ca5e1c0253dd25d6": 1, + "d3a0c262fd804f7c": 1, + "dc1d39b02f7cf638": 1, + "ddf5f7808c9315ce": 1, + "ded0bc21d5e88e85": 1, + "e1e8e9779ce70297": 2, + "e2b46b86e3815627": 1, + "e7aae44edc900f1b": 1, + "e837d0b25c178e49": 1, + "ea41b5d4c14aeddc": 2, + "ec9a920e3859418a": 1, + "edda16146ce999a2": 1, + "ee91f1ec1b1fc22c": 4, + "eeecbbfed5839023": 1, + "fb176c0bc4f1de1e": 2, + "fe27078242ac7a9e": 1 + }, + "findings": [ + { + "found": "invisible: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/column.py", + "rule": "ED-10.2" + }, + { + "found": "invisible: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/column.py", + "rule": "ED-10.2" + }, + { + "found": "final: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "instantiable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "persistable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_final: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_instantiable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_persistable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "final: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "instantiable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "persistable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_final: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_instantiable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_persistable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "persistable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_persistable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "persistable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_persistable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "final: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "is_final: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_final: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "instantiable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "is_instantiable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "not_instantiable: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/ddl/type.py", + "rule": "ED-10.2" + }, + { + "found": "atomic_refresh: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/materialized_view.py", + "rule": "ED-10.2" + }, + { + "found": "out_of_place: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/materialized_view.py", + "rule": "ED-10.2" + }, + { + "found": "nested: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/materialized_view.py", + "rule": "ED-10.2" + }, + { + "found": "refresh_after_errors: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/materialized_view.py", + "rule": "ED-10.2" + }, + { + "found": "push_deferred_rpc: Optional[bool]", + "path": "src/rhosocial/activerecord/backend/impl/oracle/expression/materialized_view.py", + "rule": "ED-10.2" + }, + { + "found": "getattr(action, \"if_not_exists\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/column.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(action, \"if_exists\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/column.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(action, \"cascade\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/column.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"column\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/comment.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr.object_type, \"value\", expr.object_type)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/comment.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"table_options\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(table_options, \"comment\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"table_options\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(to, \"tablespace\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(col_def, \"comment\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(t_const, \"match_type\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(t_const, \"deferrable\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(t_const, \"not_deferrable\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(t_const, \"initially_deferred\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(t_const, \"initially_immediate\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(t_const, \"enforced\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(t_const, \"not_enforced\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"purge\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl_table_op.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"resolved_persistable\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'definition_kind', type(expr).__name__)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr.definition, \"force\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr.definition, \"editionable\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr.definition, \"noneditionable\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'action_kind', type(expr).__name__)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'action_kind', type(expr).__name__)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"force\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/ddl_type.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(conflict_clause, \"action\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/dml.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"from_\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/expression.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(from_, \"alias\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/expression.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(from_, \"name\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/expression.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"func_name\", \"\")", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/functions.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"is_distinct\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/functions.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"_oracle_within_group\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/functions.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"_oracle_on_overflow\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/functions.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"is_distinct\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/functions.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"_oracle_within_group\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/functions.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"_oracle_returning_type\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/functions.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"_oracle_json_table_columns\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/functions.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"if_not_exists\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"build_mode\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"with_data\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"no_data\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"refresh_method\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"refresh_trigger\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"enable_query_rewrite\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"disable_query_rewrite\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"if_exists\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"preserve_table\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"cascade\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"restrict\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"view\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'view', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"concurrent\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"with_data\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"no_data\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"method\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/materialized_view.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(clause, \"with_ties\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/pagination.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(clause, \"with_ties\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/pagination.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"if_not_exists\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/sequence.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"owned_by\", None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/sequence.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, \"if_exists\", False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/sequence.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(trigger_expr, 'timing', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(trigger_expr, 'events', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(trigger_expr, 'update_columns', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(trigger_expr, 'level', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(trigger_expr, 'referencing', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(trigger_expr, 'condition', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(trigger_expr, 'body', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(trigger_expr, 'function', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(trigger_expr, 'function', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(drop_expr, 'if_exists', False)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/trigger.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(data_type, 'precision', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/types.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(data_type, 'precision', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/types.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(data_type, 'precision', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/types.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'vector1', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/vector.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'vector2', None)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/vector.py", + "rule": "ED-11.2" + }, + { + "found": "getattr(expr, 'metric', metric)", + "path": "src/rhosocial/activerecord/backend/impl/oracle/mixins/vector.py", + "rule": "ED-11.2" + } + ], + "format": 1 +} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index dbe066ac..644dc3a6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,7 +47,7 @@ jobs: - name: Install activerecord and testsuite from git 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 @@ -175,7 +175,7 @@ jobs: - name: Install activerecord and testsuite from git 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 @@ -303,7 +303,7 @@ jobs: - name: Install activerecord and testsuite from git 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 @@ -439,7 +439,7 @@ jobs: - name: Install activerecord and testsuite from git 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 c7ccaf392da420b9f44696ad54957e2b3e522a8a Mon Sep 17 00:00:00 2001 From: zhao vistart Date: Thu, 12 Nov 2026 15:20:13 +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 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 644dc3a6..1a0a093a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,7 +48,7 @@ jobs: - name: Install activerecord and testsuite from git 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: | @@ -176,7 +176,7 @@ jobs: - name: Install activerecord and testsuite from git 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: | @@ -304,7 +304,7 @@ jobs: - name: Install activerecord and testsuite from git 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: | @@ -440,7 +440,7 @@ jobs: - name: Install activerecord and testsuite from git 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: |