diff --git a/.pylintrc b/.pylintrc
deleted file mode 100644
index 7eb5e2c..0000000
--- a/.pylintrc
+++ /dev/null
@@ -1,4 +0,0 @@
-# -*- mode: conf; -*-
-
-[MESSAGES CONTROL]
-disable=fixme
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0e3522c..86872b6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,30 +5,6 @@ All notable changes to Wutta-Continuum will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
-## v0.2.2 (2025-10-29)
-
-### Fix
-
-- exclude user password from continuum versioning
-
-## v0.2.1 (2025-10-29)
-
-### Fix
-
-- add util module, w/ `model_transaction_query()`
-- refactor some more for tests + pylint
-- format all code with black
-
-## v0.2.0 (2024-12-07)
-
-### Feat
-
-- convert all uuid fields from str to proper UUID
-
-### Fix
-
-- add `User.prevent_edit` to schema
-
## v0.1.1 (2024-08-27)
### Fix
diff --git a/README.md b/README.md
index 4f35e92..c7bd996 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Wutta-Continuum
-SQLAlchemy-Continuum versioning for Wutta Framework
+SQLAlchemy-Continuum versioning for WuttJamaican
See docs at https://rattailproject.org/docs/wutta-continuum/
diff --git a/docs/api/wutta_continuum.testing.rst b/docs/api/wutta_continuum.testing.rst
deleted file mode 100644
index 4afca16..0000000
--- a/docs/api/wutta_continuum.testing.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-
-``wutta_continuum.testing``
-===========================
-
-.. automodule:: wutta_continuum.testing
- :members:
diff --git a/docs/api/wutta_continuum.util.rst b/docs/api/wutta_continuum.util.rst
deleted file mode 100644
index c337ddb..0000000
--- a/docs/api/wutta_continuum.util.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-
-``wutta_continuum.util``
-========================
-
-.. automodule:: wutta_continuum.util
- :members:
diff --git a/docs/conf.py b/docs/conf.py
index 330e71f..654920b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -8,36 +8,32 @@
from importlib.metadata import version as get_version
-project = "Wutta-Continuum"
-copyright = "2024, Lance Edgar"
-author = "Lance Edgar"
-release = get_version("Wutta-Continuum")
+project = 'Wutta-Continuum'
+copyright = '2024, Lance Edgar'
+author = 'Lance Edgar'
+release = get_version('Wutta-Continuum')
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = [
- "sphinx.ext.autodoc",
- "sphinx.ext.intersphinx",
- "sphinx.ext.viewcode",
- "sphinx.ext.todo",
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.intersphinx',
+ 'sphinx.ext.viewcode',
+ 'sphinx.ext.todo',
]
-templates_path = ["_templates"]
-exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
+templates_path = ['_templates']
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
intersphinx_mapping = {
- "sqlalchemy": ("http://docs.sqlalchemy.org/en/latest/", None),
- "sqlalchemy-continuum": (
- "https://sqlalchemy-continuum.readthedocs.io/en/latest/",
- None,
- ),
- "wuttjamaican": ("https://docs.wuttaproject.org/wuttjamaican/", None),
+ 'sqlalchemy-continuum': ('https://sqlalchemy-continuum.readthedocs.io/en/latest/', None),
+ 'wuttjamaican': ('https://rattailproject.org/docs/wuttjamaican/', None),
}
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
-html_theme = "furo"
-html_static_path = ["_static"]
+html_theme = 'furo'
+html_static_path = ['_static']
diff --git a/docs/index.rst b/docs/index.rst
index a8f656f..e229883 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -9,12 +9,6 @@ This package adds data versioning/history for `WuttJamaican`_, using
.. _SQLAlchemy-Continuum: https://sqlalchemy-continuum.readthedocs.io/en/latest/
-.. image:: https://img.shields.io/badge/linting-pylint-yellowgreen
- :target: https://github.com/pylint-dev/pylint
-
-.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
- :target: https://github.com/psf/black
-
.. toctree::
:maxdepth: 2
@@ -29,5 +23,3 @@ This package adds data versioning/history for `WuttJamaican`_, using
api/wutta_continuum
api/wutta_continuum.app
api/wutta_continuum.conf
- api/wutta_continuum.testing
- api/wutta_continuum.util
diff --git a/pyproject.toml b/pyproject.toml
index aa500d7..cdae7af 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,10 +6,10 @@ build-backend = "hatchling.build"
[project]
name = "Wutta-Continuum"
-version = "0.2.2"
-description = "SQLAlchemy-Continuum versioning for Wutta Framework"
+version = "0.1.1"
+description = "SQLAlchemy-Continuum versioning for WuttJamaican"
readme = "README.md"
-authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
+authors = [{name = "Lance Edgar", email = "lance@edbob.org"}]
license = {text = "GNU GPL v3+"}
classifiers = [
"Development Status :: 4 - Beta",
@@ -27,13 +27,13 @@ classifiers = [
requires-python = ">= 3.8"
dependencies = [
"SQLAlchemy-Continuum",
- "WuttJamaican[db]>=0.24.1",
+ "WuttJamaican[db]",
]
[project.optional-dependencies]
docs = ["Sphinx", "furo"]
-tests = ["pylint", "pytest", "pytest-cov", "tox"]
+tests = ["pytest-cov", "tox"]
[project.entry-points."wutta.app.providers"]
@@ -47,7 +47,6 @@ wutta_continuum = "wutta_continuum.conf:WuttaContinuumConfigExtension"
[project.urls]
Homepage = "https://wuttaproject.org/"
Repository = "https://forgejo.wuttaproject.org/wutta/wutta-continuum"
-Issues = "https://forgejo.wuttaproject.org/wutta/wutta-continuum/issues"
Changelog = "https://forgejo.wuttaproject.org/wutta/wutta-continuum/src/branch/master/CHANGELOG.md"
diff --git a/src/wutta_continuum/__init__.py b/src/wutta_continuum/__init__.py
index 60e7ad2..63f63ff 100644
--- a/src/wutta_continuum/__init__.py
+++ b/src/wutta_continuum/__init__.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8; -*-
################################################################################
#
-# Wutta-Continuum -- SQLAlchemy Versioning for Wutta Framework
+# Wutta-Continuum -- SQLAlchemy Versioning for WuttJamaican
# Copyright © 2024 Lance Edgar
#
# This file is part of Wutta Framework.
@@ -21,7 +21,7 @@
#
################################################################################
"""
-Wutta-Continuum -- SQLAlchemy-Continuum versioning for Wutta Framework
+Wutta-Continuum -- SQLAlchemy-Continuum versioning for WuttJamaican
"""
from ._version import __version__
diff --git a/src/wutta_continuum/_version.py b/src/wutta_continuum/_version.py
index f243184..23de4cf 100644
--- a/src/wutta_continuum/_version.py
+++ b/src/wutta_continuum/_version.py
@@ -1,9 +1,6 @@
# -*- coding: utf-8; -*-
-"""
-Package Version
-"""
from importlib.metadata import version
-__version__ = version("Wutta-Continuum")
+__version__ = version('Wutta-Continuum')
diff --git a/src/wutta_continuum/app.py b/src/wutta_continuum/app.py
index 30ab321..a6d55c7 100644
--- a/src/wutta_continuum/app.py
+++ b/src/wutta_continuum/app.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8; -*-
################################################################################
#
-# Wutta-Continuum -- SQLAlchemy Versioning for Wutta Framework
+# Wutta-Continuum -- SQLAlchemy Versioning for WuttJamaican
# Copyright © 2024 Lance Edgar
#
# This file is part of Wutta Framework.
@@ -40,6 +40,5 @@ class WuttaContinuumAppProvider(AppProvider):
This checks the config value as described in
:doc:`/narr/install`; default will be ``False``.
"""
- return self.config.get_bool(
- "wutta_continuum.enable_versioning", usedb=False, default=False
- )
+ return self.config.get_bool('wutta_continuum.enable_versioning',
+ usedb=False, default=False)
diff --git a/src/wutta_continuum/conf.py b/src/wutta_continuum/conf.py
index 1cb3bd7..bdf2d92 100644
--- a/src/wutta_continuum/conf.py
+++ b/src/wutta_continuum/conf.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8; -*-
################################################################################
#
-# Wutta-Continuum -- SQLAlchemy Versioning for Wutta Framework
-# Copyright © 2024-2025 Lance Edgar
+# Wutta-Continuum -- SQLAlchemy Versioning for WuttJamaican
+# Copyright © 2024 Lance Edgar
#
# This file is part of Wutta Framework.
#
@@ -24,6 +24,7 @@
App Configuration
"""
+import datetime
import socket
from sqlalchemy.orm import configure_mappers
@@ -41,57 +42,29 @@ class WuttaContinuumConfigExtension(WuttaConfigExtension):
This adds a startup hook, which can optionally turn on the
SQLAlchemy-Continuum versioning features for the main app DB.
"""
+ key = 'wutta_continuum'
- key = "wutta_continuum"
-
- def startup(self, config): # pylint: disable=empty-docstring
- """
- Perform final configuration setup for app startup.
-
- This will do nothing at all, unless config enables the
- versioning feature. This must be done in config file and not
- in DB settings table:
-
- .. code-block:: ini
-
- [wutta_continuum]
- enable_versioning = true
-
- Once enabled, this method will configure the integration, via
- these steps:
-
- 1. call :func:`sqlalchemy-continuum:sqlalchemy_continuum.make_versioned()`
- 2. call :meth:`wuttjamaican:wuttjamaican.app.AppHandler.get_model()`
- 3. call :func:`sqlalchemy:sqlalchemy.orm.configure_mappers()`
-
- For more about SQLAlchemy-Continuum see
- :doc:`sqlalchemy-continuum:intro`.
- """
+ def startup(self, config):
+ """ """
# only do this if config enables it
- if not config.get_bool(
- "wutta_continuum.enable_versioning", usedb=False, default=False
- ):
+ if not config.get_bool('wutta_continuum.enable_versioning',
+ usedb=False, default=False):
return
# create wutta plugin, to assign user and ip address
- spec = config.get(
- "wutta_continuum.wutta_plugin_spec",
- usedb=False,
- default="wutta_continuum.conf:WuttaContinuumPlugin",
- )
- plugin = load_object(spec)
+ spec = config.get('wutta_continuum.wutta_plugin_spec',
+ usedb=False,
+ default='wutta_continuum.conf:WuttaContinuumPlugin')
+ WuttaPlugin = load_object(spec)
+ # tell sqlalchemy-continuum to do its thing
+ make_versioned(plugins=[WuttaPlugin()])
+
+ # nb. must load the model before configuring mappers
app = config.get_app()
- if "model" in app.__dict__:
- raise RuntimeError("something not right, app already has model")
+ model = app.model
- # let sqlalchemy-continuum do its thing
- make_versioned(plugins=[plugin()])
-
- # must load model *between* prev and next calls
- app.get_model()
-
- # let sqlalchemy do its thing
+ # tell sqlalchemy to do its thing
configure_mappers()
@@ -122,29 +95,24 @@ class WuttaContinuumPlugin(Plugin):
:doc:`sqlalchemy-continuum:plugins`.
"""
- def get_remote_addr( # pylint: disable=empty-docstring,unused-argument
- self, uow, session
- ):
+ def get_remote_addr(self, uow, session):
""" """
host = socket.gethostname()
return socket.gethostbyname(host)
- def get_user_id( # pylint: disable=empty-docstring,unused-argument
- self, uow, session
- ):
+ def get_user_id(self, uow, session):
""" """
- return None
- def transaction_args(self, uow, session): # pylint: disable=empty-docstring
+ def transaction_args(self, uow, session):
""" """
kwargs = {}
remote_addr = self.get_remote_addr(uow, session)
if remote_addr:
- kwargs["remote_addr"] = remote_addr
+ kwargs['remote_addr'] = remote_addr
- user_id = self.get_user_id(uow, session) # pylint: disable=assignment-from-none
+ user_id = self.get_user_id(uow, session)
if user_id:
- kwargs["user_id"] = user_id
+ kwargs['user_id'] = user_id
return kwargs
diff --git a/src/wutta_continuum/db/alembic/versions/0a5f8ac0cd06_add_user_prevent_edit.py b/src/wutta_continuum/db/alembic/versions/0a5f8ac0cd06_add_user_prevent_edit.py
deleted file mode 100644
index b2683e5..0000000
--- a/src/wutta_continuum/db/alembic/versions/0a5f8ac0cd06_add_user_prevent_edit.py
+++ /dev/null
@@ -1,34 +0,0 @@
-"""add user.prevent_edit
-
-Revision ID: 0a5f8ac0cd06
-Revises: 71406251b8e7
-Create Date: 2024-11-24 17:39:57.415425
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-
-
-# revision identifiers, used by Alembic.
-revision: str = "0a5f8ac0cd06"
-down_revision: Union[str, None] = "71406251b8e7"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # user
- op.add_column(
- "user_version",
- sa.Column("prevent_edit", sa.Boolean(), autoincrement=False, nullable=True),
- )
-
-
-def downgrade() -> None:
-
- # user
- op.drop_column("user_version", "prevent_edit")
diff --git a/src/wutta_continuum/db/alembic/versions/71406251b8e7_first_versioning_tables.py b/src/wutta_continuum/db/alembic/versions/71406251b8e7_first_versioning_tables.py
index 13909cb..fe54b41 100644
--- a/src/wutta_continuum/db/alembic/versions/71406251b8e7_first_versioning_tables.py
+++ b/src/wutta_continuum/db/alembic/versions/71406251b8e7_first_versioning_tables.py
@@ -1,296 +1,142 @@
"""first versioning tables
Revision ID: 71406251b8e7
-Revises:
+Revises:
Create Date: 2024-08-27 18:28:31.488291
"""
-
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
-import wuttjamaican.db.util
# revision identifiers, used by Alembic.
-revision: str = "71406251b8e7"
+revision: str = '71406251b8e7'
down_revision: Union[str, None] = None
-branch_labels: Union[str, Sequence[str], None] = ("wutta_continuum",)
+branch_labels: Union[str, Sequence[str], None] = ('wutta_continuum',)
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# transaction
- op.create_table(
- "transaction",
- sa.Column("issued_at", sa.DateTime(), nullable=True),
- sa.Column("id", sa.BigInteger(), autoincrement=True, nullable=False),
- sa.Column("remote_addr", sa.String(length=50), nullable=True),
- sa.Column("user_id", wuttjamaican.db.util.UUID(), nullable=True),
- sa.ForeignKeyConstraint(
- ["user_id"], ["user.uuid"], name=op.f("fk_transaction_user_id_user")
- ),
- sa.PrimaryKeyConstraint("id", name=op.f("pk_transaction")),
- )
- op.create_index(
- op.f("ix_transaction_user_id"), "transaction", ["user_id"], unique=False
- )
+ op.create_table('transaction',
+ sa.Column('issued_at', sa.DateTime(), nullable=True),
+ sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False),
+ sa.Column('remote_addr', sa.String(length=50), nullable=True),
+ sa.Column('user_id', sa.String(length=32), nullable=True),
+ sa.ForeignKeyConstraint(['user_id'], ['user.uuid'], name=op.f('fk_transaction_user_id_user')),
+ sa.PrimaryKeyConstraint('id', name=op.f('pk_transaction'))
+ )
+ op.create_index(op.f('ix_transaction_user_id'), 'transaction', ['user_id'], unique=False)
# person
- op.create_table(
- "person_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column(
- "full_name", sa.String(length=100), autoincrement=False, nullable=True
- ),
- sa.Column(
- "first_name", sa.String(length=50), autoincrement=False, nullable=True
- ),
- sa.Column(
- "middle_name", sa.String(length=50), autoincrement=False, nullable=True
- ),
- sa.Column(
- "last_name", sa.String(length=50), autoincrement=False, nullable=True
- ),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_person_version")
- ),
- )
- op.create_index(
- op.f("ix_person_version_end_transaction_id"),
- "person_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_person_version_operation_type"),
- "person_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- op.f("ix_person_version_transaction_id"),
- "person_version",
- ["transaction_id"],
- unique=False,
- )
+ op.create_table('person_version',
+ sa.Column('uuid', sa.String(length=32), autoincrement=False, nullable=False),
+ sa.Column('full_name', sa.String(length=100), autoincrement=False, nullable=True),
+ sa.Column('first_name', sa.String(length=50), autoincrement=False, nullable=True),
+ sa.Column('middle_name', sa.String(length=50), autoincrement=False, nullable=True),
+ sa.Column('last_name', sa.String(length=50), autoincrement=False, nullable=True),
+ sa.Column('transaction_id', sa.BigInteger(), autoincrement=False, nullable=False),
+ sa.Column('end_transaction_id', sa.BigInteger(), nullable=True),
+ sa.Column('operation_type', sa.SmallInteger(), nullable=False),
+ sa.PrimaryKeyConstraint('uuid', 'transaction_id', name=op.f('pk_person_version'))
+ )
+ op.create_index(op.f('ix_person_version_end_transaction_id'), 'person_version', ['end_transaction_id'], unique=False)
+ op.create_index(op.f('ix_person_version_operation_type'), 'person_version', ['operation_type'], unique=False)
+ op.create_index(op.f('ix_person_version_transaction_id'), 'person_version', ['transaction_id'], unique=False)
# user
- op.create_table(
- "user_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("username", sa.String(length=25), autoincrement=False, nullable=True),
- sa.Column("password", sa.String(length=60), autoincrement=False, nullable=True),
- sa.Column(
- "person_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("active", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint("uuid", "transaction_id", name=op.f("pk_user_version")),
- )
- op.create_index(
- op.f("ix_user_version_end_transaction_id"),
- "user_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_user_version_operation_type"),
- "user_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- op.f("ix_user_version_transaction_id"),
- "user_version",
- ["transaction_id"],
- unique=False,
- )
+ op.create_table('user_version',
+ sa.Column('uuid', sa.String(length=32), autoincrement=False, nullable=False),
+ sa.Column('username', sa.String(length=25), autoincrement=False, nullable=True),
+ sa.Column('password', sa.String(length=60), autoincrement=False, nullable=True),
+ sa.Column('person_uuid', sa.String(length=32), autoincrement=False, nullable=True),
+ sa.Column('active', sa.Boolean(), autoincrement=False, nullable=True),
+ sa.Column('transaction_id', sa.BigInteger(), autoincrement=False, nullable=False),
+ sa.Column('end_transaction_id', sa.BigInteger(), nullable=True),
+ sa.Column('operation_type', sa.SmallInteger(), nullable=False),
+ sa.PrimaryKeyConstraint('uuid', 'transaction_id', name=op.f('pk_user_version'))
+ )
+ op.create_index(op.f('ix_user_version_end_transaction_id'), 'user_version', ['end_transaction_id'], unique=False)
+ op.create_index(op.f('ix_user_version_operation_type'), 'user_version', ['operation_type'], unique=False)
+ op.create_index(op.f('ix_user_version_transaction_id'), 'user_version', ['transaction_id'], unique=False)
# role
- op.create_table(
- "role_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column("notes", sa.Text(), autoincrement=False, nullable=True),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint("uuid", "transaction_id", name=op.f("pk_role_version")),
- )
- op.create_index(
- op.f("ix_role_version_end_transaction_id"),
- "role_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_role_version_operation_type"),
- "role_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- op.f("ix_role_version_transaction_id"),
- "role_version",
- ["transaction_id"],
- unique=False,
- )
+ op.create_table('role_version',
+ sa.Column('uuid', sa.String(length=32), autoincrement=False, nullable=False),
+ sa.Column('name', sa.String(length=100), autoincrement=False, nullable=True),
+ sa.Column('notes', sa.Text(), autoincrement=False, nullable=True),
+ sa.Column('transaction_id', sa.BigInteger(), autoincrement=False, nullable=False),
+ sa.Column('end_transaction_id', sa.BigInteger(), nullable=True),
+ sa.Column('operation_type', sa.SmallInteger(), nullable=False),
+ sa.PrimaryKeyConstraint('uuid', 'transaction_id', name=op.f('pk_role_version'))
+ )
+ op.create_index(op.f('ix_role_version_end_transaction_id'), 'role_version', ['end_transaction_id'], unique=False)
+ op.create_index(op.f('ix_role_version_operation_type'), 'role_version', ['operation_type'], unique=False)
+ op.create_index(op.f('ix_role_version_transaction_id'), 'role_version', ['transaction_id'], unique=False)
# user_x_role
- op.create_table(
- "user_x_role_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column(
- "user_uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=True
- ),
- sa.Column(
- "role_uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=True
- ),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_user_x_role_version")
- ),
- )
- op.create_index(
- op.f("ix_user_x_role_version_end_transaction_id"),
- "user_x_role_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_user_x_role_version_operation_type"),
- "user_x_role_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- op.f("ix_user_x_role_version_transaction_id"),
- "user_x_role_version",
- ["transaction_id"],
- unique=False,
- )
+ op.create_table('user_x_role_version',
+ sa.Column('uuid', sa.String(length=32), autoincrement=False, nullable=False),
+ sa.Column('user_uuid', sa.String(length=32), autoincrement=False, nullable=True),
+ sa.Column('role_uuid', sa.String(length=32), autoincrement=False, nullable=True),
+ sa.Column('transaction_id', sa.BigInteger(), autoincrement=False, nullable=False),
+ sa.Column('end_transaction_id', sa.BigInteger(), nullable=True),
+ sa.Column('operation_type', sa.SmallInteger(), nullable=False),
+ sa.PrimaryKeyConstraint('uuid', 'transaction_id', name=op.f('pk_user_x_role_version'))
+ )
+ op.create_index(op.f('ix_user_x_role_version_end_transaction_id'), 'user_x_role_version', ['end_transaction_id'], unique=False)
+ op.create_index(op.f('ix_user_x_role_version_operation_type'), 'user_x_role_version', ['operation_type'], unique=False)
+ op.create_index(op.f('ix_user_x_role_version_transaction_id'), 'user_x_role_version', ['transaction_id'], unique=False)
# permission
- op.create_table(
- "permission_version",
- sa.Column(
- "role_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=False,
- ),
- sa.Column(
- "permission", sa.String(length=254), autoincrement=False, nullable=False
- ),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "role_uuid",
- "permission",
- "transaction_id",
- name=op.f("pk_permission_version"),
- ),
- )
- op.create_index(
- op.f("ix_permission_version_end_transaction_id"),
- "permission_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_permission_version_operation_type"),
- "permission_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- op.f("ix_permission_version_transaction_id"),
- "permission_version",
- ["transaction_id"],
- unique=False,
- )
+ op.create_table('permission_version',
+ sa.Column('role_uuid', sa.String(length=32), autoincrement=False, nullable=False),
+ sa.Column('permission', sa.String(length=254), autoincrement=False, nullable=False),
+ sa.Column('transaction_id', sa.BigInteger(), autoincrement=False, nullable=False),
+ sa.Column('end_transaction_id', sa.BigInteger(), nullable=True),
+ sa.Column('operation_type', sa.SmallInteger(), nullable=False),
+ sa.PrimaryKeyConstraint('role_uuid', 'permission', 'transaction_id', name=op.f('pk_permission_version'))
+ )
+ op.create_index(op.f('ix_permission_version_end_transaction_id'), 'permission_version', ['end_transaction_id'], unique=False)
+ op.create_index(op.f('ix_permission_version_operation_type'), 'permission_version', ['operation_type'], unique=False)
+ op.create_index(op.f('ix_permission_version_transaction_id'), 'permission_version', ['transaction_id'], unique=False)
def downgrade() -> None:
# permission
- op.drop_index(
- op.f("ix_permission_version_transaction_id"), table_name="permission_version"
- )
- op.drop_index(
- op.f("ix_permission_version_operation_type"), table_name="permission_version"
- )
- op.drop_index(
- op.f("ix_permission_version_end_transaction_id"),
- table_name="permission_version",
- )
- op.drop_table("permission_version")
+ op.drop_index(op.f('ix_permission_version_transaction_id'), table_name='permission_version')
+ op.drop_index(op.f('ix_permission_version_operation_type'), table_name='permission_version')
+ op.drop_index(op.f('ix_permission_version_end_transaction_id'), table_name='permission_version')
+ op.drop_table('permission_version')
# user_x_role
- op.drop_index(
- op.f("ix_user_x_role_version_transaction_id"), table_name="user_x_role_version"
- )
- op.drop_index(
- op.f("ix_user_x_role_version_operation_type"), table_name="user_x_role_version"
- )
- op.drop_index(
- op.f("ix_user_x_role_version_end_transaction_id"),
- table_name="user_x_role_version",
- )
- op.drop_table("user_x_role_version")
+ op.drop_index(op.f('ix_user_x_role_version_transaction_id'), table_name='user_x_role_version')
+ op.drop_index(op.f('ix_user_x_role_version_operation_type'), table_name='user_x_role_version')
+ op.drop_index(op.f('ix_user_x_role_version_end_transaction_id'), table_name='user_x_role_version')
+ op.drop_table('user_x_role_version')
# role
- op.drop_index(op.f("ix_role_version_transaction_id"), table_name="role_version")
- op.drop_index(op.f("ix_role_version_operation_type"), table_name="role_version")
- op.drop_index(op.f("ix_role_version_end_transaction_id"), table_name="role_version")
- op.drop_table("role_version")
+ op.drop_index(op.f('ix_role_version_transaction_id'), table_name='role_version')
+ op.drop_index(op.f('ix_role_version_operation_type'), table_name='role_version')
+ op.drop_index(op.f('ix_role_version_end_transaction_id'), table_name='role_version')
+ op.drop_table('role_version')
# user
- op.drop_index(op.f("ix_user_version_transaction_id"), table_name="user_version")
- op.drop_index(op.f("ix_user_version_operation_type"), table_name="user_version")
- op.drop_index(op.f("ix_user_version_end_transaction_id"), table_name="user_version")
- op.drop_table("user_version")
+ op.drop_index(op.f('ix_user_version_transaction_id'), table_name='user_version')
+ op.drop_index(op.f('ix_user_version_operation_type'), table_name='user_version')
+ op.drop_index(op.f('ix_user_version_end_transaction_id'), table_name='user_version')
+ op.drop_table('user_version')
# person
- op.drop_index(op.f("ix_person_version_transaction_id"), table_name="person_version")
- op.drop_index(op.f("ix_person_version_operation_type"), table_name="person_version")
- op.drop_index(
- op.f("ix_person_version_end_transaction_id"), table_name="person_version"
- )
- op.drop_table("person_version")
+ op.drop_index(op.f('ix_person_version_transaction_id'), table_name='person_version')
+ op.drop_index(op.f('ix_person_version_operation_type'), table_name='person_version')
+ op.drop_index(op.f('ix_person_version_end_transaction_id'), table_name='person_version')
+ op.drop_table('person_version')
# transaction
- op.drop_index(op.f("ix_transaction_user_id"), table_name="transaction")
- op.drop_table("transaction")
+ op.drop_index(op.f('ix_transaction_user_id'), table_name='transaction')
+ op.drop_table('transaction')
diff --git a/src/wutta_continuum/db/alembic/versions/989392cc191d_remove_password.py b/src/wutta_continuum/db/alembic/versions/989392cc191d_remove_password.py
deleted file mode 100644
index 545f75a..0000000
--- a/src/wutta_continuum/db/alembic/versions/989392cc191d_remove_password.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""remove password
-
-Revision ID: 989392cc191d
-Revises: 0a5f8ac0cd06
-Create Date: 2025-10-29 19:42:52.985167
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "989392cc191d"
-down_revision: Union[str, None] = "0a5f8ac0cd06"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # user
- op.drop_column("user_version", "password")
-
-
-def downgrade() -> None:
-
- # user
- op.add_column(
- "user_version",
- sa.Column(
- "password", sa.VARCHAR(length=60), autoincrement=False, nullable=True
- ),
- )
diff --git a/src/wutta_continuum/testing.py b/src/wutta_continuum/testing.py
deleted file mode 100644
index c9229d3..0000000
--- a/src/wutta_continuum/testing.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# Wutta-Continuum -- SQLAlchemy Versioning for Wutta Framework
-# Copyright © 2024-2025 Lance Edgar
-#
-# This file is part of Wutta Framework.
-#
-# Wutta Framework is free software: you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option) any
-# later version.
-#
-# Wutta Framework is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# Wutta Framework. If not, see .
-#
-################################################################################
-"""
-Testing utilities
-"""
-
-import sys
-
-import sqlalchemy_continuum as continuum
-
-from wuttjamaican.testing import DataTestCase
-
-from wutta_continuum.conf import WuttaContinuumConfigExtension
-
-
-class VersionTestCase(DataTestCase):
- """
- Base class for test suites requiring the SQLAlchemy-Continuum
- versioning feature.
-
- This inherits from
- :class:`~wuttjamaican:wuttjamaican.testing.DataTestCase`.
- """
-
- def setUp(self):
- self.setup_versioning()
-
- def setup_versioning(self):
- """
- Do setup tasks relating to this class, as well as its parent(s):
-
- * call :meth:`wuttjamaican:wuttjamaican.testing.DataTestCase.setup_db()`
-
- * this will in turn call :meth:`make_config()`
- """
- self.setup_db()
-
- def tearDown(self):
- self.teardown_versioning()
-
- def teardown_versioning(self):
- """
- Do teardown tasks relating to this class, as well as its parent(s):
-
- * call :func:`sqlalchemy-continuum:sqlalchemy_continuum.remove_versioning()`
- * call :meth:`wuttjamaican:wuttjamaican.testing.DataTestCase.teardown_db()`
- """
- continuum.remove_versioning()
- continuum.versioning_manager.transaction_cls = continuum.TransactionFactory()
- self.teardown_db()
-
- def make_config(self, **kwargs):
- """
- Make and customize the config object.
-
- We override this to explicitly enable the versioning feature.
- """
- config = super().make_config(**kwargs)
- config.setdefault("wutta_continuum.enable_versioning", "true")
-
- # nb. must purge model classes from sys.modules, so they will
- # be reloaded and sqlalchemy-continuum can reconfigure
- if "wuttjamaican.db.model" in sys.modules:
- del sys.modules["wuttjamaican.db.model.batch"]
- del sys.modules["wuttjamaican.db.model.upgrades"]
- del sys.modules["wuttjamaican.db.model.auth"]
- del sys.modules["wuttjamaican.db.model.base"]
- del sys.modules["wuttjamaican.db.model"]
-
- ext = WuttaContinuumConfigExtension()
- ext.startup(config)
- return config
diff --git a/src/wutta_continuum/util.py b/src/wutta_continuum/util.py
deleted file mode 100644
index 4ca64ec..0000000
--- a/src/wutta_continuum/util.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# Wutta-Continuum -- SQLAlchemy Versioning for Wutta Framework
-# Copyright © 2024-2025 Lance Edgar
-#
-# This file is part of Wutta Framework.
-#
-# Wutta Framework is free software: you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option) any
-# later version.
-#
-# Wutta Framework is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# Wutta Framework. If not, see .
-#
-################################################################################
-"""
-SQLAlchemy-Continuum utilities
-"""
-
-import sqlalchemy as sa
-from sqlalchemy import orm
-import sqlalchemy_continuum as continuum
-
-
-OPERATION_TYPES = {
- continuum.Operation.INSERT: "INSERT",
- continuum.Operation.UPDATE: "UPDATE",
- continuum.Operation.DELETE: "DELETE",
-}
-
-
-def render_operation_type(operation_type):
- """
- Render a SQLAlchemy-Continuum ``operation_type`` from a version
- record, for display to user.
-
- :param operation_type: Value of same name from a version record.
- Must be one of:
-
- * :attr:`sqlalchemy_continuum:sqlalchemy_continuum.operation.Operation.INSERT`
- * :attr:`sqlalchemy_continuum:sqlalchemy_continuum.operation.Operation.UPDATE`
- * :attr:`sqlalchemy_continuum:sqlalchemy_continuum.operation.Operation.DELETE`
-
- :returns: Display name for the operation type, as string.
- """
- return OPERATION_TYPES[operation_type]
-
-
-def model_transaction_query(instance, session=None, model_class=None):
- """
- Make a query capable of finding all SQLAlchemy-Continuum
- ``transaction`` records associated with the given model instance.
-
- :param instance: Instance of a versioned :term:`data model`.
-
- :param session: Optional :term:`db session` to use for the query.
- If not specified, will be obtained from the ``instance``.
-
- :param model_class: Optional :term:`data model` class to query.
- If not specified, will be obtained from the ``instance``.
-
- :returns: SQLAlchemy query object. Note that it will *not* have an
- ``ORDER BY`` clause yet.
- """
- if not session:
- session = orm.object_session(instance)
- if not model_class:
- model_class = type(instance)
-
- txncls = continuum.transaction_class(model_class)
- vercls = continuum.version_class(model_class)
-
- query = session.query(txncls).join(
- vercls,
- sa.and_(vercls.uuid == instance.uuid, vercls.transaction_id == txncls.id),
- )
-
- return query
diff --git a/tasks.py b/tasks.py
index c55d669..7e7734b 100644
--- a/tasks.py
+++ b/tasks.py
@@ -15,10 +15,10 @@ def release(c, skip_tests=False):
Release a new version of Wutta-Continuum
"""
if not skip_tests:
- c.run("pytest")
+ c.run('pytest')
- if os.path.exists("dist"):
- shutil.rmtree("dist")
+ if os.path.exists('dist'):
+ shutil.rmtree('dist')
- c.run("python -m build --sdist")
- c.run("twine upload dist/*")
+ c.run('python -m build --sdist')
+ c.run('twine upload dist/*')
diff --git a/tests/test_app.py b/tests/test_app.py
index 4efb525..8d41b25 100644
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -17,5 +17,5 @@ class TestWuttaContinuumAppProvider(DataTestCase):
self.assertFalse(provider.continuum_is_enabled())
# but can be turned on
- self.config.setdefault("wutta_continuum.enable_versioning", "true")
+ self.config.setdefault('wutta_continuum.enable_versioning', 'true')
self.assertTrue(provider.continuum_is_enabled())
diff --git a/tests/test_conf.py b/tests/test_conf.py
index 1ea5d44..1f9236b 100644
--- a/tests/test_conf.py
+++ b/tests/test_conf.py
@@ -4,45 +4,33 @@ import socket
from unittest.mock import patch
-from wuttjamaican.testing import ConfigTestCase, DataTestCase
+from wuttjamaican.testing import DataTestCase
from wutta_continuum import conf as mod
-class TestWuttaContinuumConfigExtension(ConfigTestCase):
+class TestWuttaContinuumConfigExtension(DataTestCase):
def make_extension(self):
return mod.WuttaContinuumConfigExtension()
- def test_startup_without_versioning(self):
+ def test_startup(self):
ext = self.make_extension()
- with patch.object(mod, "make_versioned") as make_versioned:
- with patch.object(mod, "configure_mappers") as configure_mappers:
+
+ with patch.object(mod, 'make_versioned') as make_versioned:
+ with patch.object(mod, 'configure_mappers') as configure_mappers:
+
+ # nothing happens by default
ext.startup(self.config)
make_versioned.assert_not_called()
configure_mappers.assert_not_called()
- def test_startup_with_versioning(self):
- ext = self.make_extension()
- with patch.object(mod, "make_versioned") as make_versioned:
- with patch.object(mod, "configure_mappers") as configure_mappers:
- self.config.setdefault("wutta_continuum.enable_versioning", "true")
+ # but will if we enable it in config
+ self.config.setdefault('wutta_continuum.enable_versioning', 'true')
ext.startup(self.config)
make_versioned.assert_called_once()
configure_mappers.assert_called_once_with()
- def test_startup_with_error(self):
- ext = self.make_extension()
- with patch.object(mod, "make_versioned") as make_versioned:
- with patch.object(mod, "configure_mappers") as configure_mappers:
- self.config.setdefault("wutta_continuum.enable_versioning", "true")
- # nb. it is an error for the model to be loaded prior to
- # calling make_versioned() for sqlalchemy-continuum
- self.app.get_model()
- self.assertRaises(RuntimeError, ext.startup, self.config)
- make_versioned.assert_not_called()
- configure_mappers.assert_not_called()
-
class TestWuttaContinuumPlugin(DataTestCase):
@@ -51,8 +39,8 @@ class TestWuttaContinuumPlugin(DataTestCase):
def test_remote_addr(self):
plugin = self.make_plugin()
- with patch.object(socket, "gethostbyname", return_value="127.0.0.1"):
- self.assertEqual(plugin.get_remote_addr(None, self.session), "127.0.0.1")
+ with patch.object(socket, 'gethostbyname', return_value='127.0.0.1'):
+ self.assertEqual(plugin.get_remote_addr(None, self.session), '127.0.0.1')
def test_user_id(self):
plugin = self.make_plugin()
@@ -60,14 +48,11 @@ class TestWuttaContinuumPlugin(DataTestCase):
def test_transaction_args(self):
plugin = self.make_plugin()
- with patch.object(socket, "gethostbyname", return_value="127.0.0.1"):
- self.assertEqual(
- plugin.transaction_args(None, self.session),
- {"remote_addr": "127.0.0.1"},
- )
+ with patch.object(socket, 'gethostbyname', return_value='127.0.0.1'):
+ self.assertEqual(plugin.transaction_args(None, self.session),
+ {'remote_addr': '127.0.0.1'})
- with patch.object(plugin, "get_user_id", return_value="some-random-uuid"):
- self.assertEqual(
- plugin.transaction_args(None, self.session),
- {"remote_addr": "127.0.0.1", "user_id": "some-random-uuid"},
- )
+ with patch.object(plugin, 'get_user_id', return_value='some-random-uuid'):
+ self.assertEqual(plugin.transaction_args(None, self.session),
+ {'remote_addr': '127.0.0.1',
+ 'user_id': 'some-random-uuid'})
diff --git a/tests/test_util.py b/tests/test_util.py
deleted file mode 100644
index 944c861..0000000
--- a/tests/test_util.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8; -*-
-
-from unittest import TestCase
-
-import sqlalchemy_continuum as continuum
-
-from wutta_continuum import util as mod
-from wutta_continuum.testing import VersionTestCase
-
-
-class TestRenderOperationType(TestCase):
-
- def test_basic(self):
- self.assertEqual(
- mod.render_operation_type(continuum.Operation.INSERT), "INSERT"
- )
- self.assertEqual(
- mod.render_operation_type(continuum.Operation.UPDATE), "UPDATE"
- )
- self.assertEqual(
- mod.render_operation_type(continuum.Operation.DELETE), "DELETE"
- )
-
-
-class TestModelTransactionQuery(VersionTestCase):
-
- def test_basic(self):
- model = self.app.model
-
- user = model.User(username="fred")
- self.session.add(user)
- self.session.commit()
-
- query = mod.model_transaction_query(user)
- self.assertEqual(query.count(), 1)
- txn = query.one()
-
- UserVersion = continuum.version_class(model.User)
- version = self.session.query(UserVersion).one()
- self.assertIs(version.transaction, txn)
diff --git a/tox.ini b/tox.ini
index 460f86b..3e2d218 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,10 +6,6 @@ envlist = py38, py39, py310, py311
extras = tests
commands = pytest {posargs}
-[testenv:pylint]
-basepython = python3.11
-commands = pylint wutta_continuum
-
[testenv:coverage]
basepython = python3.11
commands = pytest --cov=wutta_continuum --cov-report=html --cov-fail-under=100