diff options
Diffstat (limited to 'src/mailman/database/types.py')
| -rw-r--r-- | src/mailman/database/types.py | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/src/mailman/database/types.py b/src/mailman/database/types.py index ba3d92df4..1984b08b5 100644 --- a/src/mailman/database/types.py +++ b/src/mailman/database/types.py @@ -23,43 +23,70 @@ from __future__ import absolute_import, print_function, unicode_literals __metaclass__ = type __all__ = [ 'Enum', + 'UUID', ] +import uuid -from storm.properties import SimpleProperty -from storm.variables import Variable +from sqlalchemy import Integer +from sqlalchemy.dialects import postgresql +from sqlalchemy.types import TypeDecorator, CHAR -class _EnumVariable(Variable): - """Storm variable for supporting enum types. +class Enum(TypeDecorator): + """Handle Python 3.4 style enums. - To use this, make the database column a INTEGER. + Stores an integer-based Enum as an integer in the database, and + converts it on-the-fly. """ + impl = Integer - def __init__(self, *args, **kws): - self._enum = kws.pop('enum') - super(_EnumVariable, self).__init__(*args, **kws) + def __init__(self, enum, *args, **kw): + self.enum = enum + super(Enum, self).__init__(*args, **kw) - def parse_set(self, value, from_db): + def process_bind_param(self, value, dialect): if value is None: return None - if not from_db: - return value - return self._enum(value) + return value.value - def parse_get(self, value, to_db): + def process_result_value(self, value, dialect): if value is None: return None - if not to_db: - return value - return value.value + return self.enum(value) -class Enum(SimpleProperty): - """Custom type for Storm supporting enums.""" + +class UUID(TypeDecorator): + """Platform-independent GUID type. + + Uses Postgresql's UUID type, otherwise uses + CHAR(32), storing as stringified hex values. - variable_class = _EnumVariable + """ + impl = CHAR - def __init__(self, enum=None): - super(Enum, self).__init__(enum=enum) + def load_dialect_impl(self, dialect): + if dialect.name == 'postgresql': + return dialect.type_descriptor(postgresql.UUID()) + else: + return dialect.type_descriptor(CHAR(32)) + + def process_bind_param(self, value, dialect): + if value is None: + return value + elif dialect.name == 'postgresql': + return str(value) + else: + if not isinstance(value, uuid.UUID): + return "%.32x" % uuid.UUID(value) + else: + # hexstring + return "%.32x" % value + + def process_result_value(self, value, dialect): + if value is None: + return value + else: + return uuid.UUID(value) |
