From: Federico Caselli Date: Tue, 24 Mar 2020 20:06:04 +0000 (+0100) Subject: Add length parameter in `Enum` X-Git-Tag: rel_1_3_16~6^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=040bbc9e8830d30a7cbeb9d35bc691dad2323162;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add length parameter in `Enum` The `Enum` type now supports the parameter `Enum.length` to specify the length of the VARCHAR column to create when using non native enums by setting `Enum.native_enum` to `False` Fixes: #5183 Change-Id: Iea05dc8cd9e33959bb968b394fb10a7dd068c873 (cherry picked from commit 3e2af98adfdcbf33ff5d8c2da15962c001344d64) --- diff --git a/doc/build/changelog/unreleased_13/5183.rst b/doc/build/changelog/unreleased_13/5183.rst new file mode 100644 index 0000000000..21265e0b20 --- /dev/null +++ b/doc/build/changelog/unreleased_13/5183.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: types, enum + :tickets: 5183 + + The :class:`.Enum` type now supports the parameter :paramref:`.Enum.length` + to specify the length of the VARCHAR column to create when using + non native enums by setting :paramref:`.Enum.native_enum` to ``False`` diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index ab05baebea..2d800f7754 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -1319,7 +1319,14 @@ class Enum(Emulated, String, SchemaType): :param native_enum: Use the database's native ENUM type when available. Defaults to True. When False, uses VARCHAR + check - constraint for all backends. + constraint for all backends. The VARCHAR length can be controlled + with :paramref:`.Enum.length` + + :param length: Allows specifying a custom length for the VARCHAR + when :paramref:`.Enum.native_enum` is False. By default it uses the + length of the longest value. + + .. versionadded:: 1.3.16 :param schema: Schema name of this type. For types that exist on the target database as an independent schema construct (PostgreSQL), @@ -1391,6 +1398,7 @@ class Enum(Emulated, String, SchemaType): self.create_constraint = kw.pop("create_constraint", True) 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) values, objects = self._parse_into_values(enums, kw) self._setup_for_values(values, objects, kw) @@ -1414,6 +1422,15 @@ class Enum(Emulated, String, SchemaType): length = max(len(x) for x in self.enums) else: length = 0 + if not self.native_enum and length_arg is not NO_ARG: + if length_arg < length: + raise ValueError( + "When provided, length must be larger or equal" + " than the length of the longest enum value. %s < %s" + % (length_arg, length) + ) + length = length_arg + self._valid_lookup[None] = self._object_lookup[None] = None super(Enum, self).__init__( diff --git a/test/sql/test_types.py b/test/sql/test_types.py index 8e2a4372a0..5be780beb3 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -1873,6 +1873,35 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest): "inherit_schema=True, native_enum=False)", ) + def test_length_native(self): + e = Enum("x", "y", "long", length=42) + + eq_(e.length, len("long")) + + # no error is raised + e = Enum("x", "y", "long", length=1) + eq_(e.length, len("long")) + + def test_length_raises(self): + assert_raises_message( + ValueError, + "When provided, length must be larger or equal.*", + Enum, + "x", + "y", + "long", + native_enum=False, + length=1, + ) + + def test_no_length_non_native(self): + e = Enum("x", "y", "long", native_enum=False) + eq_(e.length, len("long")) + + def test_length_non_native(self): + e = Enum("x", "y", "long", native_enum=False, length=42) + eq_(e.length, 42) + binary_table = MyPickleType = metadata = None