from .. import util
from ..util import compat
from ..util import langhelpers
+from ..util import OrderedDict
from ..util import pickle
.. versionadded:: 1.3.8
+ :param omit_aliases: A boolean that when true will remove aliases from
+ pep 435 enums. For backward compatibility it defaults to ``False``.
+ A deprecation warning is raised if the enum has aliases and this
+ flag was not set.
+ .. versionadded:: 1.4.4
+
+ .. deprecated:: 1.4 The default will be changed to ``True`` in
+ SQLAlchemy 2.0.
"""
self._enum_init(enums, kw)
self.values_callable = kw.pop("values_callable", None)
self._sort_key_function = kw.pop("sort_key_function", NO_ARG)
length_arg = kw.pop("length", NO_ARG)
+ self._omit_aliases = kw.pop("omit_aliases", NO_ARG)
values, objects = self._parse_into_values(enums, kw)
self._setup_for_values(values, objects, kw)
if len(enums) == 1 and hasattr(enums[0], "__members__"):
self.enum_class = enums[0]
- members = self.enum_class.__members__
+
+ _members = self.enum_class.__members__
+
+ aliases = [n for n, v in _members.items() if v.name != n]
+ if self._omit_aliases is NO_ARG and aliases:
+ util.warn_deprecated_20(
+ "The provided enum %s contains the aliases %s. The "
+ "``omit_aliases`` will default to ``True`` in SQLAlchemy "
+ "2.0. Specify a value to silence this warning."
+ % (self.enum_class.__name__, aliases)
+ )
+ if self._omit_aliases is True:
+ # remove aliases
+ members = OrderedDict(
+ (n, v) for n, v in _members.items() if v.name == n
+ )
+ else:
+ members = _members
if self.values_callable:
values = self.values_callable(self.enum_class)
else:
kw.setdefault("values_callable", self.values_callable)
kw.setdefault("create_constraint", self.create_constraint)
kw.setdefault("length", self.length)
+ kw.setdefault("omit_aliases", self._omit_aliases)
assert "_enums" in kw
return impltype(**kw)
from sqlalchemy.testing import AssertsExecutionResults
from sqlalchemy.testing import engines
from sqlalchemy.testing import eq_
+from sqlalchemy.testing import expect_deprecated_20
from sqlalchemy.testing import expect_warnings
from sqlalchemy.testing import fixtures
from sqlalchemy.testing import is_
"stdlib_enum_table",
metadata,
Column("id", Integer, primary_key=True),
- Column("someenum", Enum(cls.SomeEnum, create_constraint=True)),
+ Column(
+ "someenum",
+ Enum(cls.SomeEnum, create_constraint=True, omit_aliases=False),
+ ),
+ )
+ Table(
+ "stdlib_enum_table_no_alias",
+ metadata,
+ Column("id", Integer, primary_key=True),
+ Column(
+ "someenum",
+ Enum(
+ cls.SomeEnum,
+ create_constraint=True,
+ omit_aliases=True,
+ name="someenum_no_alias",
+ ),
+ ),
)
Table(
)
def test_python_type(self):
- eq_(types.Enum(self.SomeEnum).python_type, self.SomeEnum)
+ eq_(types.Enum(self.SomeOtherEnum).python_type, self.SomeOtherEnum)
def test_pickle_types(self):
global SomeEnum
for loads, dumps in picklers():
column_types = [
Column("Enu", Enum("x", "y", "z", name="somename")),
- Column("En2", Enum(self.SomeEnum)),
+ Column("En2", Enum(self.SomeEnum, omit_aliases=False)),
]
for column_type in column_types:
meta = MetaData()
loads(dumps(meta))
def test_validators_pep435(self):
- type_ = Enum(self.SomeEnum)
- validate_type = Enum(self.SomeEnum, validate_strings=True)
+ type_ = Enum(self.SomeEnum, omit_aliases=False)
+ validate_type = Enum(
+ self.SomeEnum, validate_strings=True, omit_aliases=False
+ )
bind_processor = type_.bind_processor(testing.db.dialect)
bind_processor_validates = validate_type.bind_processor(
self.a_member,
self.b_member,
)
- typ = Enum(self.SomeEnum)
+ typ = Enum(self.SomeEnum, omit_aliases=False)
is_(typ.sort_key_function.__func__, typ._db_value_for_elem.__func__)
def sort_enum_key_value(value):
return str(value.value)
- typ = Enum(self.SomeEnum, sort_key_function=sort_enum_key_value)
+ typ = Enum(
+ self.SomeEnum,
+ sort_key_function=sort_enum_key_value,
+ omit_aliases=False,
+ )
is_(typ.sort_key_function, sort_enum_key_value)
eq_(
)
def test_pep435_no_sort_key(self):
- typ = Enum(self.SomeEnum, sort_key_function=None)
+ typ = Enum(self.SomeEnum, sort_key_function=None, omit_aliases=False)
is_(typ.sort_key_function, None)
def test_pep435_enum_round_trip(self, connection):
eq_(e1.adapt(Enum).name, "foo")
eq_(e1.adapt(Enum).schema, "bar")
is_(e1.adapt(Enum).metadata, e1.metadata)
- e1 = Enum(self.SomeEnum)
+ e1 = Enum(self.SomeEnum, omit_aliases=False)
eq_(e1.adapt(ENUM).name, "someenum")
eq_(
e1.adapt(ENUM).enums,
e = Enum("x", "y", "long", native_enum=False, length=42)
eq_(e.length, 42)
+ def test_omit_aliases(self, connection):
+ table0 = self.tables["stdlib_enum_table"]
+ type0 = table0.c.someenum.type
+ eq_(type0.enums, ["one", "two", "three", "four", "AMember", "BMember"])
+
+ table = self.tables["stdlib_enum_table_no_alias"]
+
+ type_ = table.c.someenum.type
+ eq_(type_.enums, ["one", "two", "three", "AMember", "BMember"])
+
+ connection.execute(
+ table.insert(),
+ [
+ {"id": 1, "someenum": self.SomeEnum.three},
+ {"id": 2, "someenum": self.SomeEnum.four},
+ ],
+ )
+ eq_(
+ connection.execute(table.select().order_by(table.c.id)).fetchall(),
+ [(1, self.SomeEnum.three), (2, self.SomeEnum.three)],
+ )
+
+ def test_omit_warn(self):
+ with expect_deprecated_20(
+ r"The provided enum someenum contains the aliases \['four'\]"
+ ):
+ Enum(self.SomeEnum)
+
MyPickleType = None