Skip to content

Conversation

@vistart
Copy link
Contributor

@vistart vistart commented Nov 29, 2025

Description

This 1.0.0.dev13 development release for python-activerecord brings significant enhancements across core functionality, backend integration, and documentation.

Release/Hotfix Details

  • Target Version: v1.0.0.dev13
  • Type: Development Release
  • Key Changes:
    • New Features:
      • Introduced CurrentExpression for SQL current date/time functions.
      • Developed an interactive SQLite CLI tool with support for stdin/file input and multiple output formats.
      • Implemented robust backend-driven type adaptation for ActiveRecord.
    • Bug Fixes:
      • Resolved issues with dialect-specific placeholders in delete methods.
      • Removed type adapter caching to prevent cross-version test failures.
      • Normalized quoted column names during result processing.
    • Refactors & Improvements:
      • Improved CTE (Common Table Expression) handling and post-insert primary key retrieval.
      • Centralized and integrated parameter type adaptation within query builders.
      • Overhauled the type conversion system to utilize Type Adapters.
      • Fine-tuned backend type system and cleaned up unused code.
    • Documentation Enhancements:
      • Extensively rewrote model_testing.md.
      • Updated documentation for async support, Pydantic integration, and free-threading Python versions.
      • Enhanced GitHub pull request templates with granular breaking change options.
    • Breaking Changes (if applicable, with migration path)
    • Security Fixes (if applicable, with CVE)

Related Issues/PRs

N/A for development release

Breaking Change

  • Yes, for end-users (backward-incompatible API changes)
  • Yes, for backend developers (internal architectural changes that may affect custom implementations)
  • No breaking changes

Impact on End-Users:
No backward-incompatible changes are expected for typical end-user applications.

Impact on Backend Developers (Custom Implementations):
No backward-incompatible changes are expected for backend developers using custom implementations.

Testing

  • All CI checks passed on the source branch (e.g., release/vX.Y.Z or hotfix/ar-XXX).
  • Specific tests for this hotfix have been run and passed.

Test Plan:
Ran full test suite on release/v1.0.0.dev13 branch.

Checklist

  • My changes follow the project's version control guidelines (especially for release and hotfix procedures).
  • I have updated the CHANGELOG.md using towncrier build (for releases).
  • All necessary documentation (e.g., release notes, migration guides) has been prepared or updated.
  • I have confirmed all CI checks have passed on the target branch after merging (post-merge verification).

Additional Notes

This development release is for internal testing and integration purposes.

This commit completely replaces the legacy `TypeConverter` and `TypeRegistry` system with a new, more robust `SQLTypeAdapter` protocol-based approach.

Key changes include:
- Introduction of `SQLTypeAdapter` protocol for clear, decoupled type conversion logic.
- Deletion of `basic_type_converter.py` and `type_converters.py`.
- Implementation of a new, simpler `TypeRegistry` for adapter lookup.
- Refactoring of the `StorageBackend` and `AsyncStorageBackend` to use the new `TypeAdaptionMixin`.
- Rewriting of SQLite-specific converters into new, clean `adapters`, removing redundant implementations in favor of standard adapters.

This refactoring improves type safety, simplifies the registration of converters, and makes the system more extensible for future backend implementations.
This commit implements several fine-tuning adjustments to the backend's type system and code structure:

- Clarified the roles of  (for DDL generation) and  (for DML operations) through enhanced docstrings.
- Refactored  to remove unused utility functions, retaining only  for DDL formatting.
- Updated  to reflect the changes in .
- Corrected the instantiation of  in  to remove an incorrect parameter.
- Removed an unused  import from .
- Added detailed rationale to  docstring, explaining its necessity for precise  handling.

These changes improve code clarity, reduce codebase footprint by removing unused components, and ensure the type system's architecture is well-documented.
This commit corrects the `test_dict_params` in the async SQLite backend tests. The test was previously failing because it passed a list of dictionaries directly to `execute_many`, which violates the framework's design principle that callers are responsible for providing database-compatible parameter types.

