diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d893fef7..c4ee8a61 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,6 +12,7 @@ This version drops support for Python 3.6 Bugfixes ~~~~~~~~ +- Fixed compatibility issue with datetime classes and python `3.12` (`#425 `_) Version 2.5.3 (25 Mär 2022) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index a35d2755..7bd39c12 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -20,3 +20,4 @@ - [naquiroz](https://github.com/naquiroz) - [john-sandall](https://github.com/john-sandall) - [dineshtrivedi](https://github.com/dineshtrivedi) +- [matejsp](https://github.com/matejsp) diff --git a/pylint_django/compat.py b/pylint_django/compat.py index d4dfdeef..9eeb128c 100644 --- a/pylint_django/compat.py +++ b/pylint_django/compat.py @@ -1,6 +1,7 @@ # flake8: noqa # pylint: skip-file # no sane linter can figure out the hackiness in this compatibility layer... +import sys try: from astroid.nodes import AssignName, Attribute, ClassDef, FunctionDef, ImportFrom @@ -33,3 +34,6 @@ LOAD_CONFIGURATION_SUPPORTED = tuple(pylint.__version__.split(".")) >= ("2", "3") except AttributeError: LOAD_CONFIGURATION_SUPPORTED = pylint.__pkginfo__.numversion >= (2, 3) + +# datetime module is compiled and moved to _pydatetime +COMPILED_DATETIME_CLASSES = sys.version_info >= (3, 12) diff --git a/pylint_django/transforms/fields.py b/pylint_django/transforms/fields.py index b820b12b..70b96f12 100644 --- a/pylint_django/transforms/fields.py +++ b/pylint_django/transforms/fields.py @@ -1,7 +1,7 @@ from astroid import MANAGER, AstroidImportError, inference_tip, nodes from astroid.nodes import scoped_nodes -from pylint_django import utils +from pylint_django import compat, utils _STR_FIELDS = ( "CharField", @@ -46,7 +46,7 @@ def is_model_or_form_field(cls): return is_model_field(cls) or is_form_field(cls) -def apply_type_shim(cls, _context=None): +def apply_type_shim(cls, _context=None): # pylint: disable=too-many-statements if cls.name in _STR_FIELDS: base_nodes = scoped_nodes.builtin_lookup("str") elif cls.name in _INT_FIELDS: @@ -61,13 +61,25 @@ def apply_type_shim(cls, _context=None): except AstroidImportError: base_nodes = MANAGER.ast_from_module_name("_pydecimal").lookup("Decimal") elif cls.name in ("SplitDateTimeField", "DateTimeField"): - base_nodes = MANAGER.ast_from_module_name("datetime").lookup("datetime") + if compat.COMPILED_DATETIME_CLASSES: + base_nodes = MANAGER.ast_from_module_name("_pydatetime").lookup("datetime") + else: + base_nodes = MANAGER.ast_from_module_name("datetime").lookup("datetime") elif cls.name == "TimeField": - base_nodes = MANAGER.ast_from_module_name("datetime").lookup("time") + if compat.COMPILED_DATETIME_CLASSES: + base_nodes = MANAGER.ast_from_module_name("_pydatetime").lookup("time") + else: + base_nodes = MANAGER.ast_from_module_name("datetime").lookup("time") elif cls.name == "DateField": - base_nodes = MANAGER.ast_from_module_name("datetime").lookup("date") + if compat.COMPILED_DATETIME_CLASSES: + base_nodes = MANAGER.ast_from_module_name("_pydatetime").lookup("date") + else: + base_nodes = MANAGER.ast_from_module_name("datetime").lookup("date") elif cls.name == "DurationField": - base_nodes = MANAGER.ast_from_module_name("datetime").lookup("timedelta") + if compat.COMPILED_DATETIME_CLASSES: + base_nodes = MANAGER.ast_from_module_name("_pydatetime").lookup("timedelta") + else: + base_nodes = MANAGER.ast_from_module_name("datetime").lookup("timedelta") elif cls.name == "UUIDField": base_nodes = MANAGER.ast_from_module_name("uuid").lookup("UUID") elif cls.name == "ManyToManyField":