]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
resolves #4733
authorRamonWill <ramonwilliams@hotmail.co.uk>
Mon, 3 Aug 2020 16:57:26 +0000 (17:57 +0100)
committerRamonWill <ramonwilliams@hotmail.co.uk>
Mon, 3 Aug 2020 16:57:26 +0000 (17:57 +0100)
doc/build/changelog/unreleased_14/4733.rst [new file with mode: 0644]
lib/sqlalchemy/sql/sqltypes.py
lib/sqlalchemy/util/langhelpers.py
test/sql/test_types.py

diff --git a/doc/build/changelog/unreleased_14/4733.rst b/doc/build/changelog/unreleased_14/4733.rst
new file mode 100644 (file)
index 0000000..fb85800
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: bug, datatypes, sql
+    :tickets: 4733
+
+    The ``LookupError`` message will now provide the user with up to four
+    possible values that a column is constrained to via the :class:`.Enum`.
+    Values longer than 11 characters will be truncated and replaced with
+    ellipses. Pull request courtesy Ramon Williams.
index 186f885d8aac9c31ee3878047b1e745fada175c8..52d80da669b69cfaee599652143e6086221a27b7 100644 (file)
@@ -38,6 +38,7 @@ from .. import inspection
 from .. import processors
 from .. import util
 from ..util import compat
+from ..util import langhelpers
 from ..util import pickle
 
 
@@ -1555,7 +1556,9 @@ class Enum(Emulated, String, SchemaType):
             else:
                 util.raise_(
                     LookupError(
-                        '"%s" is not among the defined enum values' % elem
+                        "'%s' is not among the defined enum values. "
+                        "Possible values: %s"
+                        % (elem, langhelpers._repr_tuple_names(self.enums))
                     ),
                     replace_context=err,
                 )
@@ -1579,7 +1582,9 @@ class Enum(Emulated, String, SchemaType):
         except KeyError as err:
             util.raise_(
                 LookupError(
-                    '"%s" is not among the defined enum values' % elem
+                    "'%s' is not among the defined enum values. "
+                    "Possible values: %s"
+                    % (elem, langhelpers._repr_tuple_names(self.enums))
                 ),
                 replace_context=err,
             )
index 28b7aa4ccccfd5f785f8eef23eb64d232c8ce1d8..2ac4b95757f90f904a943d8ca7a1b47dda5ec282 100644 (file)
@@ -1737,3 +1737,17 @@ def inject_param_text(doctext, inject_params):
         lines.append(line)
 
     return "\n".join(lines)
+
+
+def _repr_tuple_names(names):
+    """ Trims a list of strings from the middle and return a string of up to
+        four elements. Strings greater than 12 characters will be truncated"""
+    if len(names) == 0:
+        return None
+    flag = len(names) <= 4
+    names = names[0:4] if flag else names[0:3] + names[-1:]
+    res = ["%s.." % name[:11] if len(name) > 12 else name for name in names]
+    if flag:
+        return ", ".join(res)
+    else:
+        return "%s, ..., %s" % (", ".join(res[0:3]), res[-1])
index fac9fd1399aaa224b1eda90fe46b562592371642..dfbb78245ace24a8d83398fcd57511609b58efe3 100644 (file)
@@ -1452,14 +1452,16 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
         eq_(bind_processor("foo"), "foo")
         assert_raises_message(
             LookupError,
-            '"5" is not among the defined enum values',
+            "'5' is not among the defined enum values. "
+            "Possible values: one, two, three, ..., BMember",
             bind_processor,
             5,
         )
 
         assert_raises_message(
             LookupError,
-            '"foo" is not among the defined enum values',
+            "'foo' is not among the defined enum values. "
+            "Possible values: one, two, three, ..., BMember",
             bind_processor_validates,
             "foo",
         )
@@ -1469,7 +1471,8 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
         eq_(result_processor("one"), self.one)
         assert_raises_message(
             LookupError,
-            '"foo" is not among the defined enum values',
+            "'foo' is not among the defined enum values. "
+            "Possible values: one, two, three, ..., BMember",
             result_processor,
             "foo",
         )
@@ -1484,14 +1487,16 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
 
         assert_raises_message(
             LookupError,
-            '"5" is not among the defined enum values',
+            "'5' is not among the defined enum values. "
+            "Possible values: one, two, three, ..., BMember",
             literal_processor,
             5,
         )
 
         assert_raises_message(
             LookupError,
-            '"foo" is not among the defined enum values',
+            "'foo' is not among the defined enum values. "
+            "Possible values: one, two, three, ..., BMember",
             validate_literal_processor,
             "foo",
         )
@@ -1508,14 +1513,16 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
         eq_(bind_processor("foo"), "foo")
         assert_raises_message(
             LookupError,
-            '"5" is not among the defined enum values',
+            "'5' is not among the defined enum values. "
+            "Possible values: one, two",
             bind_processor,
             5,
         )
 
         assert_raises_message(
             LookupError,
-            '"foo" is not among the defined enum values',
+            "'foo' is not among the defined enum values. "
+            "Possible values: one, two",
             bind_processor_validates,
             "foo",
         )
@@ -1525,7 +1532,8 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
         eq_(result_processor("one"), "one")
         assert_raises_message(
             LookupError,
-            '"foo" is not among the defined enum values',
+            "'foo' is not among the defined enum values. "
+            "Possible values: one, two",
             result_processor,
             "foo",
         )
@@ -1538,18 +1546,45 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
         eq_(literal_processor("foo"), "'foo'")
         assert_raises_message(
             LookupError,
-            '"5" is not among the defined enum values',
+            "'5' is not among the defined enum values. "
+            "Possible values: one, two",
             literal_processor,
             5,
         )
 
         assert_raises_message(
             LookupError,
-            '"foo" is not among the defined enum values',
+            "'foo' is not among the defined enum values. "
+            "Possible values: one, two",
             validate_literal_processor,
             "foo",
         )
 
+    def test_enum_raise_lookup_ellipses(self):
+        type_ = Enum("one", "twothreefourfivesix", "seven", "eight")
+        bind_processor = type_.bind_processor(testing.db.dialect)
+
+        eq_(bind_processor("one"), "one")
+        assert_raises_message(
+            LookupError,
+            "'5' is not among the defined enum values. "
+            "Possible values: one, twothreefou.., seven, eight",
+            bind_processor,
+            5,
+        )
+
+    def test_enum_raise_lookup_none(self):
+        type_ = Enum()
+        bind_processor = type_.bind_processor(testing.db.dialect)
+
+        assert_raises_message(
+            LookupError,
+            "'5' is not among the defined enum values. "
+            "Possible values: None",
+            bind_processor,
+            5,
+        )
+
     def test_validators_not_in_like_roundtrip(self, connection):
         enum_table = self.tables["non_native_enum_table"]
 
@@ -1745,7 +1780,8 @@ class EnumTest(AssertsCompiledSQL, fixtures.TablesTest):
             )
             assert_raises_message(
                 LookupError,
-                '"four" is not among the defined enum values',
+                "'four' is not among the defined enum values. "
+                "Possible values: one, two, three",
                 conn.scalar,
                 select([self.tables.non_native_enum_table.c.someotherenum]),
             )