]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
fix handling of native enum aliases in sqlalchemy enum columns
authorDaniel Knell <contact@danielknell.co.uk>
Mon, 5 Feb 2018 14:25:47 +0000 (09:25 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 5 Feb 2018 14:27:27 +0000 (09:27 -0500)
Fixed bug where the :class:`.Enum` type wouldn't handle
enum "aliases" correctly, when more than one key refers to the
same value.  Pull request courtesy Daniel Knell.

Fixes: #4180
Change-Id: Ia716c00ca6c67aeab56965f0fdd575ecb7c71416
Pull-request: https://github.com/zzzeek/sqlalchemy/pull/420

doc/build/changelog/unreleased_12/4180.rst [new file with mode: 0644]
lib/sqlalchemy/sql/sqltypes.py
test/sql/test_types.py

diff --git a/doc/build/changelog/unreleased_12/4180.rst b/doc/build/changelog/unreleased_12/4180.rst
new file mode 100644 (file)
index 0000000..01d8ee0
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 4180
+
+    Fixed bug where the :class:`.Enum` type wouldn't handle
+    enum "aliases" correctly, when more than one key refers to the
+    same value.  Pull request courtesy Daniel Knell.
+
index e11a59dacfd6153792a0de98fc07e49deaf2e75c..ac915c73a90ced01eaa73202bcb2641aaca40cf8 100644 (file)
@@ -1352,15 +1352,18 @@ class Enum(Emulated, String, SchemaType):
         self.enums = list(values)
 
         self._valid_lookup = dict(
-            zip(objects, values)
+            zip(reversed(objects), reversed(values))
         )
+
         self._object_lookup = dict(
-            (value, key) for key, value in self._valid_lookup.items()
-        )
-        self._valid_lookup.update(
-            [(value, value) for value in self._valid_lookup.values()]
+            zip(values, objects)
         )
 
+        self._valid_lookup.update([
+            (value, self._valid_lookup[self._object_lookup[value]])
+            for value in values
+        ])
+
     @property
     def native(self):
         return self.native_enum
index dd799de1b5b338d1bfbbe900f2ef3f5bfeefe2d7..fa917c466bc22ae62c0b7a3554f6097a18c96a5c 100644 (file)
@@ -1161,15 +1161,18 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
         # Implements PEP 435 in the minimal fashion needed by SQLAlchemy
         __members__ = OrderedDict()
 
-        def __init__(self, name, value):
+        def __init__(self, name, value, alias=None):
             self.name = name
             self.value = value
             self.__members__[name] = self
             setattr(self.__class__, name, self)
+            if alias:
+                self.__members__[alias] = self
+                setattr(self.__class__, alias, self)
 
     one = SomeEnum('one', 1)
     two = SomeEnum('two', 2)
-    three = SomeEnum('three', 3)
+    three = SomeEnum('three', 3, 'four')
 
     @classmethod
     def define_tables(cls, metadata):
@@ -1498,6 +1501,10 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
             {'id': 1, 'someenum': self.SomeEnum.two},
             {'id': 2, 'someenum': self.SomeEnum.two},
             {'id': 3, 'someenum': self.SomeEnum.one},
+            {'id': 4, 'someenum': self.SomeEnum.three},
+            {'id': 5, 'someenum': self.SomeEnum.four},
+            {'id': 6, 'someenum': 'three'},
+            {'id': 7, 'someenum': 'four'},
         ])
 
         eq_(
@@ -1507,6 +1514,10 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
                 (1, self.SomeEnum.two),
                 (2, self.SomeEnum.two),
                 (3, self.SomeEnum.one),
+                (4, self.SomeEnum.three),
+                (5, self.SomeEnum.three),
+                (6, self.SomeEnum.three),
+                (7, self.SomeEnum.three),
             ]
         )
 
@@ -1533,7 +1544,7 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
         is_(e1.adapt(Enum).metadata, e1.metadata)
         e1 = Enum(self.SomeEnum)
         eq_(e1.adapt(ENUM).name, 'someenum')
-        eq_(e1.adapt(ENUM).enums, ['one', 'two', 'three'])
+        eq_(e1.adapt(ENUM).enums, ['one', 'two', 'three', 'four'])
 
     @testing.provide_metadata
     def test_create_metadata_bound_no_crash(self):