The fix aligns the test with the pattern demonstrated in `test_execute_many_parameter_adaption` by:
- Using `backend.prepare_parameters` to perform any necessary value-level type adaptation.
- Explicitly converting the dictionary of parameters into a tuple in the correct order before passing it to `execute_many`.

This ensures the test correctly follows the "caller's responsibility" principle for both value adaptation and structural formatting (dict to tuple), resolving the `sqlite3.ProgrammingError`.
…n of concerns

This commit introduces a significant refactoring of the type adaptation system and
enhances documentation to clearly articulate the "separation of concerns" principle
between type adaptation and backend execution.

Key changes include:

- Refactored Model-Level Type Mapping (`IActiveRecord`):
    - The obsolete `column_types()` method has been replaced with `get_column_adapters()`.
    - `__column_types_cache__` has been renamed to `__column_adapters_cache__` to reflect its new purpose of caching adapter mappings (`{field_name: (adapter_instance, target_db_type)}`).
    - The `_insert_internal` method now correctly uses `get_column_adapters()` and `backend.prepare_parameters()` to pre-adapt input data before calling the backend's `insert` method. The `column_adapters` map is also passed to `insert` for processing `RETURNING` clause outputs.

- Enhanced Dialect-Level Adapter Retrieval (`SQLDialectBase`):
    - A new abstract method, `get_column_adapter(field_info, type_registry)`, has been introduced in `SQLDialectBase`. This method is responsible for retrieving the appropriate `SQLTypeAdapter` and target database type for a given Pydantic field.
    - The `SQLiteDialect` has been updated with a concrete implementation of `get_column_adapter`, including logic for handling common Python types and their corresponding database types/adapters.

- Comprehensive Docstring Clarifications (`backend/base.py`):
    - The docstring for `TypeAdaptionMixin` has been significantly expanded to include a detailed "Architectural Note" explaining the "why" behind the separation of concerns, emphasizing the caller's responsibility for type adaptation and providing a clear example (e.g., database migration scenarios). It also clarifies the role of `adapter_registry`.
    - All high-level operation methods in `SQLOperationsMixin` and `AsyncSQLOperationsMixin` (i.e., `insert`, `update`, `delete`) now have updated docstrings with PEP 257-compliant `Args:` sections. These docstrings explicitly state that input parameters are expected to be *pre-adapted* and database-compatible.
    - The low-level `execute` and `execute_many` methods (and their async counterparts) now also feature updated docstrings that clearly define the roles of `params` (input, pre-adapted) and `column_adapters` (output, for result processing), with detailed `Args:` sections.
    - The `fetch_one` and `fetch_all` methods (and their async counterparts) have similarly updated docstrings.

These changes centralize type adaptation logic within the dialect and ensure that documentation clearly guides developers on the expected data flow and responsibilities, adhering strictly to the framework's design principles.
…ptation logic

This commit refactors the type adaptation system to centralize the logic for determining
SQLTypeAdapters and target database types.

Key changes include:
- Moved `get_column_adapter` logic from `SQLDialectBase` and `SQLiteDialect` to
  `IActiveRecord.get_column_adapters`, making the `adapter_registry` in `StorageBackendBase`
  the single source of truth for type adaptation.
- Enhanced `find_one`, `find_all`, and `delete` methods in `BaseActiveRecord` to
  utilize the new centralized `get_column_adapters` for robust and consistent
  preparation of query conditions and primary key values.
- Updated `BaseQueryMixin.one()` to pass column adapters to the backends `fetch_one`
  method, ensuring proper type conversion during data retrieval.
- Added architectural notes to `StorageBackendBase` clarifying the role of `adapter_registry`.

This refactoring aims to improve consistency, maintainability, and extensibility of
type handling across the ActiveRecord system, ensuring that Python data types are
correctly transformed for database interaction irrespective of the dialect.
Refactor type conversion logic to centralize adapter suggestions in the backend and streamline parameter/result processing within ActiveRecord models and queries.

