From: Daniele Varrazzo Date: Tue, 21 Sep 2021 15:55:52 +0000 (+0100) Subject: Raise a friendly exception if None is passed to register_*() X-Git-Tag: 3.0~73 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=97c64f57c5de7fe30b3c5cccae2822851cb3840a;p=thirdparty%2Fpsycopg.git Raise a friendly exception if None is passed to register_*() The most likely cause is fetching info and the object is not found. Suggest that that's what happened instead of throwing an AttributeError or anything else random. --- diff --git a/psycopg/psycopg/types/composite.py b/psycopg/psycopg/types/composite.py index 7a754dc40..c80111875 100644 --- a/psycopg/psycopg/types/composite.py +++ b/psycopg/psycopg/types/composite.py @@ -217,6 +217,13 @@ def register_composite( the composite into a Python object. """ + # A friendly error warning instead of an AttributeError in case fetch() + # failed and it wasn't noticed. + if not info: + raise TypeError( + "no info passed. Is the requested composite available?" + ) + # Register arrays and type info info.register(context) diff --git a/psycopg/psycopg/types/hstore.py b/psycopg/psycopg/types/hstore.py index f39bec47a..e45b9414f 100644 --- a/psycopg/psycopg/types/hstore.py +++ b/psycopg/psycopg/types/hstore.py @@ -107,6 +107,10 @@ def register_hstore( :param context: The context where to register the adapters. If `!None`, register it globally. """ + # A friendly error warning instead of an AttributeError in case fetch() + # failed and it wasn't noticed. + if not info: + raise TypeError("no info passed. Is the 'hstore' extension loaded?") # Register arrays and type info info.register(context) diff --git a/psycopg/psycopg/types/range.py b/psycopg/psycopg/types/range.py index 6c353b5e5..59fa04dd3 100644 --- a/psycopg/psycopg/types/range.py +++ b/psycopg/psycopg/types/range.py @@ -442,6 +442,10 @@ def register_range( Register loaders so that loading data of this type will result in a `Range` with bounds parsed as the right subtype. """ + # A friendly error warning instead of an AttributeError in case fetch() + # failed and it wasn't noticed. + if not info: + raise TypeError("no info passed. Is the requested range available?") # Register arrays and type info info.register(context) diff --git a/tests/types/test_composite.py b/tests/types/test_composite.py index cfc2c91e3..cb1125754 100644 --- a/tests/types/test_composite.py +++ b/tests/types/test_composite.py @@ -327,3 +327,8 @@ def test_callable_dumper_not_registered(conn, testcomp): # but the loader is registered cur = conn.execute("select '(foo,42,3.14)'::testcomp") assert cur.fetchone()[0] == ("foo", 42, 3.14, 3.14) + + +def test_no_info_error(conn): + with pytest.raises(TypeError, match="composite"): + register_composite(None, conn) diff --git a/tests/types/test_hstore.py b/tests/types/test_hstore.py index 5c951548f..337d12a32 100644 --- a/tests/types/test_hstore.py +++ b/tests/types/test_hstore.py @@ -97,3 +97,8 @@ def test_roundtrip_array(hstore, conn): register_hstore(TypeInfo.fetch(conn, "hstore"), conn) samp1 = conn.execute("select %s", (samp,)).fetchone()[0] assert samp1 == samp + + +def test_no_info_error(conn): + with pytest.raises(TypeError, match="hstore.*extension"): + register_hstore(None, conn) diff --git a/tests/types/test_range.py b/tests/types/test_range.py index 9ed018c15..2860cac8f 100644 --- a/tests/types/test_range.py +++ b/tests/types/test_range.py @@ -667,3 +667,8 @@ class TestRangeObject: expected = "[2010-01-01 00:00:00-05:00, 2011-01-01 00:00:00-05:00)" result = str(r) assert result == expected + + +def test_no_info_error(conn): + with pytest.raises(TypeError, match="range"): + register_range(None, conn)