From: Federico Caselli Date: Wed, 5 Feb 2025 22:41:32 +0000 (+0100) Subject: Default python_type impl now returns object X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3a998cbb527beee0cab72c364436e51ca256efcd;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Default python_type impl now returns object The default implementation of :attr:`_sql.TypeEngine.python_type` now returns ``object`` instead of ``NotImplementedError``, since that's the base for all types in Python3. The ``python_type`` of :class:`_sql.JSON` no longer returns ``dict``, but instead fallbacks to the generic implementation. Fixes: #10646 Change-Id: I2233e4a3d35a67b520a860d70afba8e5b22fd72d --- diff --git a/doc/build/changelog/unreleased_21/10646.rst b/doc/build/changelog/unreleased_21/10646.rst new file mode 100644 index 0000000000..7d82138f98 --- /dev/null +++ b/doc/build/changelog/unreleased_21/10646.rst @@ -0,0 +1,9 @@ +.. change:: + :tags: typing + :tickets: 10646 + + The default implementation of :attr:`_sql.TypeEngine.python_type` now + returns ``object`` instead of ``NotImplementedError``, since that's the + base for all types in Python3. + The ``python_type`` of :class:`_sql.JSON` no longer returns ``dict``, + but instead fallbacks to the generic implementation. diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index 44c193bf73..ec382c2f14 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -2739,10 +2739,6 @@ class JSON(Indexable, TypeEngine[Any]): comparator_factory = Comparator - @property - def python_type(self): - return dict - @property # type: ignore # mypy property bug def should_evaluate_none(self): """Alias of :attr:`_types.JSON.none_as_null`""" diff --git a/lib/sqlalchemy/sql/type_api.py b/lib/sqlalchemy/sql/type_api.py index fb72c825e5..19b315928a 100644 --- a/lib/sqlalchemy/sql/type_api.py +++ b/lib/sqlalchemy/sql/type_api.py @@ -611,21 +611,22 @@ class TypeEngine(Visitable, Generic[_T]): @property def python_type(self) -> Type[Any]: """Return the Python type object expected to be returned - by instances of this type, if known. + by instances of this type. Basically, for those types which enforce a return type, or are known across the board to do such for all common DBAPIs (like ``int`` for example), will return that type. - If a return type is not defined, raises - ``NotImplementedError``. + By default the generic ``object`` type is returned. Note that any type also accommodates NULL in SQL which means you can also get back ``None`` from any type in practice. + .. versionchanged:: 2.1 - The default implementation now returns + ``object`` instead of raising ``NotImplementedError``. """ - raise NotImplementedError() + return object def with_variant( self, diff --git a/test/sql/test_types.py b/test/sql/test_types.py index f5a042e32a..f3e25f395a 100644 --- a/test/sql/test_types.py +++ b/test/sql/test_types.py @@ -7,6 +7,7 @@ import pickle import subprocess import sys from tempfile import mkstemp +import uuid import sqlalchemy as sa from sqlalchemy import and_ @@ -310,22 +311,27 @@ class AdaptTest(fixtures.TestBase): eq_(t1.evaluates_none().should_evaluate_none, True) def test_python_type(self): + eq_(types.ARRAY(types.Integer).python_type, list) + eq_(types.Boolean().python_type, bool) + eq_(types.Date().python_type, datetime.date) + eq_(types.DateTime().python_type, datetime.datetime) + eq_(types.Double().python_type, float) + eq_(types.Enum("one", "two", "three").python_type, str) + eq_(types.Float().python_type, float) eq_(types.Integer().python_type, int) + eq_(types.Interval().python_type, datetime.timedelta) + eq_(types.JSON().python_type, object) + eq_(types.LargeBinary().python_type, bytes) + eq_(types.NullType().python_type, object) eq_(types.Numeric().python_type, decimal.Decimal) eq_(types.Numeric(asdecimal=False).python_type, float) - eq_(types.LargeBinary().python_type, bytes) - eq_(types.Float().python_type, float) - eq_(types.Double().python_type, float) - eq_(types.Interval().python_type, datetime.timedelta) - eq_(types.Date().python_type, datetime.date) - eq_(types.DateTime().python_type, datetime.datetime) + eq_(types.PickleType().python_type, object) eq_(types.String().python_type, str) + eq_(types.Time().python_type, datetime.time) eq_(types.Unicode().python_type, str) - eq_(types.Enum("one", "two", "three").python_type, str) - - assert_raises( - NotImplementedError, lambda: types.TypeEngine().python_type - ) + eq_(types.Uuid().python_type, uuid.UUID) + eq_(types.Uuid(as_uuid=False).python_type, str) + eq_(types.TypeEngine().python_type, object) @testing.uses_deprecated() @testing.combinations(*[(t,) for t in _all_types(omit_special_types=True)])