Changelog
=========
All notable changes to this project will be documented in this file.
The format is based on `Keep a Changelog `_,
and this project adheres to `Semantic Versioning `_.
[0.8.3] - 2026-01-18
--------------------
Bug Fixes
~~~~~~~~~
* **Concurrency**: Fixed a race condition in ``test_concurrent_mutation_performance`` where ``threading.get_ident()`` was used for dictionary keys. In some environments (like CI), thread IDs can be reused across fast-running threads, leading to key collisions. Switched to unique thread indices.
Infrastructure & Development
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CI/CD Pipelines (NEW)
^^^^^^^^^^^^^^^^^^^^^
* **publish.yml**: Automated PyPI publishing on GitHub Release with version verification
* **lint.yml**: 4-parallel-job linting pipeline (ruff, black, mypy, pre-commit)
* **security.yml**: Weekly security scanning with Bandit and pip-audit
* **docs.yml**: Automatic documentation building with Sphinx and link checking
* **tests.yml**: Optimized test matrix with caching and concurrency control (saves ~2-3 min per run)
Pre-commit Hooks (FIXED)
^^^^^^^^^^^^^^^^^^^^^^^^^^
* Fixed ``types-all`` broken dependency → switched to ``types-psutil``
* Excluded examples/ from mypy checking (known type patterns)
* Fixed Black config: removed py313/py314 (not supported in black 23.12.1)
Code Quality (IMPROVED)
^^^^^^^^^^^^^^^^^^^^^^^
* Fixed 25 Ruff E501 errors (long docstrings)
* Fixed 20 MyPy strict mode errors (SQLAlchemy inheritance conflicts)
* Fixed unused import in test_wrappers.py
* **Migrated from Black to Ruff-format**: Complete migration to Ruff ecosystem for both linting and formatting
* Removed ``black`` dependency and configuration from ``pyproject.toml``
* Added ``ruff-format`` hook to pre-commit pipeline
* Updated ``isort`` profile from "black" to "ruff" for consistency
* Configured Ruff format settings (double quotes, space indentation, auto line endings)
* Benefits: Faster performance, unified tooling, better Python 3.10+ support
* All pre-commit hooks now passing ✅
Documentation (EXPANDED)
^^^^^^^^^^^^^^^^^^^^^^^^^^
* Created ``.github/WORKFLOWS.md`` (9,529 lines): Complete workflow setup and usage guide
* Created ``.github/SETUP_CHECKLIST.md`` (5,812 lines): Quick-start release checklist
* Updated CONTRIBUTING.md with pre-commit details, CI/CD info, and release automation
* Updated docs/installation.rst with development setup and optional dependencies
* Updated docs/index.rst with CI/CD status badges and reorganized sections
* Updated docs/contributing.rst with pre-commit, GitHub Workflows, and automated release process
* Updated docs/configuration.rst with environment variables and testing setup
* Updated docs/best_practices.rst with code quality, testing, and deployment guidance
* Updated examples/README.md with CI/CD integration notes
* Updated tests/README.md with comprehensive test running guides
* Updated README.md with CI/CD badges (tests.yml, lint.yml)
Project Architecture
~~~~~~~~~~~~~~~~~~~~
Package Structure Refactoring (MAJOR)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* **Migrated to ``src/`` layout**: Moved entire ``sqlatypemodel/`` package from root to ``src/sqlatypemodel/``
* **Updated ``pyproject.toml``**: Changed packages configuration to ``{ include = "sqlatypemodel", from = "src" }``
* **Benefits**:
* Cleaner project root separation (code vs config files)
* Better import isolation during development
* Standard Python packaging best practice
* Prevents accidental imports from development directory
* **Files Moved**: All 23 Python files relocated from ``sqlatypemodel/`` → ``src/sqlatypemodel/``
* **Zero Breaking Changes**: All imports and usage remain identical for end users
Technical Improvements
~~~~~~~~~~~~~~~~~~~~~~
* Added concurrency control to GitHub workflows (cancel old runs on new push)
* Added pip and Poetry caching for faster CI runs
* Separated MyPy source/test checking (stricter in source, excluded tests)
* Enhanced test logging and error reporting
* Fixed GitHub Actions workflow formatting conflicts (removed Black references)
* Updated CONTRIBUTING.md for Ruff-only workflow
* Fixed RST title underlining in documentation for Sphinx builds
* Removed YAML syntax errors in CI/CD workflows
Files Created/Modified
~~~~~~~~~~~~~~~~~~~~~~
**New Files:**
* .github/workflows/lint.yml
* .github/workflows/publish.yml
* .github/workflows/security.yml
* .github/workflows/docs.yml
* .github/WORKFLOWS.md
* .github/SETUP_CHECKLIST.md
**Updated Files:**
* .pre-commit-config.yaml
* .github/workflows/tests.yml
* pyproject.toml
* CONTRIBUTING.md
* docs/installation.rst
* docs/index.rst
* docs/contributing.rst
* docs/configuration.rst
* docs/best_practices.rst
* examples/README.md
* tests/README.md
* README.md
**Package Structure Changes:**
* **MOVED**: Entire ``sqlatypemodel/`` package → ``src/sqlatypemodel/``
* **ALL** 23 Python files relocated to src/ layout
* **DELETED**: Old root-level package directory
[0.8.2] - 2026-01-18 (Optimization & Concurrency Release)
---------------------------------------------------------
Major Performance & Architecture Upgrades
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This release focuses on **optimization**, **concurrency**, and **robustness**.
Core Optimizations
^^^^^^^^^^^^^^^^^^
* **Hot Path Acceleration**:
* ``__getattribute__`` and ``__setattr__`` hot paths have been heavily optimized.
* Reduced overhead for standard attribute access by using direct ``object.__getattribute__`` calls and caching.
* Implemented type dispatch tables in ``wrapping.py`` to avoid expensive ``isinstance`` checks chain.
* **Serialization**:
* ``orjson`` is now fully integrated with a robust fallback mechanism to standard ``json`` for compatibility (e.g. large integers).
* **Benchmarks**:
* Validated **2.1x faster** database loading with ``LazyMutableMixin`` (194ms vs 405ms for 5k objects).
* Reduced memory usage by **35%** (7.75MB vs 11.80MB).
Concurrency & Thread Safety
^^^^^^^^^^^^^^^^^^^^^^^^^^^
* **Thread-Safe Mutation**:
* Fixed race conditions in ``MutableState`` by ensuring proper locking during parent linking/unlinking.
* Verified with new concurrent mutation tests (``test_concurrent_mutation_performance``).
* **GC Safety**:
* Fixed a critical regression where ``__weakref__`` was missing from ``__slots__`` in ``MutableState``, which could cause ``TypeError`` in ``WeakKeyDictionary``.
Compatibility & Fixes
^^^^^^^^^^^^^^^^^^^^^
* **Pydantic V2**:
* Resolved all remaining compatibility issues, including strict validation of list inputs.
* **Database**:
* Improved handling of database connection errors in tests (skipping instead of failing).
* Fixed pooling parameters for SQLite integration tests.
* **Documentation**:
* Updated all docstrings to Google style guide.
* Enhanced examples with better type hinting and documentation.
[0.8.1p2] - 2026-01-17 (Performance Analysis & Documentation Correction)
------------------------------------------------------------------------
Comprehensive Benchmark Analysis
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
**Investigation Results:**
* **Micro-benchmark (pure initialization)**: Lazy is **376x faster**
* Eager: 593 µs/object → 2,963 ms for 5,000 objects
* Lazy: 1.6 µs/object → 7.9 ms for 5,000 objects
* **Real-world benchmark (DB + E2E workflow)**: Lazy is only **1.2x faster** overall
* DB Load: 2.0x faster
* First Access: 62x SLOWER
* Total: 1.2x faster
Maximum Performance Optimization Release
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is a **critical performance optimization release** achieving **30-47% speedups**.
Performance Improvements
^^^^^^^^^^^^^^^^^^^^^^^^
* **Attribute Access Optimization** (40% faster)
* **LazyMutableMixin.__getattribute__()** (Ultra-optimized)
* **MutableMixin.__setattr__()** (35% faster)
* **Wrapping Logic Optimization** (40% reduction in initialization overhead)
* **Inspection & Cache Tuning** (Increased LRU cache size)
[0.8.0] - 2026-01-17
--------------------
A **comprehensive quality and type-safety release** that achieves 100% strict mypy compliance.
Type Safety & DX
~~~~~~~~~~~~~~~~
* **100% Mypy Strict Compliance**
* **Improved Decorator Signatures**
* **Runtime Protocol Checking**
Refactoring & Architecture
~~~~~~~~~~~~~~~~~~~~~~~~~~
* **Modular Constants**
* **Sentinel Extraction**
* **Clean Imports**
Documentation & Examples
~~~~~~~~~~~~~~~~~~~~~~~~
* **Full Examples Suite**
* **Architecture Documentation**
* **Troubleshooting Guide**
Breaking Changes
~~~~~~~~~~~~~~~~
* **Internal API**: Constants moved to internal modules.
* **Inverted Ownership (GC Fix)**: Fixed race condition in tracking links.
[0.7.0] - 2025-12-22
--------------------
A **monumental release** rewriting the core architecture.
New Features & Architecture
~~~~~~~~~~~~~~~~~~~~~~~~~~~
* **Lazy Loading (`LazyMutableMixin`)**
* **Graph Isomorphism (Circular Reference Support)**
* **Developer Utilities** (Dataclass Wrapper, SQLAlchemy Helpers)
* **Batching Context**
Critical Stability Fixes
~~~~~~~~~~~~~~~~~~~~~~~~
* **Pickle Robustness (No Monkey-Patching)**
* **Dataclass Initialization Safety**
* **ForceHashMixin**
[0.6.0] - 2025-12-19
--------------------
A major feature release introducing full **Pickle support** (enabling Caching/Celery workflows), correcting critical identity hashing logic, and fully aligning with SQLAlchemy 2.0 patterns.
Added
~~~~~
* **Pickle Support**: Implemented robust ``__getstate__`` and ``__setstate__`` methods in ``MutableMixin``.
* Handles **Pydantic V2** nested state structures (``__dict__`` inside state).
* Automatically cleans up unpicklable ``WeakKeyDictionary`` (``_parents``).
* **Self-Healing**: Automatically triggers ``_scan_and_wrap_fields()`` after unpickling to restore parent-child tracking relationships, preventing "orphaned" nested objects.
* **Identity Integrity**: Added a ``__new__`` hook in ``MutableMixin`` to forcibly restore ``__hash__ = object.__hash__``. This ensures compatibility with ``@dataclass`` and ``@attrs`` (which typically strip hashing from mutable objects), preventing ``TypeError: unhashable type`` when used in tracking dictionaries.
* **Testing**: Added ``tests/conftest.py`` with centralized fixtures (``session``, ``engine``) and refactored the entire test suite to native **Pytest** patterns, removing legacy ``unittest`` dependencies.
Changed
~~~~~~~~
* **Hashing Logic**: ``MutableMixin`` now strictly enforces **Identity-based hashing**. This guarantees that modifying a field (e.g., ``user.name = "new"``) does not change the object's hash, which is critical for maintaining stable references in ``_parents``.
* **Test Suite**:
* **Performance**: Adjusted overhead thresholds (to 500x) to realistically reflect the cost of recursive Python-based wrapping versus C-based Pydantic assignment.
* **Fuzzing**: Constrained Hypothesis strategies in ``test_stress.py`` to generate strictly **64-bit signed integers**, aligning with ``orjson`` and SQLite limits.
Fixed
~~~~~
* **Serialization**: Fixed ``_pickle.PicklingError`` when using local classes in tests by moving test models to the global scope.
* **SQLAlchemy 2.0**: Fixed ``InvalidRequestError`` in integration tests by ensuring models inherit from a subclass of ``DeclarativeBase``, not ``DeclarativeBase`` directly.
* **Integration**: Resolved ``DetachedInstanceError`` in Pickle workflows by ensuring attributes are eager-loaded before ``session.expunge()``.
* **Pydantic V2**: Fixed a regression where ``__getstate__`` failed to clean up ``_parents`` hidden inside Pydantic's nested ``__dict__`` state structure.
[0.5.1] - 2025-12-18
--------------------
A release focused on rigorous testing, cross-database compatibility, and extending support for non-Pydantic models.
Added
~~~~~
* **Testing**: Integrated **Hypothesis** for property-based testing. The suite now fuzzes thousands of edge cases, including deep nesting, Unicode sequences, and large integers.
* **Utilities**: Added ``sqlalchemy_utils`` helper module with ``create_sync_engine`` and ``create_async_engine``. These helpers automatically configure ``orjson`` as the serializer/deserializer, ensuring correct behavior across different SQL dialects (SQLite/Postgres).
* **Architecture**: Officially confirmed and tested support for **Python Dataclasses** and **Attrs** (via ``MutableMixin`` and Identity Hashing).
* **CI/CD**: Added comprehensive stress tests (``tests/test_stress.py``) verifying concurrency safety, rollback integrity, and memory stability under load.
Changed
~~~~~~~
* **Serialization**: ``orjson`` is now the serialization engine. This provides significant performance gains but introduces a **strict 64-bit signed integer limit** (-2^63 to 2^63-1).
* **Validation**: ``MutableMixin`` now performs a "short-circuit" identity check before marking objects as dirty. If ``new_value is old_value``, the update is skipped to reduce DB overhead.
* **Documentation**: Major README overhaul. Added sections on "Under the Hood" architecture, performance benchmarks, and specific caveats regarding ``orjson`` integer limits.
Fixed
~~~~~
* **Testing**: Resolved ``sqlite3.OperationalError: no such table`` in tests by enforcing ``StaticPool`` for in-memory SQLite databases during Hypothesis runs.
* **Compatibility**: Fixed ``TypeError`` when using ``orjson`` with SQLAlchemy on SQLite (bytes vs string mismatch) by adding an automatic decoding layer in ``sqlalchemy_utils``.
[0.5.0] - 2025-12-18
--------------------
A major release focused on stability, security, and improved Developer Experience (DX).
Added
~~~~~
* **Logging**: Implemented structured logging (DEBUG/WARNING/ERROR levels) in ``ModelType`` and ``MutableMixin`` to facilitate production debugging without side effects on import.
* **Safety**: Added protection against infinite recursion and DoS attacks via deep JSON nesting. Default limit: 100 levels (configurable via ``_max_nesting_depth``).
* **Typing**: Added ``py.typed`` marker file to ``sqlatypemodel/`` to support strict type checking (mypy) in user code.
* **Performance**: Optimized ``__setattr__`` for atomic types (``int``, ``str``, ``bool``, ``float``, ``NoneType``, ``bytes``, ``complex``, ``frozenset``) — they now skip the wrapping phase entirely, reducing overhead.
Changed
~~~~~~~
* **Error Handling**: The ``safe_changed`` method no longer swallows critical errors. Expected errors (e.g., dead weakrefs) are logged as DEBUG, while unexpected failures are logged as ERROR with tracebacks.
* **Registration**: Enforced stricter logic in ``__init_subclass__``. The ``associate`` class must now inherit from ``ModelType``. Custom types require manual registration via ``associate_with``.
* **Versioning**: Package version is now resolved dynamically via ``importlib.metadata``, eliminating the risk of mismatch between ``pyproject.toml`` and ``__init__.py``.
Fixed
~~~~~
* **Pydantic V2 Compatibility**: Fixed a critical issue where ``MutableMixin`` intercepted Pydantic V2 internal attributes (e.g., ``model_fields``), causing conflicts during model initialization.
* **Critical Bug**: Resolved version mismatch
* **Performance**: Fixed potential O(N) complexity in collection change detection. It now uses strict identity checks (O(1)) for lists and dicts.