3
0
Fork 0

fix: add db.util.make_topo_sortkey() function

This commit is contained in:
Lance Edgar 2024-12-03 21:53:30 -06:00
parent c3aa97ed27
commit d95b101dbf
2 changed files with 39 additions and 0 deletions

View file

@ -27,6 +27,7 @@ Database Utilities
import uuid as _uuid
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.dialects.postgresql import UUID as PGUUID
from wuttjamaican.util import make_uuid
@ -127,3 +128,26 @@ def uuid_fk_column(target_column, *args, **kwargs):
if not args:
args = (sa.String(length=32), sa.ForeignKey(target_column))
return sa.Column(*args, **kwargs)
def make_topo_sortkey(model):
"""
Returns a function suitable for use as a ``key`` kwarg to a
standard Python sorting call. This key function will expect a
single class mapper and return a sequence number associated with
that model. The sequence is determined by SQLAlchemy's
topological table sorting.
:param model: Usually the :term:`app model`, but can be any module
containing model classes.
"""
metadata = model.Base.metadata
tables = dict([(table.name, i)
for i, table in enumerate(metadata.sorted_tables, 1)])
def sortkey(name):
cls = getattr(model, name)
mapper = orm.class_mapper(cls)
return tuple(tables[t.name] for t in mapper.tables)
return sortkey

View file

@ -11,6 +11,7 @@ try:
from wuttjamaican.db import util as mod
from wuttjamaican.db.model.base import Setting
from wuttjamaican.util import make_true_uuid
from wuttjamaican.testing import DataTestCase
except ImportError:
pass
else:
@ -124,3 +125,17 @@ else:
self.assertIsInstance(column, sa.Column)
self.assertIsInstance(column.type, sa.String)
self.assertEqual(column.type.length, 32)
class TestMakeTopoSortkey(DataTestCase):
def test_basic(self):
model = self.app.model
sortkey = mod.make_topo_sortkey(model)
original = ['User', 'Person', 'UserRole', 'Role']
# models are sorted so dependants come later
result = sorted(original, key=sortkey)
self.assertTrue(result.index('Role') < result.index('UserRole'))
self.assertTrue(result.index('User') < result.index('UserRole'))
self.assertTrue(result.index('Person') < result.index('User'))