This commit introduces a new architectural pattern for type adaptation:
-  now defines an abstract  method, requiring concrete backends to provide curated type mappings.
-  implements  with a deterministic, cached set of suggestions for common Python types relevant to SQLite.
- `IActiveRecord`'s `get_column_adapters` is refactored to a classmethod and utilizes these backend suggestions for result processing.
- `IActiveRecord`'s `_insert_internal` and `_update_internal` methods now properly leverage backend suggestions for preparing both SET clause and WHERE clause parameters.
- `BaseActiveRecord`'s `find_one`, `find_all`, and `delete` methods are updated to correctly use backend suggestions for preparing input query conditions.
- `BaseQueryMixin`'s `build`, `all`, and `one` methods are enhanced to prepare parameters and process results using the new backend-driven suggestions.

This change ensures consistent and explicit type conversion across the ORM while maintaining a clear separation of concerns between the ActiveRecord layer and the underlying database backend.
This refactoring moves the responsibility for query parameter type adaptation from the ActiveRecord model layer (`base.py`) to the query builder layer (`query/*.py`).

Key changes:
- Type conversion logic is now centralized in the query builders, simplifying the `find`, `find_all`, and `delete` methods in the model.
- A new `adapt_params(bool)` method has been introduced in the query interface, allowing type adaptation to be disabled when needed for greater flexibility.

This change leads to cleaner code, reduces duplication, and improves the maintainability of the query construction process.
… fix(backend): Normalize quoted column names in result processing

- Synchronized `async_backend.py` with `backend.py` by adding `_register_sqlite_adapters` and `get_default_adapter_suggestions` methods.
- Updated `__init__` in `AsyncSQLiteBackend` to call adapter registration.
- Added necessary type adapter imports to `async_backend.py`.
- Implemented stripping of quotes from column names in `AsyncTypeAdaptionMixin._process_result_set` to ensure consistent data representation across Python versions and resolve compatibility issues with `aiosqlite`.
…st failures

The type adapter caching mechanism was causing test failures across Python versions 3.8-3.13 when running full test suites, with only Python 3.14 working consistently. The cache was interfering with proper type adapter resolution across different test contexts, particularly affecting relationship queries.

- Removes `_default_suggestions_cache` in `SQLiteBackend`
- Removes `__column_adapters_cache` in `IActiveRecord`
- Ensures consistent behavior across all supported Python versions
- Fixes inconsistent test results between single-file and directory tests across Python 3.8-3.13 environments.
Modify the CI workflow to install `rhosocial-activerecord-testsuite`
directly from the `release/v1.0.0.dev3` branch on GitHub.

This change ensures that the CI pipeline uses the most recent version
of the testsuite, including the fix for the full outer join tests,
rather than relying on the version published to PyPI.
…atterns

- Rewrote model_testing.md (English and Chinese) to align with python-activerecord-testsuite patterns.
- Included detailed explanations and examples for test setup, CRUD operations, validation testing, and custom type adapter testing using a provider-based approach.
- Emphasized best practices derived from the test suite's structure for robust model testing.
- Updated examples to reflect correct backend access and custom adapter registration within a test context.
The `BaseActiveRecord.delete` method previously used a hardcoded '?'
placeholder when constructing the WHERE clause for the delete operation.
This caused `ValueError: Parameter count mismatch` errors on backends
like MySQL that use a different placeholder format (e.g., '%s').

This fix replaces the hardcoded '?' with a call to
`backend.dialect.get_placeholder()`, ensuring that the correct,
backend-specific placeholder is used. This resolves the bug and allows
delete operations to function correctly across all database backends.
This commit introduces several enhancements and fixes to the query and data persistence layer.

- **CTE Refactoring**: The mechanism for defining recursive CTEs has been refactored. The `recursive` flag is now passed to `format_with_clause` instead of being part of individual CTE definitions. This centralizes the logic and aligns better with the SQL `WITH RECURSIVE` syntax.

