Compare commits
	
		
			2 commits
		
	
	
		
			0e25cca0ba
			...
			53b35f1f55
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 53b35f1f55 | |||
| 4db3fa5962 | 
					 11 changed files with 290 additions and 14 deletions
				
			
		| 
						 | 
					@ -5,6 +5,14 @@ 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/)
 | 
					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).
 | 
					and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 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)
 | 
					## v0.2.0 (2024-12-07)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Feat
 | 
					### Feat
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								docs/api/wutta_continuum.testing.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								docs/api/wutta_continuum.testing.rst
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``wutta_continuum.testing``
 | 
				
			||||||
 | 
					===========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. automodule:: wutta_continuum.testing
 | 
				
			||||||
 | 
					   :members:
 | 
				
			||||||
							
								
								
									
										6
									
								
								docs/api/wutta_continuum.util.rst
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								docs/api/wutta_continuum.util.rst
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``wutta_continuum.util``
 | 
				
			||||||
 | 
					========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. automodule:: wutta_continuum.util
 | 
				
			||||||
 | 
					   :members:
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@ templates_path = ["_templates"]
 | 
				
			||||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
 | 
					exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
intersphinx_mapping = {
 | 
					intersphinx_mapping = {
 | 
				
			||||||
 | 
					    "sqlalchemy": ("http://docs.sqlalchemy.org/en/latest/", None),
 | 
				
			||||||
    "sqlalchemy-continuum": (
 | 
					    "sqlalchemy-continuum": (
 | 
				
			||||||
        "https://sqlalchemy-continuum.readthedocs.io/en/latest/",
 | 
					        "https://sqlalchemy-continuum.readthedocs.io/en/latest/",
 | 
				
			||||||
        None,
 | 
					        None,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,3 +29,5 @@ This package adds data versioning/history for `WuttJamaican`_, using
 | 
				
			||||||
   api/wutta_continuum
 | 
					   api/wutta_continuum
 | 
				
			||||||
   api/wutta_continuum.app
 | 
					   api/wutta_continuum.app
 | 
				
			||||||
   api/wutta_continuum.conf
 | 
					   api/wutta_continuum.conf
 | 
				
			||||||
 | 
					   api/wutta_continuum.testing
 | 
				
			||||||
 | 
					   api/wutta_continuum.util
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@ build-backend = "hatchling.build"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[project]
 | 
					[project]
 | 
				
			||||||
name = "Wutta-Continuum"
 | 
					name = "Wutta-Continuum"
 | 
				
			||||||
version = "0.2.0"
 | 
					version = "0.2.1"
 | 
				
			||||||
description = "SQLAlchemy-Continuum versioning for Wutta Framework"
 | 
					description = "SQLAlchemy-Continuum versioning for Wutta Framework"
 | 
				
			||||||
readme = "README.md"
 | 
					readme = "README.md"
 | 
				
			||||||
authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
 | 
					authors = [{name = "Lance Edgar", email = "lance@wuttaproject.org"}]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,28 @@ class WuttaContinuumConfigExtension(WuttaConfigExtension):
 | 
				
			||||||
    key = "wutta_continuum"
 | 
					    key = "wutta_continuum"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def startup(self, config):  # pylint: disable=empty-docstring
 | 
					    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`.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        # only do this if config enables it
 | 
					        # only do this if config enables it
 | 
				
			||||||
        if not config.get_bool(
 | 
					        if not config.get_bool(
 | 
				
			||||||
            "wutta_continuum.enable_versioning", usedb=False, default=False
 | 
					            "wutta_continuum.enable_versioning", usedb=False, default=False
 | 
				
			||||||
| 
						 | 
					@ -60,14 +81,17 @@ class WuttaContinuumConfigExtension(WuttaConfigExtension):
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        plugin = load_object(spec)
 | 
					        plugin = load_object(spec)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # tell sqlalchemy-continuum to do its thing
 | 
					        app = config.get_app()
 | 
				
			||||||
 | 
					        if "model" in app.__dict__:
 | 
				
			||||||
 | 
					            raise RuntimeError("something not right, app already has model")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # let sqlalchemy-continuum do its thing
 | 
				
			||||||
        make_versioned(plugins=[plugin()])
 | 
					        make_versioned(plugins=[plugin()])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # nb. must load the model before configuring mappers
 | 
					        # must load model *between* prev and next calls
 | 
				
			||||||
        app = config.get_app()
 | 
					        app.get_model()
 | 
				
			||||||
        model = app.model  # pylint: disable=unused-variable
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # tell sqlalchemy to do its thing
 | 
					        # let sqlalchemy do its thing
 | 
				
			||||||
        configure_mappers()
 | 
					        configure_mappers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										92
									
								
								src/wutta_continuum/testing.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/wutta_continuum/testing.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,92 @@
 | 
				
			||||||
 | 
					# -*- 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					################################################################################
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
							
								
								
									
										85
									
								
								src/wutta_continuum/util.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/wutta_continuum/util.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,85 @@
 | 
				
			||||||
 | 
					# -*- 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					################################################################################
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					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
 | 
				
			||||||
| 
						 | 
					@ -4,33 +4,45 @@ import socket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from unittest.mock import patch
 | 
					from unittest.mock import patch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from wuttjamaican.testing import DataTestCase
 | 
					from wuttjamaican.testing import ConfigTestCase, DataTestCase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from wutta_continuum import conf as mod
 | 
					from wutta_continuum import conf as mod
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestWuttaContinuumConfigExtension(DataTestCase):
 | 
					class TestWuttaContinuumConfigExtension(ConfigTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def make_extension(self):
 | 
					    def make_extension(self):
 | 
				
			||||||
        return mod.WuttaContinuumConfigExtension()
 | 
					        return mod.WuttaContinuumConfigExtension()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_startup(self):
 | 
					    def test_startup_without_versioning(self):
 | 
				
			||||||
        ext = self.make_extension()
 | 
					        ext = self.make_extension()
 | 
				
			||||||
 | 
					 | 
				
			||||||
        with patch.object(mod, "make_versioned") as make_versioned:
 | 
					        with patch.object(mod, "make_versioned") as make_versioned:
 | 
				
			||||||
            with patch.object(mod, "configure_mappers") as configure_mappers:
 | 
					            with patch.object(mod, "configure_mappers") as configure_mappers:
 | 
				
			||||||
 | 
					 | 
				
			||||||
                # nothing happens by default
 | 
					 | 
				
			||||||
                ext.startup(self.config)
 | 
					                ext.startup(self.config)
 | 
				
			||||||
                make_versioned.assert_not_called()
 | 
					                make_versioned.assert_not_called()
 | 
				
			||||||
                configure_mappers.assert_not_called()
 | 
					                configure_mappers.assert_not_called()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # but will if we enable it in config
 | 
					    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")
 | 
					                self.config.setdefault("wutta_continuum.enable_versioning", "true")
 | 
				
			||||||
                ext.startup(self.config)
 | 
					                ext.startup(self.config)
 | 
				
			||||||
                make_versioned.assert_called_once()
 | 
					                make_versioned.assert_called_once()
 | 
				
			||||||
                configure_mappers.assert_called_once_with()
 | 
					                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):
 | 
					class TestWuttaContinuumPlugin(DataTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										40
									
								
								tests/test_util.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								tests/test_util.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					# -*- 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)
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue