From fd21f82aa82b0d75a161f618ef944ebe0923e0ab Mon Sep 17 00:00:00 2001 From: Nick Pope Date: Wed, 18 Jan 2023 16:27:23 +0000 Subject: [PATCH] Refs #34233 -- Used types.NoneType. Available since Python 3.10 where it was reintroduced. --- django/contrib/gis/gdal/srs.py | 3 ++- django/contrib/postgres/constraints.py | 8 +++++--- django/contrib/sites/checks.py | 4 +++- django/db/migrations/serializer.py | 4 ++-- django/db/models/constraints.py | 7 ++++--- django/db/models/expressions.py | 2 +- django/db/models/indexes.py | 6 ++++-- django/utils/encoding.py | 3 ++- tests/migrations/test_writer.py | 3 ++- 9 files changed, 25 insertions(+), 15 deletions(-) diff --git a/django/contrib/gis/gdal/srs.py b/django/contrib/gis/gdal/srs.py index 2e335fe5d5..c8877753fd 100644 --- a/django/contrib/gis/gdal/srs.py +++ b/django/contrib/gis/gdal/srs.py @@ -28,6 +28,7 @@ """ from ctypes import byref, c_char_p, c_int from enum import IntEnum +from types import NoneType from django.contrib.gis.gdal.base import GDALBase from django.contrib.gis.gdal.error import SRSException @@ -57,7 +58,7 @@ class SpatialReference(GDALBase): EPSG code, a PROJ string, and/or a projection "well known" shorthand string (one of 'WGS84', 'WGS72', 'NAD27', 'NAD83'). """ - if not isinstance(axis_order, (type(None), AxisOrder)): + if not isinstance(axis_order, (NoneType, AxisOrder)): raise ValueError( "SpatialReference.axis_order must be an AxisOrder instance." ) diff --git a/django/contrib/postgres/constraints.py b/django/contrib/postgres/constraints.py index 4c739b3fbb..30ef7602a5 100644 --- a/django/contrib/postgres/constraints.py +++ b/django/contrib/postgres/constraints.py @@ -1,3 +1,5 @@ +from types import NoneType + from django.contrib.postgres.indexes import OpClass from django.core.exceptions import ValidationError from django.db import DEFAULT_DB_ALIAS, NotSupportedError @@ -45,13 +47,13 @@ class ExclusionConstraint(BaseConstraint): isinstance(expr, (list, tuple)) and len(expr) == 2 for expr in expressions ): raise ValueError("The expressions must be a list of 2-tuples.") - if not isinstance(condition, (type(None), Q)): + if not isinstance(condition, (NoneType, Q)): raise ValueError("ExclusionConstraint.condition must be a Q instance.") - if not isinstance(deferrable, (type(None), Deferrable)): + if not isinstance(deferrable, (NoneType, Deferrable)): raise ValueError( "ExclusionConstraint.deferrable must be a Deferrable instance." ) - if not isinstance(include, (type(None), list, tuple)): + if not isinstance(include, (NoneType, list, tuple)): raise ValueError("ExclusionConstraint.include must be a list or tuple.") self.expressions = expressions self.index_type = index_type or "GIST" diff --git a/django/contrib/sites/checks.py b/django/contrib/sites/checks.py index 6db039fb56..66e8551bed 100644 --- a/django/contrib/sites/checks.py +++ b/django/contrib/sites/checks.py @@ -1,10 +1,12 @@ +from types import NoneType + from django.conf import settings from django.core.checks import Error def check_site_id(app_configs, **kwargs): if hasattr(settings, "SITE_ID") and not isinstance( - settings.SITE_ID, (type(None), int) + settings.SITE_ID, (NoneType, int) ): return [ Error("The SITE_ID setting must be an integer", id="sites.E101"), diff --git a/django/db/migrations/serializer.py b/django/db/migrations/serializer.py index 7ebc966f40..454feaa829 100644 --- a/django/db/migrations/serializer.py +++ b/django/db/migrations/serializer.py @@ -304,7 +304,7 @@ class TypeSerializer(BaseSerializer): def serialize(self): special_cases = [ (models.Model, "models.Model", ["from django.db import models"]), - (type(None), "type(None)", []), + (types.NoneType, "types.NoneType", ["import types"]), ] for case, string, imports in special_cases: if case is self.value: @@ -338,7 +338,7 @@ class Serializer: (datetime.date, datetime.timedelta, datetime.time): DateTimeSerializer, SettingsReference: SettingsReferenceSerializer, float: FloatSerializer, - (bool, int, type(None), bytes, str, range): BaseSimpleSerializer, + (bool, int, types.NoneType, bytes, str, range): BaseSimpleSerializer, decimal.Decimal: DecimalSerializer, (functools.partial, functools.partialmethod): FunctoolsPartialSerializer, ( diff --git a/django/db/models/constraints.py b/django/db/models/constraints.py index 49c7c91de9..179cfd2a18 100644 --- a/django/db/models/constraints.py +++ b/django/db/models/constraints.py @@ -1,4 +1,5 @@ from enum import Enum +from types import NoneType from django.core.exceptions import FieldError, ValidationError from django.db import connections @@ -148,7 +149,7 @@ class UniqueConstraint(BaseConstraint): raise ValueError( "UniqueConstraint.fields and expressions are mutually exclusive." ) - if not isinstance(condition, (type(None), Q)): + if not isinstance(condition, (NoneType, Q)): raise ValueError("UniqueConstraint.condition must be a Q instance.") if condition and deferrable: raise ValueError("UniqueConstraint with conditions cannot be deferred.") @@ -163,11 +164,11 @@ class UniqueConstraint(BaseConstraint): "UniqueConstraint.opclasses cannot be used with expressions. " "Use django.contrib.postgres.indexes.OpClass() instead." ) - if not isinstance(deferrable, (type(None), Deferrable)): + if not isinstance(deferrable, (NoneType, Deferrable)): raise ValueError( "UniqueConstraint.deferrable must be a Deferrable instance." ) - if not isinstance(include, (type(None), list, tuple)): + if not isinstance(include, (NoneType, list, tuple)): raise ValueError("UniqueConstraint.include must be a list or tuple.") if not isinstance(opclasses, (list, tuple)): raise ValueError("UniqueConstraint.opclasses must be a list or tuple.") diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 5a1838809c..cac3c0aae8 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -4,6 +4,7 @@ import functools import inspect from collections import defaultdict from decimal import Decimal +from types import NoneType from uuid import UUID from django.core.exceptions import EmptyResultSet, FieldError, FullResultSet @@ -506,7 +507,6 @@ class Expression(BaseExpression, Combinable): # The current approach for NULL is based on lowest common denominator behavior # i.e. if one of the supported databases is raising an error (rather than # return NULL) for `val NULL`, then Django raises FieldError. -NoneType = type(None) _connector_combinations = [ # Numeric operations - operands of same type. diff --git a/django/db/models/indexes.py b/django/db/models/indexes.py index f6f9a004af..a5bddb8325 100644 --- a/django/db/models/indexes.py +++ b/django/db/models/indexes.py @@ -1,3 +1,5 @@ +from types import NoneType + from django.db.backends.utils import names_digest, split_identifier from django.db.models.expressions import Col, ExpressionList, F, Func, OrderBy from django.db.models.functions import Collate @@ -26,7 +28,7 @@ class Index: ): if opclasses and not name: raise ValueError("An index must be named to use opclasses.") - if not isinstance(condition, (type(None), Q)): + if not isinstance(condition, (NoneType, Q)): raise ValueError("Index.condition must be a Q instance.") if condition and not name: raise ValueError("An index must be named to use condition.") @@ -58,7 +60,7 @@ class Index: raise ValueError("Index.fields must contain only strings with field names.") if include and not name: raise ValueError("A covering index must be named.") - if not isinstance(include, (type(None), list, tuple)): + if not isinstance(include, (NoneType, list, tuple)): raise ValueError("Index.include must be a list or tuple.") self.fields = list(fields) # A list of 2-tuple with the field name and ordering ('' or 'DESC'). diff --git a/django/utils/encoding.py b/django/utils/encoding.py index 43847b5385..5b618e74a3 100644 --- a/django/utils/encoding.py +++ b/django/utils/encoding.py @@ -2,6 +2,7 @@ import codecs import datetime import locale from decimal import Decimal +from types import NoneType from urllib.parse import quote from django.utils.functional import Promise @@ -34,7 +35,7 @@ def smart_str(s, encoding="utf-8", strings_only=False, errors="strict"): _PROTECTED_TYPES = ( - type(None), + NoneType, int, float, Decimal, diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py index 0762c43dde..1c11c68e97 100644 --- a/tests/migrations/test_writer.py +++ b/tests/migrations/test_writer.py @@ -9,6 +9,7 @@ import re import sys import uuid import zoneinfo +from types import NoneType from unittest import mock import custom_migration_operations.more_operations @@ -797,7 +798,7 @@ class WriterTests(SimpleTestCase): self.assertEqual(result.keywords, value.keywords) def test_serialize_type_none(self): - self.assertSerializedEqual(type(None)) + self.assertSerializedEqual(NoneType) def test_serialize_type_model(self): self.assertSerializedEqual(models.Model)