- **Enhanced PK Retrieval**: Primary key retrieval after an INSERT operation is now more robust. It prioritizes using the `RETURNING` clause data (for backends like PostgreSQL) and falls back to `last_insert_id` (for MySQL/SQLite), raising a `DatabaseError` if the key cannot be found.

- **Aggregate Query Fix**: Scalar aggregate queries (e.g., `count`, `sum`) now correctly ignore any `ORDER BY` or `LIMIT` clauses from the query chain, preventing incorrect results.

- **CTE Statement Recognition**: Statements starting with `WITH` are now correctly identified as read-only queries.
- Split `feature_bugfix_template.md` into `feature_template.md` and `bugfix_template.md` for more specific guidance.
- `feature_template.md` is now dedicated to new feature proposals.
- `bugfix_template.md` includes a dedicated "Reproduction Steps" section to emphasize clear bug reproduction.
- `release_hotfix_template.md` remains for release and critical hotfix management.

This refinement provides more granular and focused guidance for different types of contributions, aligning with the project's development workflow.
…ferences [skip ci]

- Renamed PostgreSQL backend references from 'pgsql' to 'postgres' across
  documentation (README.md, docs/en_US/**, docs/zh_CN/**) and
  build configuration (pyproject.toml).
- Updated asynchronous driver type from 'asyncpg' to 'psycopg' in
  documentation, reflecting current best practices and consistent naming.
…tsuite

Refactor the `conftest.py` files within the `tests/rhosocial/activerecord_test/feature/` subdirectories to follow a consistent, simplified pattern.

Previously, many of these files contained boilerplate code that duplicated the fixture definitions from the `rhosocial-activerecord-testsuite` package, or the files were missing entirely. This change removes the redundant logic and creates standardized `conftest.py` files that use a simple pass-through import:

`from rhosocial.activerecord.testsuite.feature/{feature_name}.conftest import *`

This makes the test setup cleaner, more maintainable, and ensures that the backend test configuration correctly and directly inherits the canonical fixture definitions from the testsuite.
Implement a command-line interface for the SQLite backend, allowing users
to execute SQL queries directly against a SQLite database.

This new tool can be invoked via `python -m rhosocial.activerecord.backend.impl.sqlite`.

Key features:
- Supports both file-based and in-memory databases via the `--db-file` flag.
- Defaults to an in-memory database if no file is specified.
- Integrates with the `rich` library for formatted, user-friendly output.
- Falls back gracefully to plain text if `rich` is not installed.
- Uses a decoupled `OutputProvider` pattern for maintainability.
Implement a command-line interface for the SQLite backend and abstract
its output handling to a shared module.

The new CLI tool, invoked via `python -m rhosocial.activerecord.backend.impl.sqlite`,
allows for direct SQL query execution against file-based or in-memory
SQLite databases.

Key features and changes in this commit:
- An `OutputProvider` strategy pattern is introduced and centralized in
  `backend/output.py` to handle both plain text and rich output,
  improving maintainability.
- The SQLite CLI is implemented to use this shared output provider.
- Documentation for the CLI is included, clarifying file creation
  behavior and concurrency considerations.
This commit introduces a new command-line interface for the SQLite backend and refactors backend documentation.

Key changes:
- Add a new CLI tool for the SQLite backend, invoked via
  `python -m rhosocial.activerecord.backend.impl.sqlite`.
- Abstract CLI output handling into a shared `OutputProvider` pattern,
  now located at `backend/output.py`.
- Refactor the mathematical notation documentation into a single,
  unified English version at `.gemini/math_notation.md`.
- Update diagrams to Mermaid format and correct syntax.
Align the main README title with the formal notation defined in the
math notation documentation. This improves consistency across the
project ecosystem.
Update the README.md for the SQLite CLI tool to document all new input and output functionalities:
- Multiple input sources: positional argument, --file flag, and stdin piping.
- Multiple output formats: table, json, csv, and tsv.
- The new --executescript flag for multi-statement SQL execution.
- Examples updated to demonstrate these new features, including file input, stdin input, and different output formats.
…le output formats

Significantly enhance the SQLite backend CLI tool with advanced input and output capabilities:

- **Multiple Input Sources:** The CLI now supports reading SQL queries from:
    - Positional arguments.
    - Files via the `--file` flag.
    - Standard input (stdin) via piping.
- **Multiple Output Formats:** Implemented new `--output` flag supporting:
    - `table`: Richly formatted tables (default when `rich` is installed).
    - `json`: Machine-readable JSON output.
    - `csv`: Comma-separated values output.
    - `tsv`: Tab-separated values output.
- **Multi-statement Execution:** Introduced `--executescript` flag for running SQL scripts containing multiple statements.
- **I/O Redirection Compliance:** Ensures data output goes to `stdout` and all log/error messages go to `stderr`.
- **Refactoring for Maintainability:**
    - Abstracted `OutputProvider` interface (`output_abc.py`) and `RichOutputProvider` (`output_rich.py`) to separate files.
    - Centralized `Json`, `Csv`, `Tsv` providers in `output.py`.
    - `__main__.py` dynamically selects the appropriate provider.
- **Documentation:** `README.md` and example SQL files are thoroughly updated.
- Updated ActiveRecord pattern description to clarify it's an implementation rather than a traditional ORM
- Added complete SQLite schema definitions and full example code for FastAPI integration
- Included API usage examples with curl commands and jq formatting
- Added demo code files in both Chinese and English documentation directories
- Created .gitignore files to exclude database files from commits
- Updated both Chinese and English versions consistently
- Updated the main README.md to clarify that Free-Threading support may be limited by backend database drivers
- Updated both Chinese and English introduction documentation to specify that support varies by backend
- Mentioned specific examples: SQLite and MySQL backends support Free-Threading mode, but PostgreSQL's psycopg driver may not
- Added reference to check individual backend documentation for specific support details
- Updated main README.md to clarify that Free-Threading Python is available from Python 3.13+
- Updated Python 3.13/3.14 compatibility section to reflect that free-threaded mode was introduced in Python 3.13
- Updated both Chinese and English documentation to use accurate version numbers (3.13+) instead of 3.14+
- Clarified that Python 3.13 introduced free-threaded mode as an optional build via PEP 703
- Corrected relative paths in database backend documentation to properly reference
  models and features across different sections
- Fixed links in mariadb.md, mysql.md, and primary_key_configuration.md
- Updated Pydantic integration example with proper path references
- Ensured all cross-section links use correct relative paths within language directories
- Verified all Markdown links point to existing files

Signed-off-by: vistart <i@vistart.me>
- Added clear notice that async functionality is not yet implemented at ActiveRecord/ActiveQuery level
- Updated both Chinese (zh_CN) and English (en_US) versions
- Made it clear that async is only available at backend level currently

Signed-off-by: vistart <i@vistart.me>
vistart and others added 10 commits November 28, 2025 15:36
- Added explanation about future ActiveRecord/ActiveQuery async capabilities depending on backend support
- Clarified that SQLite backend does not provide async support while MySQL/PostgreSQL do
- Updated both Chinese and English versions with consistent information

Signed-off-by: vistart <i@vistart.me>
- Enhanced bug report template with database-specific information fields
- Enhanced feature request template with database backend consideration sections
- Added guidance to direct users to appropriate repositories based on issue scope
- Included environment information specific to database backends
- Added sections for database queries, model definitions, and backend-specific configurations

Signed-off-by: vistart <i@vistart.me>
Modified test.yml to install rhosocial-activerecord-testsuite version 1.0.0.dev3 from TestPyPI instead of directly from the Git repository. This change is part of the release preparation process.
Configured test.yml to install rhosocial-activerecord-testsuite version 1.0.0.dev3 from its Git repository (release branch). This step is part of the release preparation process, ensuring regression testing with the intended test suite version.
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
6.7% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@vistart vistart merged commit 219c088 into main Nov 29, 2025
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant