diff --git a/db/base.py b/db/base.py index fe17e7905..4da639a20 100644 --- a/db/base.py +++ b/db/base.py @@ -13,6 +13,29 @@ # See the License for the specific language governing permissions and # limitations under the License. # =============================================================================== +""" +db/base.py + +This file defines the foundational components for the SQLAlchemy models. +It includes: +1. The declarative base class (`Base`) that all models will inherit from. +2. A helper function (`lexicon_term`) to create standardized foreign key columns + referencing the `lexicon_term` table. +3. A helper function (`pascal_to_snake`) to convert class names from PascalCase to snake_case + for automatic table naming. +4. Mixins for common functionality: + - `AutoBaseMixin`: Adds automatic table naming and an auto-incrementing primary key. + - `PropertiesMixin`: Adds a JSONB properties column for storing additional attributes. + - `ReleaseMixin`: Adds a release status column referencing the `lexicon_term` table. + - `AuditMixin`: Adds standard audit columns (created_at, created_by, updated_at, updated_by). +5. A simple `User` model for tracking user information in audit columns. +6. Polymorphic helper mixins (`StatusHistoryMixin`, `NotesMixin`, `AttributionMixin`, etc.) + which provide a clean, reusable way to add relationships to the polymorphic + metadata tables. Any model that can have a status history (like Thing or Location) + can simply inherit from the `StatusHistoryMixin` mixin. +7. An `AuditMixin` to add standard audit columns to tables. +""" + from sqlalchemy import ( Column, DateTime, @@ -20,11 +43,15 @@ Integer, JSON, String, - Boolean, - Text, ForeignKey, ) -from sqlalchemy.orm import DeclarativeBase, declared_attr, Mapped, mapped_column +from sqlalchemy.orm import ( + DeclarativeBase, + declared_attr, + Mapped, + mapped_column, + relationship, +) from sqlalchemy_searchable import make_searchable from sqlalchemy_continuum import make_versioned import re @@ -41,6 +68,12 @@ class Base(DeclarativeBase): def lexicon_term(foreignkeykw=None, **kw): + """Create a SQLAlchemy mapped column for a self-referencing lexicon term. + + This helper function simplifies the creation of a string column that also + acts as a foreign key to the 'term' column of the 'lexicon_term' table. + It standardizes the column type to String(100) and sets the onupdate + behavior to "CASCADE".""" fkw = foreignkeykw if foreignkeykw else {} @@ -55,13 +88,18 @@ def pascal_to_snake(name): return re.sub(r"(?