diff --git a/django_codemod/visitors/__init__.py b/django_codemod/visitors/__init__.py index 6364e3e2..267e0694 100644 --- a/django_codemod/visitors/__init__.py +++ b/django_codemod/visitors/__init__.py @@ -1,5 +1,9 @@ from .admin import InlineHasAddPermissionsTransformer -from .encoding import ForceTextTransformer, SmartTextTransformer +from .encoding import ( + ForceTextTransformer, + SmartTextTransformer, + UnicodeCompatibleTransformer, +) from .html import UnescapeEntitiesTransformer from .http import ( HttpUrlQuotePlusTransformer, @@ -8,6 +12,8 @@ HttpUrlUnQuoteTransformer, IsSafeUrlTransformer, ) +from .lru_cache import LRUCacheTransformer +from .os_utils import AbsPathTransformer from .shortcuts import RenderToResponseTransformer from .translations import ( UGetTextLazyTransformer, @@ -19,6 +25,7 @@ from .urls import URLTransformer __all__ = ( + "AbsPathTransformer", "ForceTextTransformer", "HttpUrlQuotePlusTransformer", "HttpUrlQuoteTransformer", @@ -26,6 +33,7 @@ "HttpUrlUnQuoteTransformer", "InlineHasAddPermissionsTransformer", "IsSafeUrlTransformer", + "LRUCacheTransformer", "RenderToResponseTransformer", "SmartTextTransformer", "UGetTextLazyTransformer", @@ -35,4 +43,5 @@ "UNGetTextTransformer", "URLTransformer", "UnescapeEntitiesTransformer", + "UnicodeCompatibleTransformer", ) diff --git a/django_codemod/visitors/encoding.py b/django_codemod/visitors/encoding.py index 2c3e469f..e7e9ca91 100644 --- a/django_codemod/visitors/encoding.py +++ b/django_codemod/visitors/encoding.py @@ -1,4 +1,4 @@ -from django_codemod.constants import DJANGO_30, DJANGO_40 +from django_codemod.constants import DJANGO_20, DJANGO_30, DJANGO_40 from django_codemod.visitors.base import BaseSimpleFuncRenameTransformer @@ -18,3 +18,12 @@ class SmartTextTransformer(BaseSimpleFuncRenameTransformer): removed_in = DJANGO_40 rename_from = "django.utils.encoding.smart_text" rename_to = "django.utils.encoding.smart_str" + + +class UnicodeCompatibleTransformer(BaseSimpleFuncRenameTransformer): + """Resolve deprecation of ``django.utils.encoding.python_2_unicode_compatible``.""" + + deprecated_in = DJANGO_20 + removed_in = DJANGO_30 + rename_from = "django.utils.encoding.python_2_unicode_compatible" + rename_to = "six.python_2_unicode_compatible" diff --git a/django_codemod/visitors/lru_cache.py b/django_codemod/visitors/lru_cache.py new file mode 100644 index 00000000..688750bb --- /dev/null +++ b/django_codemod/visitors/lru_cache.py @@ -0,0 +1,11 @@ +from django_codemod.constants import DJANGO_20, DJANGO_30 +from django_codemod.visitors.base import BaseSimpleFuncRenameTransformer + + +class LRUCacheTransformer(BaseSimpleFuncRenameTransformer): + """Resolve deprecation of ``django.utils.lru_cache.lru_cache``.""" + + deprecated_in = DJANGO_20 + removed_in = DJANGO_30 + rename_from = "django.utils.lru_cache.lru_cache" + rename_to = "functools.lru_cache" diff --git a/django_codemod/visitors/os_utils.py b/django_codemod/visitors/os_utils.py new file mode 100644 index 00000000..0163c57e --- /dev/null +++ b/django_codemod/visitors/os_utils.py @@ -0,0 +1,11 @@ +from django_codemod.constants import DJANGO_20, DJANGO_30 +from django_codemod.visitors.base import BaseSimpleFuncRenameTransformer + + +class AbsPathTransformer(BaseSimpleFuncRenameTransformer): + """Resolve deprecation of ``django.utils._os.abspathu``.""" + + deprecated_in = DJANGO_20 + removed_in = DJANGO_30 + rename_from = "django.utils._os.abspathu" + rename_to = "os.path.abspath" diff --git a/docs/codemods.rst b/docs/codemods.rst index a73b80eb..5ce12b7b 100644 --- a/docs/codemods.rst +++ b/docs/codemods.rst @@ -10,6 +10,9 @@ Applied by passing the ``--removed-in 3.0`` or ``--deprecated-in 2.0`` option: - Replaces ``render_to_response()`` by ``render()`` and add ``request=None`` as the first argument of ``render()``. +- Replaces ``django.utils.lru_cache.lru_cache()`` by the function it's an alias of: ``functools.lru_cache()``. +- Replaces ``django.utils._os.abspathu()`` by the function it's an alias of: ``os.path.abspath()``. +- Replaces ``django.utils.encoding.python_2_unicode_compatible()`` by the function it's an alias of: ``six.python_2_unicode_compatible()``. Applied by passing the ``--removed-in 3.0`` or ``--deprecated-in 2.1`` option: diff --git a/tests/test_cli.py b/tests/test_cli.py index b6ad0c30..9199c63f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -124,7 +124,12 @@ def test_deprecated_in_mapping(): "UnescapeEntitiesTransformer", ], (2, 1): ["InlineHasAddPermissionsTransformer"], - (2, 0): ["RenderToResponseTransformer"], + (2, 0): [ + "AbsPathTransformer", + "LRUCacheTransformer", + "RenderToResponseTransformer", + "UnicodeCompatibleTransformer", + ], } @@ -147,5 +152,11 @@ def test_removed_in_mapping(): "URLTransformer", "UnescapeEntitiesTransformer", ], - (3, 0): ["InlineHasAddPermissionsTransformer", "RenderToResponseTransformer"], + (3, 0): [ + "AbsPathTransformer", + "InlineHasAddPermissionsTransformer", + "LRUCacheTransformer", + "RenderToResponseTransformer", + "UnicodeCompatibleTransformer", + ], } diff --git a/tests/visitors/test_encoding.py b/tests/visitors/test_encoding.py index 178417ed..7812efe3 100644 --- a/tests/visitors/test_encoding.py +++ b/tests/visitors/test_encoding.py @@ -1,4 +1,8 @@ -from django_codemod.visitors import ForceTextTransformer, SmartTextTransformer +from django_codemod.visitors import ( + ForceTextTransformer, + SmartTextTransformer, + UnicodeCompatibleTransformer, +) from tests.visitors.base import BaseVisitorTest @@ -37,3 +41,26 @@ def test_simple_substitution(self) -> None: result = smart_str(content) """ self.assertCodemod(before, after) + + +class TestUnicodeCompatibleTransformer(BaseVisitorTest): + + transformer = UnicodeCompatibleTransformer + + def test_simple_substitution(self) -> None: + """Check simple use case.""" + before = """ + from django.utils.encoding import python_2_unicode_compatible + + @python_2_unicode_compatible + class MyModel: + pass + """ + after = """ + from six import python_2_unicode_compatible + + @python_2_unicode_compatible + class MyModel: + pass + """ + self.assertCodemod(before, after) diff --git a/tests/visitors/test_lru_cache.py b/tests/visitors/test_lru_cache.py new file mode 100644 index 00000000..99140768 --- /dev/null +++ b/tests/visitors/test_lru_cache.py @@ -0,0 +1,20 @@ +from django_codemod.visitors import LRUCacheTransformer +from tests.visitors.base import BaseVisitorTest + + +class TestLRUCacheTransformer(BaseVisitorTest): + + transformer = LRUCacheTransformer + + def test_simple_substitution(self) -> None: + before = """ + from django.utils.lru_cache import lru_cache + + result = lru_cache(content) + """ + after = """ + from functools import lru_cache + + result = lru_cache(content) + """ + self.assertCodemod(before, after) diff --git a/tests/visitors/test_os_utils.py b/tests/visitors/test_os_utils.py new file mode 100644 index 00000000..d321e356 --- /dev/null +++ b/tests/visitors/test_os_utils.py @@ -0,0 +1,20 @@ +from django_codemod.visitors import AbsPathTransformer +from tests.visitors.base import BaseVisitorTest + + +class TestAbsPathTransformer(BaseVisitorTest): + + transformer = AbsPathTransformer + + def test_simple_substitution(self) -> None: + before = """ + from django.utils._os import abspathu + + result = abspathu(content) + """ + after = """ + from os.path import abspath + + result = abspath(content) + """ + self.assertCodemod(before, after)