feat: add support for lane_op and lane_trans DB sessions, models

This commit is contained in:
Lance Edgar 2025-01-24 19:33:34 -06:00
parent bf6bf63e68
commit e6921c8533
6 changed files with 158 additions and 2 deletions

View file

@ -12,8 +12,7 @@ Install the Wutta-COREPOS package to your virtual environment:
pip install Wutta-COREPOS
Edit your :term:`config file` to add CORE-POS DB connection info, and
related settings. Note that so far, only CORE Office DB connections
are supported.
related settings.
.. code-block:: ini
@ -29,4 +28,14 @@ are supported.
[corepos.db.office_arch]
default.url = mysql+mysqlconnector://localhost/trans_archive
[corepos.db.lane_op]
keys = 01, 02
01.url = mysql+mysqlconnector://lane01/opdata
02.url = mysql+mysqlconnector://lane02/opdata
[corepos.db.lane_trans]
keys = 01, 02
01.url = mysql+mysqlconnector://lane01/translog
02.url = mysql+mysqlconnector://lane02/translog
And that's it, the CORE-POS integration is configured.

View file

@ -74,6 +74,34 @@ class WuttaCoreposConfigExtension(WuttaConfigExtension):
Dict of ``office_arch`` DB engines. May be empty if no config
is found; otherwise there should at least be a ``default`` key
defined, corresonding to :data:`core_office_arch_engine`.
.. data:: core_lane_op_engine
Primary engine for the ``lane_op`` DB. May be null if no
"default" engine is configured - which is *typical* for a
multi-lane environment. See :data:`core_lane_op_engines` for
the full set.
.. data:: core_lane_op_engines
Dict of ``lane_op`` DB engines. May be empty if no config is
found; otherwise keys are typically like ``01`` and ``02`` etc.
If present, the ``default`` key will correspond to
:data:`core_lane_op_engine`.
.. data:: core_lane_trans_engine
Primary engine for the ``lane_trans`` DB. May be null if no
"default" engine is configured - which is *typical* for a
multi-lane environment. See :data:`core_lane_trans_engines`
for the full set.
.. data:: core_lane_trans_engines
Dict of ``lane_trans`` DB engines. May be empty if no config
is found; otherwise keys are typically like ``01`` and ``02``
etc. If present, the ``default`` key will correspond to
:data:`core_lane_trans_engine`.
"""
key = 'wutta_corepos'
@ -101,6 +129,20 @@ class WuttaCoreposConfigExtension(WuttaConfigExtension):
config.core_office_arch_engine = engines.get('default')
Session.configure(bind=config.core_office_arch_engine)
# lane_op
from corepos.db.lane_op import Session
engines = get_engines(config, 'corepos.db.lane_op')
config.core_lane_op_engines = engines
config.core_lane_op_engine = engines.get('default')
Session.configure(bind=config.core_lane_op_engine)
# lane_trans
from corepos.db.lane_trans import Session
engines = get_engines(config, 'corepos.db.lane_trans')
config.core_lane_trans_engines = engines
config.core_lane_trans_engine = engines.get('default')
Session.configure(bind=config.core_lane_trans_engine)
# define some schema columns "late" unless not supported
if config.get_bool('corepos.db.office_op.use_latest_columns',
default=True, usedb=False):

View file

@ -60,6 +60,24 @@ class CoreposHandler(GenericHandler):
return model
def get_model_lane_op(self):
"""
Returns the :term:`data model` module for CORE Lane 'op' DB,
i.e. :mod:`pycorepos:corepos.db.lane_op.model`.
"""
from corepos.db.lane_op import model
return model
def get_model_lane_trans(self):
"""
Returns the :term:`data model` module for CORE Lane 'trans'
DB, i.e. :mod:`pycorepos:corepos.db.lane_trans.model`.
"""
from corepos.db.lane_trans import model
return model
def make_session_office_op(self, dbkey='default', **kwargs):
"""
Make a new :term:`db session` for the CORE Office 'op' DB.
@ -99,6 +117,32 @@ class CoreposHandler(GenericHandler):
kwargs['bind'] = self.config.core_office_arch_engines[dbkey]
return Session(**kwargs)
def make_session_lane_op(self, dbkey='default', **kwargs):
"""
Make a new :term:`db session` for the CORE Lane 'op' DB.
:returns: Instance of
:class:`pycorepos:corepos.db.lane_op.Session`.
"""
from corepos.db.lane_op import Session
if 'bind' not in kwargs:
kwargs['bind'] = self.config.core_lane_op_engines[dbkey]
return Session(**kwargs)
def make_session_lane_trans(self, dbkey='default', **kwargs):
"""
Make a new :term:`db session` for the CORE Lane 'trans' DB.
:returns: Instance of
:class:`pycorepos:corepos.db.lane_trans.Session`.
"""
from corepos.db.lane_trans import Session
if 'bind' not in kwargs:
kwargs['bind'] = self.config.core_lane_trans_engines[dbkey]
return Session(**kwargs)
def get_office_url(self, require=False):
"""
Returns the base URL for the CORE Office web app.

View file

@ -49,6 +49,22 @@ in general.
.. class:: ExtraCoreArchSessions
Dict of secondary CORE Office 'arch' DB sessions, if applicable.
.. class:: CoreLaneOpSession
Primary web app :term:`db session` for CORE Lane 'op' DB.
.. class:: CoreLaneTransSession
Primary web app :term:`db session` for CORE Lane 'trans' DB.
.. class:: ExtraCoreLaneOpSessions
Dict of secondary CORE Lane 'op' DB sessions, if applicable.
.. class:: ExtraCoreLaneTransSessions
Dict of secondary CORE Lane 'trans' DB sessions, if applicable.
"""
from sqlalchemy.orm import sessionmaker, scoped_session
@ -64,7 +80,15 @@ register(CoreTransSession)
CoreArchSession = scoped_session(sessionmaker())
register(CoreArchSession)
CoreLaneOpSession = scoped_session(sessionmaker())
register(CoreLaneOpSession)
CoreLaneTransSession = scoped_session(sessionmaker())
register(CoreLaneTransSession)
# nb. these start out empty but may be populated on app startup
ExtraCoreOpSessions = {}
ExtraCoreTransSessions = {}
ExtraCoreArchSessions = {}
ExtraCoreLaneOpSessions = {}
ExtraCoreLaneTransSessions = {}

