From bb1de54f84265ab3291dfeb303597c995ea4ac87 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Nov 2025 01:23:00 +0000 Subject: [PATCH 1/5] Fill out architecture documentation with system overview Document the high-level system architecture, major components, and their relationships for the frigid library. This provides a comprehensive overview of the layered architecture, data flow patterns, and key architectural patterns used throughout the codebase. The documentation covers: - Purpose and scope of the library - Major components in public API and implementation layers - Component relationships and dependency flows - Data flow patterns for initialization and operations - Key architectural patterns (wrapper, delegation, etc.) - Quality attributes and system constraints --- documentation/architecture/summary.rst | 374 ++++++++++++++++++++++++- 1 file changed, 373 insertions(+), 1 deletion(-) diff --git a/documentation/architecture/summary.rst b/documentation/architecture/summary.rst index bab368a..40d483b 100644 --- a/documentation/architecture/summary.rst +++ b/documentation/architecture/summary.rst @@ -21,4 +21,376 @@ System Overview ******************************************************************************* -.. todo:: Describe the high-level system architecture, major components, and their relationships. \ No newline at end of file +Frigid is a Python library that provides immutable data structures and class +behaviors through a layered architecture. The system enforces immutability +at multiple levels - from low-level dictionary implementations to high-level +class decorators - while maintaining compatibility with Python's standard +library patterns and third-party tools like dataclasses. + +Purpose and Scope +=============================================================================== + +The library addresses the need for immutable data structures in Python by: + +* Providing drop-in replacements for mutable built-in types (dict, namespace) +* Enabling conversion of arbitrary classes to immutable variants +* Supporting selective mutability for gradual adoption +* Maintaining type safety and comprehensive documentation + +The library does not attempt to make immutability completely unbreakable +(which is impossible in Python), but instead provides practical immutability +that integrates naturally with Python's idioms and existing code. + +Major Components +=============================================================================== + +The system is organized into distinct layers that build upon each other: + +Public API Layer +------------------------------------------------------------------------------- + +**dictionaries.py** + Immutable dictionary implementations with two variants: + + - ``Dictionary``: Standard immutable dictionary similar to dict but frozen + - ``ValidatorDictionary``: Dictionary with validation on initialization + - Provides set operations (union, intersection) not available on MappingProxyType + +**namespaces.py** + Immutable namespace objects similar to ``types.SimpleNamespace`` but with + frozen attributes after creation. + +**classes.py** + Metaclasses and decorators for creating immutable classes: + + - Metaclasses (Class, Dataclass, AbstractBaseClass, ProtocolClass, etc.) + - Base classes (Object, DataclassObject, Protocol variants) + - Decorators (with_standard_behaviors, dataclass_with_standard_behaviors) + +**modules.py** + Immutable module types and utilities for freezing module-level constants + after initialization. + +**sequences.py** + Utility functions for creating immutable sequences, primarily the ``one()`` + function for single-item tuples. + +**exceptions.py** + Exception hierarchy for immutability violations: + + - ``AttributeImmutability``: Raised when modifying immutable attributes + - ``EntryImmutability``: Raised when modifying immutable dictionary entries + - ``EntryInvalidity``: Raised when validation fails + +**installers.py** + Convenience utilities for installing frigid functions into Python builtins. + +Core Implementation Layer +------------------------------------------------------------------------------- + +Located in the ``__`` subpackage (internal implementation): + +**ImmutableDictionary** (``__/dictionaries.py``) + The foundational immutable dictionary class that all other dictionary-based + structures build upon. Subclasses ``dict`` and uses behavioral flags to + enforce immutability after initialization. + +**imports.py** (``__/imports.py``) + Centralized import hub providing all external dependencies through a single + namespace. Primary dependencies include classcore, dynadoc, absence, and + typing_extensions. + +**nomina.py** (``__/nomina.py``) + Type aliases, type variables, and naming utilities used throughout the + package. + +**doctab.py** (``__/doctab.py``) + Documentation fragments table for dynamic documentation generation via + dynadoc. + +**exceptions.py** (``__/exceptions.py``) + Internal exception classes used by the implementation layer. + +Foundation Dependencies +------------------------------------------------------------------------------- + +**classcore** + Provides the core class factory mechanism and attribute protection system. + Frigid delegates most low-level immutability enforcement to classcore's + ``standard`` module while providing higher-level API and configuration. + +**dynadoc** + Enables dynamic documentation generation using reusable fragments. All + classes define ``_dynadoc_fragments_`` attributes referencing documentation + strings from the doctab. + +**absence** + Provides the ``absent`` sentinel value for distinguishing missing values + from ``None`` in optional parameters. + +Component Relationships +=============================================================================== + +Architecture Layers +------------------------------------------------------------------------------- + +The system follows a clear layered architecture: + +:: + + ┌─────────────────────────────────────────────────────────────┐ + │ Public API │ + │ (Dictionary, Namespace, Object, decorators) │ + └─────────────────────────────────────────────────────────────┘ + ↓ + ┌─────────────────────────────────────────────────────────────┐ + │ Core Implementation (__/) │ + │ (ImmutableDictionary, type aliases, doc fragments) │ + └─────────────────────────────────────────────────────────────┘ + ↓ + ┌─────────────────────────────────────────────────────────────┐ + │ Foundation Libraries │ + │ (classcore, dynadoc, absence) │ + └─────────────────────────────────────────────────────────────┘ + +Dependency Flow +------------------------------------------------------------------------------- + +All modules follow the ``__`` import pattern: + +1. Public modules import from ``. import __`` +2. The ``__`` package provides centralized access to external dependencies +3. Configuration flows from public API through to classcore via partial application +4. Runtime checks flow from classcore back through implementation to user code + +Key dependencies between components: + +* ``dictionaries.py`` → ``classes.py`` (uses AbstractBaseClass metaclass) +* ``namespaces.py`` → ``classes.py`` (uses Object base class) +* ``modules.py`` → ``classes.py`` (uses Module metaclass) +* All components → ``__`` (centralized imports and utilities) +* ``classes.py`` → ``classcore.standard`` (core class factory) + +Data Flow Patterns +=============================================================================== + +Initialization Flow +------------------------------------------------------------------------------- + +Immutable objects follow a consistent initialization pattern: + +1. Object creation begins with standard Python ``__new__`` +2. During ``__init__``, attributes/entries can be freely set +3. After ``__init__`` completes, protection is activated +4. Subsequent modification attempts raise immutability exceptions + +For ``ImmutableDictionary``: + +:: + + __init__ starts + ↓ + Set entries in dict (immutability not active) + ↓ + Add 'immutability' flag to _behaviors_ + ↓ + __init__ completes + ↓ + Future __setitem__/__delitem__ check flag and raise exceptions + +For classes using metaclasses: + +:: + + User class definition + ↓ + Metaclass __new__ with classcore.standard.class_factory + ↓ + Instance __init__ (attributes can be set) + ↓ + Protection activated via __setattr__/__delattr__ overrides + ↓ + Future modifications raise AttributeImmutability + +Operation Flow +------------------------------------------------------------------------------- + +Dictionary operations (union, intersection) maintain immutability: + +1. User invokes operation: ``dict1 | dict2`` +2. Operation method computes new data +3. Method calls ``with_data()`` to create new instance +4. New instance has same type and validator (if applicable) +5. Returns new immutable dictionary + +Class Creation Flow +------------------------------------------------------------------------------- + +When using decorators or metaclasses: + +:: + + User defines class with metaclass or decorator + ↓ + Metaclass or decorator invokes _class_factory (partial) + ↓ + classcore.standard.class_factory receives configuration: + - attributes_namer (calculate_attrname) + - dynadoc_configuration + - error_class_provider + - protection/concealment behaviors + ↓ + Returns configured class with immutability enforcement + ↓ + User creates instances with standard constructor + ↓ + classcore enforces attribute protection after __init__ + +Key Architectural Patterns +=============================================================================== + +Wrapper Pattern +------------------------------------------------------------------------------- + +Public classes wrap internal implementations: + +* ``Dictionary`` wraps ``ImmutableDictionary`` stored in ``_data_`` attribute +* ``ValidatorDictionary`` extends ``Dictionary`` with ``_validator_`` attribute +* ``Namespace`` uses ``ImmutableDictionary`` for ``__dict__`` + +This separation provides: + +* Clean public API distinct from implementation details +* Flexibility to change implementation without breaking API +* Support for subclassing and specialization + +Delegation Pattern +------------------------------------------------------------------------------- + +Frigid delegates core functionality to classcore rather than reimplementing +immutability mechanisms. This provides: + +* Reduced code duplication +* Leveraging battle-tested implementation +* Consistent behavior with other classcore-based packages +* Focus on user-facing API and documentation + +Configuration via Partial Application +------------------------------------------------------------------------------- + +Class factories use ``functools.partial`` to bind frigid-specific configuration: + +.. code-block:: python + + _class_factory = partial( + ccstd.class_factory, + attributes_namer=calculate_attrname, + dynadoc_configuration=DynadocConfiguration(...), + error_class_provider=_provide_error_class, + ) + +This pattern enables: + +* Reusable configuration across multiple metaclasses +* Clear separation of frigid customization from classcore mechanics +* Type-safe configuration that fails at import time, not runtime + +Centralized Import Hub Pattern +------------------------------------------------------------------------------- + +The ``__`` subpackage provides consistent access to dependencies: + +* All modules use ``from . import __`` +* Single source of truth for external dependencies +* Easy refactoring of dependencies +* Reduced import overhead through centralization + +Template Method Pattern +------------------------------------------------------------------------------- + +Abstract methods enable customization in subclasses: + +* ``Dictionary.with_data()`` - creates new instance with different data +* Subclasses override to maintain type and behavior +* Enables operations like union/intersection to return correct types + +Behavioral Flags Pattern +------------------------------------------------------------------------------- + +``ImmutableDictionary`` uses a ``_behaviors_`` set to track state: + +* During ``__init__``, 'immutability' not in set (modifications allowed) +* After ``__init__``, 'immutability' added to set (modifications blocked) +* Methods check flag before allowing operations +* Provides clear initialization window without complex state tracking + +Quality Attributes +=============================================================================== + +Maintainability +------------------------------------------------------------------------------- + +* Clear layered architecture separates concerns +* Delegation to classcore reduces maintenance burden +* Centralized imports simplify dependency management +* Comprehensive documentation via dynadoc + +Usability +------------------------------------------------------------------------------- + +* Familiar API similar to built-in types +* Multiple access patterns (metaclasses, decorators, direct instantiation) +* Clear exception messages for violations +* Gradual adoption via selective mutability + +Compatibility +------------------------------------------------------------------------------- + +* Works with dataclasses and other decorators +* Compatible with protocols and abstract base classes +* Supports pickling and standard Python introspection +* Respects existing Python conventions + +Performance +------------------------------------------------------------------------------- + +* Centralized imports reduce per-module import overhead +* Delegation to classcore leverages optimized C code where available +* Minimal runtime overhead beyond Python's standard attribute access +* No runtime code generation or bytecode manipulation + +System Constraints +=============================================================================== + +Python Language Limitations +------------------------------------------------------------------------------- + +True immutability is impossible in Python: + +* Anyone with intermediate knowledge can circumvent protections +* ``object.__setattr__`` can bypass custom ``__setattr__`` +* Direct manipulation of ``__dict__`` possible in some cases +* Reflection and introspection expose internal state + +The library provides practical immutability for normal usage, not security +against determined circumvention. + +Initialization Window Requirement +------------------------------------------------------------------------------- + +Objects must support normal Python initialization: + +* ``__init__`` must be able to set attributes +* Dataclass initialization requires attribute assignment +* Protection activates only after ``__init__`` completes +* Brief window where object is technically mutable + +Compatibility with Third-Party Tools +------------------------------------------------------------------------------- + +Must work with existing Python ecosystem: + +* Dataclasses require specific initialization patterns +* Pickling requires certain attributes to be accessible +* Introspection tools expect standard Python semantics +* Documentation tools need readable docstrings and signatures \ No newline at end of file From 9f6095969fcb49eb32a4640da329a8d498fe5f7a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Nov 2025 01:55:05 +0000 Subject: [PATCH 2/5] Complete architecture documentation with PRD and filesystem details Add comprehensive Product Requirements Document (PRD) that defines: - Executive summary and problem statement - User personas and target users - Detailed functional requirements with acceptance criteria - Non-functional requirements (performance, compatibility, usability) - Constraints, assumptions, and scope boundaries Expand filesystem.rst with detailed module organization: - Complete package structure with all modules documented - Module purposes and responsibilities for both public API and internal implementation - Import pattern implementation and benefits - Exception hierarchy and dual inheritance pattern - Test organization structure and naming conventions - Documentation organization and types - Development workspace structure and usage - Configuration files and tool settings Both documents follow the architecture guidelines and provide comprehensive reference material for understanding the frigid library's organization, requirements, and design decisions. Co-Authored-By: Claude Sonnet 4.5 --- documentation/architecture/filesystem.rst | 483 ++++++++++++++++++- documentation/prd.rst | 557 +++++++++++++++++++++- 2 files changed, 1027 insertions(+), 13 deletions(-) diff --git a/documentation/architecture/filesystem.rst b/documentation/architecture/filesystem.rst index 4b3f4c8..fb399e1 100644 --- a/documentation/architecture/filesystem.rst +++ b/documentation/architecture/filesystem.rst @@ -57,23 +57,171 @@ The main Python package follows the standard ``sources/`` directory pattern: .. code-block:: sources/ - ├── frigid/ # Main Python package - │ ├── __/ # Centralized import hub - │ │ ├── __init__.py # Re-exports core utilities - │ │ ├── imports.py # External library imports - │ │ └── nomina.py # python-frigid-specific naming constants - │ ├── __init__.py # Package entry point - │ ├── py.typed # Type checking marker - │ ├── exceptions.py # Package exception hierarchy - │ └── [modules].py # Feature-specific modules - + └── frigid/ # Main Python package + ├── __/ # Centralized import hub (internal) + │ ├── __init__.py # Re-exports core utilities + │ ├── imports.py # External library imports + │ ├── dictionaries.py # ImmutableDictionary implementation + │ ├── doctab.py # Documentation fragments table + │ ├── exceptions.py # Internal exception classes + │ └── nomina.py # Type aliases and naming utilities + ├── __init__.py # Package entry point (public API) + ├── py.typed # Type checking marker for mypy/pyright + ├── classes.py # Metaclasses and decorators for immutable classes + ├── dictionaries.py # Public immutable dictionary types + ├── exceptions.py # Public exception hierarchy + ├── installers.py # Utilities for installing into builtins + ├── modules.py # Immutable module types + ├── namespaces.py # Immutable namespace objects + └── sequences.py # Immutable sequence utilities All package modules use the standard ``__`` import pattern as documented in the common architecture guide. +Module Purposes +------------------------------------------------------------------------------- + +**Public API Modules** (directly under ``sources/frigid/``): + +``__init__.py`` + Package entry point that re-exports the public API. Imports and exposes: + + * Core classes (Dictionary, ValidatorDictionary, Namespace, Object, etc.) + * Metaclasses (Class, Dataclass, AbstractBaseClass, Protocol variants) + * Decorators (with_standard_behaviors, dataclass_with_standard_behaviors) + * Exception classes (AttributeImmutability, EntryImmutability, etc.) + * Utility functions (one, finalize_module) + +``classes.py`` + Metaclasses and decorators for creating immutable classes: + + * Metaclasses: Class, Dataclass, DataclassMutable, AbstractBaseClass, + ProtocolClass, ProtocolDataclass, ProtocolDataclassMutable + * Base classes: Object, ObjectMutable, DataclassObject, + DataclassObjectMutable, Protocol variants + * Decorators: with_standard_behaviors, dataclass_with_standard_behaviors + * All delegate to classcore.standard.class_factory with frigid configuration + +``dictionaries.py`` + Immutable dictionary implementations: + + * AbstractDictionary: Base class defining immutable dictionary interface + * Dictionary: Standard immutable dictionary (wraps ImmutableDictionary) + * ValidatorDictionary: Dictionary with validation on initialization + * Supports set operations (union ``|``, intersection ``&``) + +``exceptions.py`` + Public exception hierarchy: + + * Omniexception: Base exception for all frigid exceptions + * Omnierror: Base error (inherits from Omniexception) + * AttributeImmutability: Raised when modifying immutable attributes + * EntryImmutability: Raised when modifying immutable dictionary entries + * EntryInvalidity: Raised when dictionary validation fails + +``installers.py`` + Utilities for installing frigid functions into Python builtins: + + * install_into_builtins(): Adds frigid utilities to builtins module + * Opt-in mechanism for making frigid functions globally available + +``modules.py`` + Immutable module types and utilities: + + * Module: Immutable module class (extends types.ModuleType) + * finalize_module(): Combines dynadoc generation with module reclassification + * Prevents modification of module-level constants after finalization + +``namespaces.py`` + Immutable namespace objects: + + * Namespace: Similar to types.SimpleNamespace but immutable + * Initialization from iterables, mappings, and keyword arguments + * Uses ImmutableDictionary for __dict__ storage + +``sequences.py`` + Immutable sequence utilities: + + * one(): Creates single-item tuple more readably than ``(x,)`` syntax + * Minimal module focused on ergonomic tuple creation + +**Internal Implementation** (under ``sources/frigid/__/``): + +``__init__.py`` + Re-exports commonly used imports for internal use: + + * All imports from imports.py + * All type aliases from nomina.py + * Makes ``from . import __`` work consistently + +``imports.py`` + Centralized external library imports: + + * Standard library: abc, collections.abc, dataclasses, functools, types + * Third-party: classcore, dynadoc, absence, typing_extensions + * Provides consistent namespace for all frigid modules + * Reduces import duplication and eases dependency management + +``dictionaries.py`` + Core immutable dictionary implementation: + + * ImmutableDictionary: Subclasses dict with immutability enforcement + * Uses _behaviors_ set to track immutability state + * Allows modifications during __init__, blocks after initialization + * Foundation for all dictionary-based immutable structures + +``doctab.py`` + Documentation fragments for dynamic documentation: + + * Reusable documentation strings for classes and behaviors + * Used by dynadoc to generate comprehensive docstrings + * Organized by topic (classes, modules, behaviors, etc.) + +``exceptions.py`` + Internal exception classes: + + * EntryImmutability: Internal version for dictionary operations + * OperationInvalidity: Raised for invalid operations on immutable collections + * Used by implementation layer before being re-raised as public exceptions + +``nomina.py`` + Type aliases, type variables, and naming utilities: + + * Type variables: H (hashable), V (value), etc. + * Type aliases for common signatures + * calculate_attrname(): Generates package-specific attribute names + * Provides consistent naming across the package + Component Integration =============================================================================== +Import Pattern Implementation +------------------------------------------------------------------------------- + +All public modules follow the centralized import pattern: + +.. code-block:: python + + # In any public module (e.g., dictionaries.py, namespaces.py) + from . import __ + + # Usage throughout the module + class Dictionary( __.cabc.Mapping[ __.H, __.V ] ): + ''' Immutable dictionary implementation. ''' + def __init__( self, *args: __.typx.Any, **kwargs: __.typx.Any ): + self._data_ = __.ImmutableDictionary( *args, **kwargs ) + +This pattern provides: + +* Consistent access to external dependencies (classcore, dynadoc, absence) +* Type aliases (cabc for collections.abc, typx for typing extensions) +* Internal utilities (ImmutableDictionary, calculate_attrname) +* Reduced per-module import overhead + +The ``__`` package acts as a single source of truth for all dependencies, +making it easy to update dependencies or add new ones without modifying +individual modules. + Exception Organization ------------------------------------------------------------------------------- @@ -81,6 +229,321 @@ Package-wide exceptions are centralized in ``sources/frigid/exceptions.py`` following the standard hierarchy patterns documented in the `common practices guide `_. +The exception hierarchy follows this structure: + +.. code-block:: + + Omniexception (base for all frigid exceptions) + └── Omnierror (base for error conditions) + ├── AttributeImmutability (attribute modification violations) + ├── EntryImmutability (dictionary entry modification violations) + └── EntryInvalidity (validation failures) + +Each exception class inherits from both the frigid base and an appropriate +Python built-in exception: + +* ``AttributeImmutability`` → ``Omnierror`` + ``AttributeError`` +* ``EntryImmutability`` → ``Omnierror`` + ``TypeError`` +* ``EntryInvalidity`` → ``Omnierror`` + ``ValueError`` + +This dual inheritance ensures exceptions are catchable both through frigid's +hierarchy and through standard Python exception types. + +Documentation Integration +------------------------------------------------------------------------------- + +The package uses dynadoc for dynamic documentation generation: + +**Documentation Fragments** (``sources/frigid/__/doctab.py``): + +* Centralized table of reusable documentation strings +* Organized by category (classes, modules, behaviors) +* Enables consistent documentation across similar components + +**Fragment Usage**: + +.. code-block:: python + + class Dictionary: + _dynadoc_fragments_ = { + 'description': doctab.classes.Dictionary.description, + 'examples': doctab.classes.Dictionary.examples, + } + +**Benefits**: + +* Reduces documentation duplication +* Ensures consistency across similar classes +* Facilitates documentation updates +* Supports multiple documentation renderers + +Test Organization +=============================================================================== + +Test Structure +------------------------------------------------------------------------------- + +Tests mirror the source package structure: + +.. code-block:: + + tests/ + ├── test_000_modules/ # Module-level tests + │ ├── test_010_classes.py # Tests for classes.py + │ ├── test_020_dictionaries.py # Tests for dictionaries.py + │ ├── test_030_namespaces.py # Tests for namespaces.py + │ ├── test_040_sequences.py # Tests for sequences.py + │ └── test_050_modules.py # Tests for modules.py + ├── test_100_edge_cases/ # Edge case and integration tests + └── fixtures/ # Shared test fixtures + +This organization follows the `test development guidelines +`_. + +Test Naming Conventions +------------------------------------------------------------------------------- + +**File naming**: ``test__.py`` + +* Priority indicates test execution order (000, 010, 020, etc.) +* Module name matches the source module being tested + +**Test function naming**: ``test__`` + +* Number indicates test execution order within file +* Description uses snake_case and clearly states what is tested + +**Example**: + +.. code-block:: python + + # In tests/test_000_modules/test_020_dictionaries.py + def test_010_dictionary_initialization_from_kwargs( ): + ''' Dictionary can be initialized from keyword arguments. ''' + + def test_020_dictionary_prevents_modification( ): + ''' Dictionary raises exception on modification attempt. ''' + +Test Coverage +------------------------------------------------------------------------------- + +The test suite aims for comprehensive coverage: + +* Unit tests for all public APIs +* Edge case tests for boundary conditions +* Integration tests for component interactions +* Doctest examples in documentation +* Type checking via pyright + +Coverage targets: + +* >95% line coverage for source code +* 100% coverage of public API surface +* All documented examples tested via doctest + +Documentation Organization +=============================================================================== + +Documentation Structure +------------------------------------------------------------------------------- + +Project documentation resides in ``documentation/``: + +.. code-block:: + + documentation/ + ├── index.rst # Documentation home + ├── architecture/ # Architecture documentation + │ ├── index.rst # Architecture overview + │ ├── summary.rst # System architecture summary + │ ├── filesystem.rst # This file + │ ├── decisions/ # Architectural decision records (ADRs) + │ │ └── index.rst # ADR index + │ ├── designs/ # Detailed design documents + │ │ └── index.rst # Design documents index + │ └── testplans/ # Test planning documentation + │ ├── index.rst # Test plans index + │ └── summary.rst # Test coverage summary + ├── examples/ # Usage examples + │ ├── index.rst # Examples overview + │ ├── classes.rst # Immutable classes examples + │ ├── dictionaries.rst # Dictionary examples + │ ├── namespaces.rst # Namespace examples + │ ├── sequences.rs # Sequence utilities examples + │ └── modules.rst # Module examples + ├── prd.rst # Product requirements document + └── contribution.rst # Contribution guidelines + +Documentation Types +------------------------------------------------------------------------------- + +**API Documentation**: + +* Generated from source code docstrings +* Uses Sphinx with autodoc extension +* Includes type hints and examples +* Available at package documentation site + +**Architecture Documentation**: + +* High-level system design +* Component relationships +* Architectural decision records +* Design patterns and rationale + +**Examples Documentation**: + +* Practical usage examples +* Common patterns and idioms +* Migration guides +* Tested via doctest + +**Requirements Documentation**: + +* Product requirements (prd.rst) +* Feature specifications +* Success criteria +* Constraints and assumptions + +Development Workspace +=============================================================================== + +Development-specific files are organized in ``.auxiliary/``: + +.. code-block:: + + .auxiliary/ + ├── notes/ # Development notes and session state + │ ├── todo.md # Current development TODOs + │ └── session-*.md # Session-specific notes + ├── scribbles/ # Temporary scratch files + │ └── (ephemeral content) # Experiments, debugging artifacts + └── instructions/ # Cached development guidelines + ├── architecture.rst # Architecture documentation guide + ├── nomenclature.rst # Naming conventions guide + ├── nomenclature-latin.rst # Latin-derived vocabulary + ├── nomenclature-germanic.rst # Germanic-derived vocabulary + ├── practices.rst # Development practices guide + ├── requirements.rst # Requirements documentation guide + └── tests.rst # Test development guidelines + +Purpose and Usage +------------------------------------------------------------------------------- + +**Session Continuity**: + +* ``.auxiliary/notes/`` preserves development context across sessions +* Claude Code agents update notes during conversations +* TODO items track remaining work and emergent tasks +* Session notes capture decisions and context + +**Development Resources**: + +* ``.auxiliary/instructions/`` caches commonly-referenced guidelines +* Populated by agentsmgr tool from upstream repositories +* Provides offline access to development standards +* Ensures consistency with project templates + +**Scratch Space**: + +* ``.auxiliary/scribbles/`` for temporary experiments +* Preferred over ``/tmp/`` for project-specific scratch work +* Not committed to version control +* Cleaned up periodically + +Exclusion from Distribution +------------------------------------------------------------------------------- + +The ``.auxiliary/`` directory is excluded from package distributions: + +* Listed in ``.gitignore`` for local development files +* Excluded via ``tool.hatch.build`` configuration in ``pyproject.toml`` +* Not included in source distributions +* Development-specific only, not needed by users + +Configuration Files +=============================================================================== + +Project Configuration +------------------------------------------------------------------------------- + +``pyproject.toml`` + Centralized project configuration following PEP 518/PEP 621: + + * Package metadata (name, version, description, authors) + * Dependencies (runtime and development) + * Build system configuration (hatch) + * Tool configurations (pytest, coverage, ruff, pyright) + * Entry points and optional dependencies + +``README.rst`` + Project overview and quick start: + + * Brief description and key features + * Installation instructions + * Basic usage examples + * Links to documentation + * Contribution guidelines + +``LICENSE.txt`` + Apache License 2.0: + + * Open source license terms + * Copyright information + * Legal permissions and limitations + +Development Tool Configuration +------------------------------------------------------------------------------- + +Tool configurations are centralized in ``pyproject.toml``: + +**Hatch** (``[tool.hatch]``): + +* Build system configuration +* Environment definitions +* Version management +* Distribution settings + +**Pytest** (``[tool.pytest.ini_options]``): + +* Test discovery patterns +* Coverage reporting +* Test execution options +* Fixture configuration + +**Ruff** (``[tool.ruff]``): + +* Linting rules and exclusions +* Code style enforcement +* Import sorting +* Line length and formatting + +**Pyright** (``[tool.pyright]``): + +* Type checking strictness +* Python version targeting +* Type stub paths +* Reportable issues + +**Coverage** (``[tool.coverage]``): + +* Coverage measurement configuration +* Exclusion patterns +* Reporting thresholds +* Branch coverage settings + +Data Resources +=============================================================================== + +The ``data/`` directory (if present) contains resources intended for package +distribution. Currently, frigid does not include data resources, but the +structure supports future additions such as: + +* Configuration templates +* Default settings files +* Static assets (if applicable) +* Resource files accessed via ``importlib.resources`` + Architecture Evolution =============================================================================== diff --git a/documentation/prd.rst b/documentation/prd.rst index 85bf640..3fb816b 100644 --- a/documentation/prd.rst +++ b/documentation/prd.rst @@ -21,7 +21,558 @@ Product Requirements Document ******************************************************************************* -.. todo:: Define product requirements, user stories, and acceptance criteria. +Executive Summary +=============================================================================== -For PRD format and guidance, see the `requirements documentation guide -`_. \ No newline at end of file +Frigid is a Python library that provides practical immutability for Python +data structures and classes. The library addresses the gap between Python's +mutable-by-default design and the need for immutable objects in modern +software development practices. By offering familiar APIs similar to built-in +types (dict, namespace) and flexible integration mechanisms (metaclasses, +decorators), frigid enables developers to adopt immutability gradually and +pragmatically. + +The library targets Python developers who need immutable data structures for +configuration objects, value objects, thread-safe data sharing, and functional +programming patterns, while maintaining compatibility with the broader Python +ecosystem including dataclasses, protocols, and type checking tools. + +Problem Statement +=============================================================================== + +Python's built-in data structures (dict, list, set) and user-defined classes +are mutable by default. While Python provides some immutable types (tuple, +frozenset, str), it lacks comprehensive immutable alternatives for common +use cases: + +**Who experiences the problem:** + +* Python developers building concurrent or distributed systems +* Teams adopting functional programming patterns +* Developers creating configuration management systems +* Library authors providing public APIs with stability guarantees +* Engineers working with shared state across threads or processes + +**When and where it occurs:** + +* Configuration objects that should remain constant after initialization +* Value objects that represent immutable concepts (coordinates, timestamps) +* Shared data structures accessed by multiple threads +* API responses that should not be modified by consumers +* Cache keys that must maintain consistent hash values + +**Impact and consequences:** + +* Unintended mutations cause hard-to-debug errors +* Race conditions in concurrent code from shared mutable state +* Cache invalidation issues from objects changing after hashing +* Defensive copying proliferates throughout codebases +* Lack of compile-time guarantees about object immutability + +**Current workarounds and limitations:** + +* ``types.MappingProxyType`` - read-only view but lacks set operations and + creates indirection +* Manual ``__setattr__`` overrides - error-prone boilerplate for each class +* Converting to tuples - loses named access and type information +* Frozen dataclasses - limited to dataclasses and requires decorator +* Custom implementations - inconsistent behavior across projects + +None of these solutions provide a comprehensive, ergonomic, and consistent +approach to immutability across different Python constructs. + +Goals and Objectives +=============================================================================== + +Primary Objectives +------------------------------------------------------------------------------- + +**GOAL-001: Provide drop-in immutable replacements for common built-in types** + +* Success metric: Users can replace ``dict`` with ``Dictionary`` and + ``types.SimpleNamespace`` with ``Namespace`` with minimal code changes +* Success metric: Immutable versions support all read operations of their + mutable counterparts + +**GOAL-002: Enable conversion of arbitrary classes to immutable variants** + +* Success metric: Developers can make any class immutable using a decorator + or metaclass +* Success metric: Works with dataclasses, protocols, and abstract base classes + +**GOAL-003: Maintain compatibility with Python ecosystem** + +* Success metric: Compatible with type checkers (mypy, pyright) +* Success metric: Works with pickle, copy, and standard introspection tools +* Success metric: Integrates with dataclasses and other decorators + +**GOAL-004: Support gradual adoption** + +* Success metric: Selective mutability allows specific attributes to remain + mutable +* Success metric: Clear migration path from mutable to immutable code +* Success metric: Interoperability with mutable code without defensive copying + +Secondary Objectives +------------------------------------------------------------------------------- + +**GOAL-005: Provide clear error messages for immutability violations** + +* Success metric: Exceptions include attribute/entry names in error messages +* Success metric: Users can quickly identify and fix violations + +**GOAL-006: Minimize performance overhead** + +* Success metric: Immutable operations have comparable performance to mutable + equivalents +* Success metric: Import time and memory overhead remain minimal + +**GOAL-007: Comprehensive documentation and examples** + +* Success metric: All public APIs have complete documentation +* Success metric: Examples cover common use cases +* Success metric: Migration guides assist users transitioning from mutable code + +Target Users +=============================================================================== + +Primary User Personas +------------------------------------------------------------------------------- + +**Backend Python Developer** + +* Experience: 2-5 years with Python +* Needs: Thread-safe data structures, configuration management +* Context: Building web services and APIs +* Pain points: Debugging race conditions, unintended state mutations +* Technical proficiency: Comfortable with decorators, type hints + +**Library Author** + +* Experience: 5+ years with Python +* Needs: Stable public APIs, consistent object behavior +* Context: Publishing open-source or internal libraries +* Pain points: API stability, versioning, backward compatibility +* Technical proficiency: Deep Python knowledge, metaclasses, protocols + +**Data Engineer** + +* Experience: 3-7 years with Python +* Needs: Immutable data pipelines, cacheable results +* Context: ETL processes, data transformations +* Pain points: Cache invalidation, data consistency +* Technical proficiency: Strong with dataclasses, type hints, functional patterns + +**Scientific Computing Developer** + +* Experience: Varied (1-10+ years) +* Needs: Immutable parameters, reproducible computations +* Context: Research, numerical computing, simulations +* Pain points: Parameter tracking, result reproducibility +* Technical proficiency: NumPy, dataclasses, type annotations + +User Needs and Motivations +------------------------------------------------------------------------------- + +* **Correctness**: Prevent accidental mutations that cause bugs +* **Concurrency**: Safe data sharing across threads/processes +* **Performance**: Avoid defensive copying overhead +* **Maintainability**: Clear intent through immutable types +* **Interoperability**: Work with existing Python tools and libraries + +Usage Contexts +------------------------------------------------------------------------------- + +* Web application configuration objects +* API request/response models +* Shared cache keys and values +* Functional programming pipelines +* Thread-safe message passing +* Domain model value objects +* Immutable test fixtures + +Functional Requirements +=============================================================================== + +Immutable Dictionary (Priority: Critical) +------------------------------------------------------------------------------- + +**REQ-001: Standard Immutable Dictionary** + +Priority: Critical + +As a Python developer, I want an immutable dictionary similar to dict so that +I can prevent accidental modifications to my data structures. + +Acceptance Criteria: + +* Initialization from iterables, mappings, and keyword arguments +* All read operations (``__getitem__``, ``get``, ``keys``, ``values``, + ``items``, ``__len__``, ``__contains__``) +* Mutations (``__setitem__``, ``__delitem__``, ``clear``, ``pop``, + ``popitem``, ``update``) raise immutability exceptions +* Supports equality comparison and hashing +* Preserves dict-like repr and iteration order + +**REQ-002: Set Operations on Dictionaries** + +Priority: High + +As a developer working with multiple dictionaries, I want set-like operations +(union, intersection) so that I can combine immutable dictionaries while +maintaining immutability. + +Acceptance Criteria: + +* Union operation (``|``) creates new immutable dictionary +* Intersection operation (``&``) creates new immutable dictionary +* Operations return same type as operands (subclass-aware) +* Type signatures accept both mutable and immutable dictionaries + +**REQ-003: Dictionary with Validation** + +Priority: High + +As a developer creating validated data structures, I want a dictionary that +validates entries on initialization so that I can ensure data integrity. + +Acceptance Criteria: + +* Accepts validator function during initialization +* Validator receives all entries and raises exception on invalid data +* Validation occurs before immutability is enforced +* Clear error messages indicate which entries failed validation + +Immutable Namespace (Priority: Critical) +------------------------------------------------------------------------------- + +**REQ-004: Immutable Namespace Object** + +Priority: Critical + +As a Python developer, I want an immutable namespace similar to +types.SimpleNamespace so that I can create simple immutable objects with +attribute access. + +Acceptance Criteria: + +* Initialization from iterables, mappings, and keyword arguments +* Attribute read access (``__getattr__``) +* Attribute modifications (``__setattr__``, ``__delattr__``) raise exceptions +* Supports equality comparison +* Readable repr showing all attributes + +Immutable Classes (Priority: Critical) +------------------------------------------------------------------------------- + +**REQ-005: Metaclass for Immutable Classes** + +Priority: Critical + +As a library author, I want metaclasses for creating immutable class +hierarchies so that I can build consistent immutable APIs. + +Acceptance Criteria: + +* Metaclass ``Class`` for standard immutable classes +* Metaclass ``Dataclass`` for immutable dataclasses +* Metaclass ``AbstractBaseClass`` compatible with abc.ABCMeta +* Protocol metaclasses for structural typing +* Attributes can be set during ``__init__`` +* Attribute protection activates after ``__init__`` completes + +**REQ-006: Decorator for Immutable Classes** + +Priority: Critical + +As a Python developer, I want decorators to make existing classes immutable +so that I can add immutability without changing class inheritance. + +Acceptance Criteria: + +* ``with_standard_behaviors`` decorator for any class +* ``dataclass_with_standard_behaviors`` combines dataclass and immutability +* Works with existing decorators (property, classmethod, staticmethod) +* Compatible with inheritance hierarchies +* Preserves type hints and docstrings + +**REQ-007: Selective Mutability** + +Priority: High + +As a developer with legacy code, I want to mark specific attributes as +mutable so that I can adopt immutability gradually. + +Acceptance Criteria: + +* Metaclass parameter ``instances_mutables`` lists mutable attributes +* Decorator parameter ``instances_mutables`` lists mutable attributes +* Wildcard (``'*'``) allows all instance attributes to be mutable +* Class attributes remain protected by default +* Clear error messages distinguish protected vs. mutable attributes + +Immutable Modules (Priority: Medium) +------------------------------------------------------------------------------- + +**REQ-008: Immutable Module Type** + +Priority: Medium + +As a library author, I want immutable modules so that I can prevent +modification of module-level constants. + +Acceptance Criteria: + +* ``Module`` class extends types.ModuleType +* Module attributes cannot be modified after ``finalize_module`` call +* Integration with dynadoc for documentation generation +* Compatible with standard module importing + +Utility Functions (Priority: Medium) +------------------------------------------------------------------------------- + +**REQ-009: Sequence Utilities** + +Priority: Medium + +As a Python developer, I want readable utilities for creating immutable +sequences so that my code is more maintainable. + +Acceptance Criteria: + +* ``one(x)`` creates single-item tuple more readably than ``(x,)`` +* Compatible with type checkers +* Minimal performance overhead + +**REQ-010: Builtins Installation** + +Priority: Low + +As a developer, I want to optionally install frigid functions into builtins +so that they are available throughout my application. + +Acceptance Criteria: + +* Installer function adds frigid utilities to builtins +* Opt-in mechanism (not automatic) +* Clear documentation about when to use + +Exception Handling (Priority: Critical) +------------------------------------------------------------------------------- + +**REQ-011: Clear Exception Hierarchy** + +Priority: Critical + +As a developer debugging immutability violations, I want clear exception +messages so that I can quickly identify and fix issues. + +Acceptance Criteria: + +* ``AttributeImmutability`` for attribute violations (inherits AttributeError) +* ``EntryImmutability`` for dictionary entry violations (inherits TypeError) +* ``EntryInvalidity`` for validation failures (inherits ValueError) +* Exception messages include attribute/entry names +* Base exception classes (``Omniexception``, ``Omnierror``) for catching all + frigid exceptions + +Non-Functional Requirements +=============================================================================== + +Performance Requirements +------------------------------------------------------------------------------- + +**NFR-001: Low Overhead** + +* Import time < 100ms on standard hardware +* Immutable dictionary operations within 2x of built-in dict performance +* Attribute access on immutable objects within 1.5x of regular classes +* Memory overhead < 10% compared to mutable equivalents + +**NFR-002: Scalability** + +* Support dictionaries with 1M+ entries without performance degradation +* Support class hierarchies with 10+ levels of inheritance +* Minimal performance impact from attribute protection + +Compatibility Requirements +------------------------------------------------------------------------------- + +**NFR-003: Python Version Support** + +* Support Python 3.10+ (latest stable versions) +* Follow Python's deprecation schedule for older versions +* Test against multiple Python implementations (CPython priority) + +**NFR-004: Type Checking Compatibility** + +* Full type hint coverage for public APIs +* Compatible with mypy, pyright, and other type checkers +* Proper generic type support for containers +* dataclass_transform decorator for dataclass metaclasses + +**NFR-005: Ecosystem Integration** + +* Pickle support for all immutable types +* Copy module compatibility (deepcopy, copy) +* Works with standard introspection (inspect module) +* Compatible with other decorators and metaclasses + +Usability Requirements +------------------------------------------------------------------------------- + +**NFR-006: API Familiarity** + +* Immutable types mirror built-in type interfaces +* Method names follow Python naming conventions +* Consistent behavior with Python's data model +* Familiar initialization patterns + +**NFR-007: Error Messages** + +* Informative exception messages with context +* Clear indication of which attribute/entry caused violation +* Helpful suggestions for common mistakes +* Stack traces point to user code, not library internals + +**NFR-008: Documentation Quality** + +* Comprehensive API documentation for all public symbols +* Practical examples for each major feature +* Migration guides from common patterns +* Performance characteristics documented +* Type hints visible in documentation + +Maintainability Requirements +------------------------------------------------------------------------------- + +**NFR-009: Code Quality** + +* Type hints for all public and internal APIs +* Test coverage > 95% for all modules +* Automated testing on multiple Python versions +* Linting with ruff, type checking with pyright + +**NFR-010: Architectural Clarity** + +* Clear separation between public API and implementation +* Layered architecture documented +* Dependency on stable libraries (classcore, dynadoc) +* Minimal external dependencies + +Reliability Requirements +------------------------------------------------------------------------------- + +**NFR-011: Robustness** + +* Graceful handling of edge cases (empty collections, None values) +* No silent failures or data corruption +* Consistent behavior across Python versions +* Memory safety (no segmentation faults) + +Security Requirements +------------------------------------------------------------------------------- + +**NFR-012: Practical Immutability** + +* Immutability enforced for normal usage patterns +* Clear documentation that circumvention is possible +* Not intended as security boundary +* Protection against accidental modification, not malicious circumvention + +Constraints and Assumptions +=============================================================================== + +Technical Constraints +------------------------------------------------------------------------------- + +* Python language limitations make true immutability impossible +* Must allow attribute setting during ``__init__`` for compatibility +* Cannot prevent all circumvention methods (``object.__setattr__``, etc.) +* Delegation to classcore for core immutability mechanisms + +Dependency Constraints +------------------------------------------------------------------------------- + +* Depends on classcore for class factory and protection mechanisms +* Depends on dynadoc for documentation generation +* Depends on absence for sentinel values +* Depends on typing_extensions for backported type features + +Compatibility Constraints +------------------------------------------------------------------------------- + +* Must work with dataclasses decorator +* Must support Python's pickling protocol +* Must be compatible with metaclass conflicts resolution +* Must work with standard library introspection tools + +Performance Constraints +------------------------------------------------------------------------------- + +* Cannot use runtime code generation (impacts startup time) +* Cannot significantly impact import time +* Memory overhead must remain reasonable for large collections +* Attribute access must remain fast for real-time applications + +Assumptions +------------------------------------------------------------------------------- + +* Users understand Python's object model and attribute access +* Users accept that absolute immutability is impossible in Python +* Development environments support Python 3.10+ +* Type checkers are used as optional tools, not requirements +* Users willing to adopt new APIs for immutability benefits + +Out of Scope +=============================================================================== + +The following features are explicitly excluded from frigid's scope: + +**Security-Hardened Immutability** + +* Frigid does not prevent determined circumvention +* Not suitable as security boundary or sandbox +* Use Python's restricted execution or separate processes for security + +**Deep Freezing of Nested Structures** + +* Frigid does not recursively freeze nested mutable objects +* Users must explicitly create immutable nested structures +* No automatic conversion of mutable contents to immutable + +**Immutable Built-in Collections** + +* No immutable list (use tuple) +* No immutable set (use frozenset) +* Frigid focuses on types not provided by Python standard library + +**Runtime Performance Optimization** + +* No C extensions for performance optimization +* No JIT compilation or bytecode manipulation +* Relies on Python's standard attribute access mechanisms + +**Immutability Analysis Tools** + +* No static analysis for detecting mutations +* No linting rules for enforcing immutability +* Users should use type checkers for static guarantees + +**Automatic Migration Tools** + +* No automated refactoring from mutable to immutable code +* No codemod tools for converting existing code +* Users perform manual migration using documentation + +**Immutable I/O or External Resources** + +* No immutable file handles or network connections +* No immutable database connections +* Scope limited to in-memory data structures + +**Thread Synchronization Primitives** + +* No locks, semaphores, or other concurrency primitives +* Immutability aids thread safety but does not replace synchronization +* Users must still implement proper concurrent access patterns \ No newline at end of file From 9da3803e682a66ddcb068d1317835405805a8a1a Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Nov 2025 04:34:54 +0000 Subject: [PATCH 3/5] Simplify PRD by removing personas and user story format Remove user personas section and rewrite functional requirements in direct format instead of "As a , I want..." user story style. This makes the PRD more concise and appropriate for an open-source library where the focus is on what the product does rather than specific user personas. Changes: - Remove Target Users section with personas, needs, and usage contexts - Rewrite all functional requirements with direct descriptions - Change "Acceptance Criteria" to "Requirements" - Move priority to requirement title in parentheses - Keep all essential requirement information Co-Authored-By: Claude Sonnet 4.5 --- documentation/prd.rst | 175 +++++++++++------------------------------- 1 file changed, 43 insertions(+), 132 deletions(-) diff --git a/documentation/prd.rst b/documentation/prd.rst index 3fb816b..cc334c0 100644 --- a/documentation/prd.rst +++ b/documentation/prd.rst @@ -133,78 +133,18 @@ Secondary Objectives * Success metric: Examples cover common use cases * Success metric: Migration guides assist users transitioning from mutable code -Target Users -=============================================================================== - -Primary User Personas -------------------------------------------------------------------------------- - -**Backend Python Developer** - -* Experience: 2-5 years with Python -* Needs: Thread-safe data structures, configuration management -* Context: Building web services and APIs -* Pain points: Debugging race conditions, unintended state mutations -* Technical proficiency: Comfortable with decorators, type hints - -**Library Author** - -* Experience: 5+ years with Python -* Needs: Stable public APIs, consistent object behavior -* Context: Publishing open-source or internal libraries -* Pain points: API stability, versioning, backward compatibility -* Technical proficiency: Deep Python knowledge, metaclasses, protocols - -**Data Engineer** - -* Experience: 3-7 years with Python -* Needs: Immutable data pipelines, cacheable results -* Context: ETL processes, data transformations -* Pain points: Cache invalidation, data consistency -* Technical proficiency: Strong with dataclasses, type hints, functional patterns - -**Scientific Computing Developer** - -* Experience: Varied (1-10+ years) -* Needs: Immutable parameters, reproducible computations -* Context: Research, numerical computing, simulations -* Pain points: Parameter tracking, result reproducibility -* Technical proficiency: NumPy, dataclasses, type annotations - -User Needs and Motivations -------------------------------------------------------------------------------- - -* **Correctness**: Prevent accidental mutations that cause bugs -* **Concurrency**: Safe data sharing across threads/processes -* **Performance**: Avoid defensive copying overhead -* **Maintainability**: Clear intent through immutable types -* **Interoperability**: Work with existing Python tools and libraries - -Usage Contexts -------------------------------------------------------------------------------- - -* Web application configuration objects -* API request/response models -* Shared cache keys and values -* Functional programming pipelines -* Thread-safe message passing -* Domain model value objects -* Immutable test fixtures - Functional Requirements =============================================================================== -Immutable Dictionary (Priority: Critical) +Immutable Dictionary ------------------------------------------------------------------------------- -**REQ-001: Standard Immutable Dictionary** - -Priority: Critical +**REQ-001: Standard Immutable Dictionary** (Priority: Critical) -As a Python developer, I want an immutable dictionary similar to dict so that -I can prevent accidental modifications to my data structures. +Provide an immutable dictionary type similar to dict that prevents +modifications after creation. -Acceptance Criteria: +Requirements: * Initialization from iterables, mappings, and keyword arguments * All read operations (``__getitem__``, ``get``, ``keys``, ``values``, @@ -214,47 +154,37 @@ Acceptance Criteria: * Supports equality comparison and hashing * Preserves dict-like repr and iteration order -**REQ-002: Set Operations on Dictionaries** +**REQ-002: Set Operations on Dictionaries** (Priority: High) -Priority: High +Support set-like operations for combining immutable dictionaries. -As a developer working with multiple dictionaries, I want set-like operations -(union, intersection) so that I can combine immutable dictionaries while -maintaining immutability. - -Acceptance Criteria: +Requirements: * Union operation (``|``) creates new immutable dictionary * Intersection operation (``&``) creates new immutable dictionary * Operations return same type as operands (subclass-aware) * Type signatures accept both mutable and immutable dictionaries -**REQ-003: Dictionary with Validation** - -Priority: High +**REQ-003: Dictionary with Validation** (Priority: High) -As a developer creating validated data structures, I want a dictionary that -validates entries on initialization so that I can ensure data integrity. +Provide a dictionary variant that validates entries on initialization. -Acceptance Criteria: +Requirements: * Accepts validator function during initialization * Validator receives all entries and raises exception on invalid data * Validation occurs before immutability is enforced * Clear error messages indicate which entries failed validation -Immutable Namespace (Priority: Critical) +Immutable Namespace ------------------------------------------------------------------------------- -**REQ-004: Immutable Namespace Object** - -Priority: Critical +**REQ-004: Immutable Namespace Object** (Priority: Critical) -As a Python developer, I want an immutable namespace similar to -types.SimpleNamespace so that I can create simple immutable objects with -attribute access. +Provide an immutable namespace type similar to types.SimpleNamespace for +simple immutable objects with attribute access. -Acceptance Criteria: +Requirements: * Initialization from iterables, mappings, and keyword arguments * Attribute read access (``__getattr__``) @@ -262,17 +192,14 @@ Acceptance Criteria: * Supports equality comparison * Readable repr showing all attributes -Immutable Classes (Priority: Critical) +Immutable Classes ------------------------------------------------------------------------------- -**REQ-005: Metaclass for Immutable Classes** +**REQ-005: Metaclass for Immutable Classes** (Priority: Critical) -Priority: Critical +Provide metaclasses for creating immutable class hierarchies. -As a library author, I want metaclasses for creating immutable class -hierarchies so that I can build consistent immutable APIs. - -Acceptance Criteria: +Requirements: * Metaclass ``Class`` for standard immutable classes * Metaclass ``Dataclass`` for immutable dataclasses @@ -281,14 +208,12 @@ Acceptance Criteria: * Attributes can be set during ``__init__`` * Attribute protection activates after ``__init__`` completes -**REQ-006: Decorator for Immutable Classes** - -Priority: Critical +**REQ-006: Decorator for Immutable Classes** (Priority: Critical) -As a Python developer, I want decorators to make existing classes immutable -so that I can add immutability without changing class inheritance. +Provide decorators to make existing classes immutable without changing +inheritance. -Acceptance Criteria: +Requirements: * ``with_standard_behaviors`` decorator for any class * ``dataclass_with_standard_behaviors`` combines dataclass and immutability @@ -296,14 +221,11 @@ Acceptance Criteria: * Compatible with inheritance hierarchies * Preserves type hints and docstrings -**REQ-007: Selective Mutability** +**REQ-007: Selective Mutability** (Priority: High) -Priority: High +Support marking specific attributes as mutable for gradual adoption. -As a developer with legacy code, I want to mark specific attributes as -mutable so that I can adopt immutability gradually. - -Acceptance Criteria: +Requirements: * Metaclass parameter ``instances_mutables`` lists mutable attributes * Decorator parameter ``instances_mutables`` lists mutable attributes @@ -311,63 +233,52 @@ Acceptance Criteria: * Class attributes remain protected by default * Clear error messages distinguish protected vs. mutable attributes -Immutable Modules (Priority: Medium) +Immutable Modules ------------------------------------------------------------------------------- -**REQ-008: Immutable Module Type** - -Priority: Medium +**REQ-008: Immutable Module Type** (Priority: Medium) -As a library author, I want immutable modules so that I can prevent -modification of module-level constants. +Provide immutable module types to prevent modification of module-level +constants. -Acceptance Criteria: +Requirements: * ``Module`` class extends types.ModuleType * Module attributes cannot be modified after ``finalize_module`` call * Integration with dynadoc for documentation generation * Compatible with standard module importing -Utility Functions (Priority: Medium) +Utility Functions ------------------------------------------------------------------------------- -**REQ-009: Sequence Utilities** +**REQ-009: Sequence Utilities** (Priority: Medium) -Priority: Medium +Provide readable utilities for creating immutable sequences. -As a Python developer, I want readable utilities for creating immutable -sequences so that my code is more maintainable. - -Acceptance Criteria: +Requirements: * ``one(x)`` creates single-item tuple more readably than ``(x,)`` * Compatible with type checkers * Minimal performance overhead -**REQ-010: Builtins Installation** - -Priority: Low +**REQ-010: Builtins Installation** (Priority: Low) -As a developer, I want to optionally install frigid functions into builtins -so that they are available throughout my application. +Support optional installation of frigid functions into builtins. -Acceptance Criteria: +Requirements: * Installer function adds frigid utilities to builtins * Opt-in mechanism (not automatic) * Clear documentation about when to use -Exception Handling (Priority: Critical) +Exception Handling ------------------------------------------------------------------------------- -**REQ-011: Clear Exception Hierarchy** - -Priority: Critical +**REQ-011: Clear Exception Hierarchy** (Priority: Critical) -As a developer debugging immutability violations, I want clear exception -messages so that I can quickly identify and fix issues. +Provide clear exception hierarchy for debugging immutability violations. -Acceptance Criteria: +Requirements: * ``AttributeImmutability`` for attribute violations (inherits AttributeError) * ``EntryImmutability`` for dictionary entry violations (inherits TypeError) From 5390e6f477f267e27cef5fb7f964c037489ff67f Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Nov 2025 05:12:43 +0000 Subject: [PATCH 4/5] Refine architecture documentation based on feedback Simplify and improve documentation based on review feedback: Documentation Organization: - Remove redundant module descriptions from summary.rst - Point to filesystem.rst for detailed module information - Condense Configuration Files section - Remove Data Resources section (not applicable) - Simplify Development Workspace section (show only subdirectories) Terminology: - Use "the package" instead of "Frigid" for maintainability - Remove incorrect claim about classcore having optimized C code Requirements Updates: - Remove performance requirements from PRD (NFR-001, NFR-002) - Remove pickle/copy support claims pending verification - Renumber remaining NFRs sequentially - Remove performance constraints section - Add verification task to .auxiliary/notes/todo.md The documentation is now more concise, accurate, and maintainable while retaining all essential architectural information. Co-Authored-By: Claude Sonnet 4.5 --- .auxiliary/notes/todo.md | 10 ++ documentation/architecture/filesystem.rst | 90 ++---------------- documentation/architecture/summary.rst | 106 +++++----------------- documentation/prd.rst | 49 +++------- 4 files changed, 48 insertions(+), 207 deletions(-) create mode 100644 .auxiliary/notes/todo.md diff --git a/.auxiliary/notes/todo.md b/.auxiliary/notes/todo.md new file mode 100644 index 0000000..f6adfed --- /dev/null +++ b/.auxiliary/notes/todo.md @@ -0,0 +1,10 @@ +# Development TODOs + +## Verification Tasks + +- [ ] **Verify pickle/copy support**: Test and verify that all immutable types properly support Python's pickle protocol and copy module operations. Update documentation and requirements once verified. + - Test pickling of Dictionary, ValidatorDictionary, Namespace + - Test pickling of classes created with metaclasses + - Test pickling of classes created with decorators + - Test copy.copy() and copy.deepcopy() operations + - Document any limitations or special considerations diff --git a/documentation/architecture/filesystem.rst b/documentation/architecture/filesystem.rst index fb399e1..cbb1e6c 100644 --- a/documentation/architecture/filesystem.rst +++ b/documentation/architecture/filesystem.rst @@ -414,18 +414,8 @@ Development-specific files are organized in ``.auxiliary/``: .auxiliary/ ├── notes/ # Development notes and session state - │ ├── todo.md # Current development TODOs - │ └── session-*.md # Session-specific notes ├── scribbles/ # Temporary scratch files - │ └── (ephemeral content) # Experiments, debugging artifacts └── instructions/ # Cached development guidelines - ├── architecture.rst # Architecture documentation guide - ├── nomenclature.rst # Naming conventions guide - ├── nomenclature-latin.rst # Latin-derived vocabulary - ├── nomenclature-germanic.rst # Germanic-derived vocabulary - ├── practices.rst # Development practices guide - ├── requirements.rst # Requirements documentation guide - └── tests.rst # Test development guidelines Purpose and Usage ------------------------------------------------------------------------------- @@ -464,85 +454,17 @@ The ``.auxiliary/`` directory is excluded from package distributions: Configuration Files =============================================================================== -Project Configuration -------------------------------------------------------------------------------- - ``pyproject.toml`` - Centralized project configuration following PEP 518/PEP 621: - - * Package metadata (name, version, description, authors) - * Dependencies (runtime and development) - * Build system configuration (hatch) - * Tool configurations (pytest, coverage, ruff, pyright) - * Entry points and optional dependencies + Centralized project configuration following PEP 518/PEP 621 with package + metadata, dependencies, build system (hatch), and tool configurations + (pytest, coverage, ruff, pyright). ``README.rst`` - Project overview and quick start: - - * Brief description and key features - * Installation instructions - * Basic usage examples - * Links to documentation - * Contribution guidelines + Project overview with key features, installation instructions, basic + examples, and contribution guidelines. ``LICENSE.txt`` - Apache License 2.0: - - * Open source license terms - * Copyright information - * Legal permissions and limitations - -Development Tool Configuration -------------------------------------------------------------------------------- - -Tool configurations are centralized in ``pyproject.toml``: - -**Hatch** (``[tool.hatch]``): - -* Build system configuration -* Environment definitions -* Version management -* Distribution settings - -**Pytest** (``[tool.pytest.ini_options]``): - -* Test discovery patterns -* Coverage reporting -* Test execution options -* Fixture configuration - -**Ruff** (``[tool.ruff]``): - -* Linting rules and exclusions -* Code style enforcement -* Import sorting -* Line length and formatting - -**Pyright** (``[tool.pyright]``): - -* Type checking strictness -* Python version targeting -* Type stub paths -* Reportable issues - -**Coverage** (``[tool.coverage]``): - -* Coverage measurement configuration -* Exclusion patterns -* Reporting thresholds -* Branch coverage settings - -Data Resources -=============================================================================== - -The ``data/`` directory (if present) contains resources intended for package -distribution. Currently, frigid does not include data resources, but the -structure supports future additions such as: - -* Configuration templates -* Default settings files -* Static assets (if applicable) -* Resource files accessed via ``importlib.resources`` + Apache License 2.0 with copyright and legal terms. Architecture Evolution =============================================================================== diff --git a/documentation/architecture/summary.rst b/documentation/architecture/summary.rst index 40d483b..827da76 100644 --- a/documentation/architecture/summary.rst +++ b/documentation/architecture/summary.rst @@ -21,11 +21,11 @@ System Overview ******************************************************************************* -Frigid is a Python library that provides immutable data structures and class -behaviors through a layered architecture. The system enforces immutability -at multiple levels - from low-level dictionary implementations to high-level -class decorators - while maintaining compatibility with Python's standard -library patterns and third-party tools like dataclasses. +The package provides immutable data structures and class behaviors through a +layered architecture. The system enforces immutability at multiple levels - +from low-level dictionary implementations to high-level class decorators - +while maintaining compatibility with Python's standard library patterns and +third-party tools like dataclasses. Purpose and Scope =============================================================================== @@ -46,87 +46,23 @@ Major Components The system is organized into distinct layers that build upon each other: -Public API Layer -------------------------------------------------------------------------------- - -**dictionaries.py** - Immutable dictionary implementations with two variants: - - - ``Dictionary``: Standard immutable dictionary similar to dict but frozen - - ``ValidatorDictionary``: Dictionary with validation on initialization - - Provides set operations (union, intersection) not available on MappingProxyType - -**namespaces.py** - Immutable namespace objects similar to ``types.SimpleNamespace`` but with - frozen attributes after creation. - -**classes.py** - Metaclasses and decorators for creating immutable classes: - - - Metaclasses (Class, Dataclass, AbstractBaseClass, ProtocolClass, etc.) - - Base classes (Object, DataclassObject, Protocol variants) - - Decorators (with_standard_behaviors, dataclass_with_standard_behaviors) - -**modules.py** - Immutable module types and utilities for freezing module-level constants - after initialization. - -**sequences.py** - Utility functions for creating immutable sequences, primarily the ``one()`` - function for single-item tuples. - -**exceptions.py** - Exception hierarchy for immutability violations: - - - ``AttributeImmutability``: Raised when modifying immutable attributes - - ``EntryImmutability``: Raised when modifying immutable dictionary entries - - ``EntryInvalidity``: Raised when validation fails - -**installers.py** - Convenience utilities for installing frigid functions into Python builtins. - -Core Implementation Layer -------------------------------------------------------------------------------- - -Located in the ``__`` subpackage (internal implementation): - -**ImmutableDictionary** (``__/dictionaries.py``) - The foundational immutable dictionary class that all other dictionary-based - structures build upon. Subclasses ``dict`` and uses behavioral flags to - enforce immutability after initialization. - -**imports.py** (``__/imports.py``) - Centralized import hub providing all external dependencies through a single - namespace. Primary dependencies include classcore, dynadoc, absence, and - typing_extensions. - -**nomina.py** (``__/nomina.py``) - Type aliases, type variables, and naming utilities used throughout the - package. - -**doctab.py** (``__/doctab.py``) - Documentation fragments table for dynamic documentation generation via - dynadoc. - -**exceptions.py** (``__/exceptions.py``) - Internal exception classes used by the implementation layer. - -Foundation Dependencies -------------------------------------------------------------------------------- +**Public API Layer** + Modules that provide user-facing functionality: dictionaries, namespaces, + classes (metaclasses and decorators), modules, sequences, exceptions, and + installers. See ``architecture/filesystem.rst`` for detailed module + descriptions. -**classcore** - Provides the core class factory mechanism and attribute protection system. - Frigid delegates most low-level immutability enforcement to classcore's - ``standard`` module while providing higher-level API and configuration. +**Core Implementation Layer** + Internal ``__`` subpackage containing ImmutableDictionary, centralized + imports, type aliases, documentation fragments, and internal exceptions. + See ``architecture/filesystem.rst`` for detailed module descriptions. -**dynadoc** - Enables dynamic documentation generation using reusable fragments. All - classes define ``_dynadoc_fragments_`` attributes referencing documentation - strings from the doctab. +**Foundation Dependencies** + External libraries providing core functionality: -**absence** - Provides the ``absent`` sentinel value for distinguishing missing values - from ``None`` in optional parameters. + - **classcore**: Class factory mechanism and attribute protection system + - **dynadoc**: Dynamic documentation generation using reusable fragments + - **absence**: Sentinel value for distinguishing missing values from ``None`` Component Relationships =============================================================================== @@ -348,16 +284,16 @@ Compatibility * Works with dataclasses and other decorators * Compatible with protocols and abstract base classes -* Supports pickling and standard Python introspection +* Supports standard Python introspection * Respects existing Python conventions Performance ------------------------------------------------------------------------------- * Centralized imports reduce per-module import overhead -* Delegation to classcore leverages optimized C code where available * Minimal runtime overhead beyond Python's standard attribute access * No runtime code generation or bytecode manipulation +* Delegation to classcore for efficient attribute protection System Constraints =============================================================================== diff --git a/documentation/prd.rst b/documentation/prd.rst index cc334c0..dbf4640 100644 --- a/documentation/prd.rst +++ b/documentation/prd.rst @@ -103,7 +103,7 @@ Primary Objectives **GOAL-003: Maintain compatibility with Python ecosystem** * Success metric: Compatible with type checkers (mypy, pyright) -* Success metric: Works with pickle, copy, and standard introspection tools +* Success metric: Works with standard introspection tools * Success metric: Integrates with dataclasses and other decorators **GOAL-004: Support gradual adoption** @@ -290,63 +290,45 @@ Requirements: Non-Functional Requirements =============================================================================== -Performance Requirements -------------------------------------------------------------------------------- - -**NFR-001: Low Overhead** - -* Import time < 100ms on standard hardware -* Immutable dictionary operations within 2x of built-in dict performance -* Attribute access on immutable objects within 1.5x of regular classes -* Memory overhead < 10% compared to mutable equivalents - -**NFR-002: Scalability** - -* Support dictionaries with 1M+ entries without performance degradation -* Support class hierarchies with 10+ levels of inheritance -* Minimal performance impact from attribute protection - Compatibility Requirements ------------------------------------------------------------------------------- -**NFR-003: Python Version Support** +**NFR-001: Python Version Support** * Support Python 3.10+ (latest stable versions) * Follow Python's deprecation schedule for older versions * Test against multiple Python implementations (CPython priority) -**NFR-004: Type Checking Compatibility** +**NFR-002: Type Checking Compatibility** * Full type hint coverage for public APIs * Compatible with mypy, pyright, and other type checkers * Proper generic type support for containers * dataclass_transform decorator for dataclass metaclasses -**NFR-005: Ecosystem Integration** +**NFR-003: Ecosystem Integration** -* Pickle support for all immutable types -* Copy module compatibility (deepcopy, copy) * Works with standard introspection (inspect module) * Compatible with other decorators and metaclasses Usability Requirements ------------------------------------------------------------------------------- -**NFR-006: API Familiarity** +**NFR-004: API Familiarity** * Immutable types mirror built-in type interfaces * Method names follow Python naming conventions * Consistent behavior with Python's data model * Familiar initialization patterns -**NFR-007: Error Messages** +**NFR-005: Error Messages** * Informative exception messages with context * Clear indication of which attribute/entry caused violation * Helpful suggestions for common mistakes * Stack traces point to user code, not library internals -**NFR-008: Documentation Quality** +**NFR-006: Documentation Quality** * Comprehensive API documentation for all public symbols * Practical examples for each major feature @@ -357,14 +339,14 @@ Usability Requirements Maintainability Requirements ------------------------------------------------------------------------------- -**NFR-009: Code Quality** +**NFR-007: Code Quality** * Type hints for all public and internal APIs * Test coverage > 95% for all modules * Automated testing on multiple Python versions * Linting with ruff, type checking with pyright -**NFR-010: Architectural Clarity** +**NFR-008: Architectural Clarity** * Clear separation between public API and implementation * Layered architecture documented @@ -374,7 +356,7 @@ Maintainability Requirements Reliability Requirements ------------------------------------------------------------------------------- -**NFR-011: Robustness** +**NFR-009: Robustness** * Graceful handling of edge cases (empty collections, None values) * No silent failures or data corruption @@ -384,7 +366,7 @@ Reliability Requirements Security Requirements ------------------------------------------------------------------------------- -**NFR-012: Practical Immutability** +**NFR-010: Practical Immutability** * Immutability enforced for normal usage patterns * Clear documentation that circumvention is possible @@ -414,18 +396,9 @@ Compatibility Constraints ------------------------------------------------------------------------------- * Must work with dataclasses decorator -* Must support Python's pickling protocol * Must be compatible with metaclass conflicts resolution * Must work with standard library introspection tools -Performance Constraints -------------------------------------------------------------------------------- - -* Cannot use runtime code generation (impacts startup time) -* Cannot significantly impact import time -* Memory overhead must remain reasonable for large collections -* Attribute access must remain fast for real-time applications - Assumptions ------------------------------------------------------------------------------- From 9567e38422d1c53ba8d2a0cc11cb0f0858c34181 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 13 Nov 2025 05:34:24 +0000 Subject: [PATCH 5/5] Move test organization to testplans and simplify documentation structure Reorganize documentation to reduce redundancy and improve clarity: Test Organization: - Move test structure, naming conventions, and coverage targets to documentation/architecture/testplans/index.rst - Replace detailed test section in filesystem.rst with brief reference to testplans/index.rst - Eliminate duplication between filesystem.rst and testplans documentation Documentation Structure: - Simplify documentation tree structure in filesystem.rst - Remove individual examples file listing, replace with single line - Reorder documentation/ tree to show top-level files first These changes make the documentation more maintainable by keeping test information in one authoritative location and reducing unnecessary detail in the filesystem overview. Co-Authored-By: Claude Sonnet 4.5 --- documentation/architecture/filesystem.rst | 81 ++----------------- .../architecture/testplans/index.rst | 36 ++++++++- 2 files changed, 42 insertions(+), 75 deletions(-) diff --git a/documentation/architecture/filesystem.rst b/documentation/architecture/filesystem.rst index cbb1e6c..494faab 100644 --- a/documentation/architecture/filesystem.rst +++ b/documentation/architecture/filesystem.rst @@ -280,66 +280,9 @@ The package uses dynadoc for dynamic documentation generation: Test Organization =============================================================================== -Test Structure -------------------------------------------------------------------------------- - -Tests mirror the source package structure: - -.. code-block:: - - tests/ - ├── test_000_modules/ # Module-level tests - │ ├── test_010_classes.py # Tests for classes.py - │ ├── test_020_dictionaries.py # Tests for dictionaries.py - │ ├── test_030_namespaces.py # Tests for namespaces.py - │ ├── test_040_sequences.py # Tests for sequences.py - │ └── test_050_modules.py # Tests for modules.py - ├── test_100_edge_cases/ # Edge case and integration tests - └── fixtures/ # Shared test fixtures - -This organization follows the `test development guidelines -`_. - -Test Naming Conventions -------------------------------------------------------------------------------- - -**File naming**: ``test__.py`` - -* Priority indicates test execution order (000, 010, 020, etc.) -* Module name matches the source module being tested - -**Test function naming**: ``test__`` - -* Number indicates test execution order within file -* Description uses snake_case and clearly states what is tested - -**Example**: - -.. code-block:: python - - # In tests/test_000_modules/test_020_dictionaries.py - def test_010_dictionary_initialization_from_kwargs( ): - ''' Dictionary can be initialized from keyword arguments. ''' - - def test_020_dictionary_prevents_modification( ): - ''' Dictionary raises exception on modification attempt. ''' - -Test Coverage -------------------------------------------------------------------------------- - -The test suite aims for comprehensive coverage: - -* Unit tests for all public APIs -* Edge case tests for boundary conditions -* Integration tests for component interactions -* Doctest examples in documentation -* Type checking via pyright - -Coverage targets: - -* >95% line coverage for source code -* 100% coverage of public API surface -* All documented examples tested via doctest +Tests mirror the source package structure and follow project naming conventions. +For detailed information about test structure, naming conventions, and coverage +targets, see ``architecture/testplans/index.rst``. Documentation Organization =============================================================================== @@ -353,26 +296,16 @@ Project documentation resides in ``documentation/``: documentation/ ├── index.rst # Documentation home + ├── prd.rst # Product requirements document + ├── contribution.rst # Contribution guidelines ├── architecture/ # Architecture documentation │ ├── index.rst # Architecture overview │ ├── summary.rst # System architecture summary │ ├── filesystem.rst # This file - │ ├── decisions/ # Architectural decision records (ADRs) - │ │ └── index.rst # ADR index + │ ├── decisions/ # Architectural decision records │ ├── designs/ # Detailed design documents - │ │ └── index.rst # Design documents index │ └── testplans/ # Test planning documentation - │ ├── index.rst # Test plans index - │ └── summary.rst # Test coverage summary - ├── examples/ # Usage examples - │ ├── index.rst # Examples overview - │ ├── classes.rst # Immutable classes examples - │ ├── dictionaries.rst # Dictionary examples - │ ├── namespaces.rst # Namespace examples - │ ├── sequences.rs # Sequence utilities examples - │ └── modules.rst # Module examples - ├── prd.rst # Product requirements document - └── contribution.rst # Contribution guidelines + └── examples/ # Usage examples for each module Documentation Types ------------------------------------------------------------------------------- diff --git a/documentation/architecture/testplans/index.rst b/documentation/architecture/testplans/index.rst index 3db3d71..f7d326c 100644 --- a/documentation/architecture/testplans/index.rst +++ b/documentation/architecture/testplans/index.rst @@ -26,5 +26,39 @@ Test Plans summary +Test Structure +=============================================================================== -.. todo:: Add test plan documents to toctree. \ No newline at end of file +Tests mirror the source package structure: + +.. code-block:: + + tests/ + ├── test_000_modules/ # Module-level tests + │ ├── test_010_classes.py # Tests for classes.py + │ ├── test_020_dictionaries.py # Tests for dictionaries.py + │ ├── test_030_namespaces.py # Tests for namespaces.py + │ ├── test_040_sequences.py # Tests for sequences.py + │ └── test_050_modules.py # Tests for modules.py + ├── test_100_edge_cases/ # Edge case and integration tests + └── fixtures/ # Shared test fixtures + +Naming Conventions +------------------------------------------------------------------------------- + +**File naming**: ``test__.py`` + +* Priority indicates test execution order (000, 010, 020, etc.) +* Module name matches the source module being tested + +**Test function naming**: ``test__`` + +* Number indicates test execution order within file +* Description uses snake_case and clearly states what is tested + +Coverage Targets +------------------------------------------------------------------------------- + +* >95% line coverage for source code +* 100% coverage of public API surface +* All documented examples tested via doctest \ No newline at end of file