From: Mike Bayer Date: Fri, 10 Jun 2022 16:42:54 +0000 (-0400) Subject: honor enum length in all cases X-Git-Tag: rel_2_0_0b1~247^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4274981156a554fb4b8340d2fa4d8c4afed7c86c;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git honor enum length in all cases The :paramref:`.Enum.length` parameter, which sets the length of the ``VARCHAR`` column for non-native enumeration types, is now used unconditionally when emitting DDL for the ``VARCHAR`` datatype, including when the :paramref:`.Enum.native_enum` parameter is set to ``True`` for target backends that continue to use ``VARCHAR``. Previously the parameter would be erroneously ignored in this case. The warning previously emitted for this case is now removed. Fixes: #7791 Change-Id: I91764546b56e9416479949be8a118cdc91ac5ed9 --- diff --git a/doc/build/changelog/unreleased_20/7791.rst b/doc/build/changelog/unreleased_20/7791.rst new file mode 100644 index 0000000000..4673a8790c --- /dev/null +++ b/doc/build/changelog/unreleased_20/7791.rst @@ -0,0 +1,11 @@ +.. change:: + :tags: bug, sql + :tickets: 7791 + + The :paramref:`.Enum.length` parameter, which sets the length of the + ``VARCHAR`` column for non-native enumeration types, is now used + unconditionally when emitting DDL for the ``VARCHAR`` datatype, including + when the :paramref:`.Enum.native_enum` parameter is set to ``True`` for + target backends that continue to use ``VARCHAR``. Previously the parameter + would be erroneously ignored in this case. The warning previously emitted + for this case is now removed. diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index 50cb325033..7b18fda722 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -1316,10 +1316,14 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]): ignored if native_enum=True. :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. + when a non-native enumeration datatype is used. By default it uses + the length of the longest value. + + .. versionchanged:: 2.0.0 The :paramref:`.Enum.length` parameter + is used unconditionally for ``VARCHAR`` rendering regardless of + the :paramref:`.Enum.native_enum` parameter, for those backends + where ``VARCHAR`` is used for enumerated datatypes. - .. 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), @@ -1419,22 +1423,13 @@ class Enum(String, SchemaType, Emulated, TypeEngine[Union[str, enum.Enum]]): self._default_length = length = 0 if length_arg is not NO_ARG: - if self.native_enum: - if not _disable_warnings: - util.warn( - "Enum 'length' argument is currently ignored unless " - "native_enum is specified as False, including for DDL " - "that renders VARCHAR in any case. This may change " - "in a future release." - ) - else: - if not _disable_warnings and 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 + if not _disable_warnings and 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 diff --git a/test/sql/test_types.py b/test/sql/test_types.py index b2afa2dbab..ef39157269 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -83,7 +83,6 @@ from sqlalchemy.testing import AssertsExecutionResults from sqlalchemy.testing import engines from sqlalchemy.testing import eq_ from sqlalchemy.testing import expect_raises -from sqlalchemy.testing import expect_warnings from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import is_not @@ -2394,18 +2393,26 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest): eq_(e1_vc.adapt(ENUM).name, "someotherenum") eq_(e1_vc.adapt(ENUM).enums, ["1", "2", "3", "a", "b"]) - def test_adapt_length(self): + @testing.combinations(True, False, argnames="native_enum") + def test_adapt_length(self, native_enum): from sqlalchemy.dialects.postgresql import ENUM - e1 = Enum("one", "two", "three", length=50, native_enum=False) - eq_(e1.adapt(ENUM).length, 50) + e1 = Enum("one", "two", "three", length=50, native_enum=native_enum) + + if not native_enum: + eq_(e1.adapt(ENUM).length, 50) + eq_(e1.adapt(Enum).length, 50) + self.assert_compile(e1, "VARCHAR(50)", dialect="default") + e1 = Enum("one", "two", "three") eq_(e1.length, 5) eq_(e1.adapt(ENUM).length, 5) eq_(e1.adapt(Enum).length, 5) + self.assert_compile(e1, "VARCHAR(5)", dialect="default") + @testing.provide_metadata def test_create_metadata_bound_no_crash(self): m1 = self.metadata @@ -2502,32 +2509,20 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest): ) def test_repr_four(self): - with expect_warnings( - "Enum 'length' argument is currently ignored unless native_enum" - ): - e = Enum("x", "y", length=255) - # length is currently ignored if native_enum is not False + e = Enum("x", "y", length=255) eq_( repr(e), - "Enum('x', 'y')", + "Enum('x', 'y', length=255)", ) def test_length_native(self): - with expect_warnings( - "Enum 'length' argument is currently ignored unless native_enum" - ): - e = Enum("x", "y", "long", length=42) - - eq_(e.length, len("long")) + e = Enum("x", "y", "long", length=42) + eq_(e.length, 42) - # no error is raised - with expect_warnings( - "Enum 'length' argument is currently ignored unless native_enum" - ): - e = Enum("x", "y", "long", length=1) + e = Enum("x", "y", "long") eq_(e.length, len("long")) - def test_length_raises(self): + def test_length_too_short_raises(self): assert_raises_message( ValueError, "When provided, length must be larger or equal.*",