View file

@ -16,14 +16,21 @@ class TestWuttaCoreposConfigExtension(TestCase):
self.assertFalse(hasattr(config, 'core_office_op_engine'))
self.assertFalse(hasattr(config, 'core_office_trans_engine'))
self.assertFalse(hasattr(config, 'core_office_arch_engine'))
self.assertFalse(hasattr(config, 'core_lane_op_engine'))
self.assertFalse(hasattr(config, 'core_lane_trans_engine'))
ext = mod.WuttaCoreposConfigExtension()
ext.configure(config)
self.assertIsNone(config.core_office_op_engine)
self.assertIsNone(config.core_office_trans_engine)
self.assertIsNone(config.core_office_arch_engine)
self.assertIsNone(config.core_lane_op_engine)
self.assertIsNone(config.core_lane_trans_engine)
# but config can change that
config.setdefault('corepos.db.office_op.default.url', 'sqlite://')
config.setdefault('corepos.db.lane_trans.default.url', 'sqlite://')
ext.configure(config)
self.assertIsNotNone(config.core_office_op_engine)
self.assertEqual(str(config.core_office_op_engine.url), 'sqlite://')
self.assertIsNotNone(config.core_lane_trans_engine)
self.assertEqual(str(config.core_lane_trans_engine.url), 'sqlite://')

View file

@ -34,6 +34,18 @@ class TestCoreposHandler(ConfigTestCase):
arch_model = handler.get_model_office_arch()
self.assertIs(arch_model, model)
def test_get_model_lane_op(self):
from corepos.db.lane_op import model
handler = self.make_handler()
op_model = handler.get_model_lane_op()
self.assertIs(op_model, model)
def test_get_model_lane_trans(self):
from corepos.db.lane_trans import model
handler = self.make_handler()
trans_model = handler.get_model_lane_trans()
self.assertIs(trans_model, model)
def test_make_session_office_op(self):
handler = self.make_handler()
engine = sa.create_engine('sqlite://')
@ -61,6 +73,24 @@ class TestCoreposHandler(ConfigTestCase):
self.assertIsInstance(arch_session, orm.Session)
self.assertIs(arch_session.bind, engine)
def test_make_session_lane_op(self):
handler = self.make_handler()
engine = sa.create_engine('sqlite://')
with patch.object(self.config, 'core_lane_op_engines', create=True,
new={'default': engine}):
op_session = handler.make_session_lane_op()
self.assertIsInstance(op_session, orm.Session)
self.assertIs(op_session.bind, engine)
def test_make_session_lane_trans(self):
handler = self.make_handler()
engine = sa.create_engine('sqlite://')
with patch.object(self.config, 'core_lane_trans_engines', create=True,
new={'default': engine}):
trans_session = handler.make_session_lane_trans()
self.assertIsInstance(trans_session, orm.Session)
self.assertIs(trans_session.bind, engine)
def test_get_office_url(self):
handler = self.make_handler()