Skip to content

Commit

Permalink
feat: add codemod to add a length parameter to get_random_string()
Browse files Browse the repository at this point in the history
  • Loading branch information
akx authored and browniebroke committed Oct 16, 2020
1 parent 111dd37 commit f88f56d
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 0 deletions.
2 changes: 2 additions & 0 deletions django_codemod/visitors/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .admin import InlineHasAddPermissionsTransformer
from .core import URLResolversTransformer
from .crypto import GetRandomStringTransformer
from .decorators import AvailableAttrsTransformer, ContextDecoratorTransformer
from .encoding import (
ForceTextTransformer,
Expand Down Expand Up @@ -46,6 +47,7 @@
"FloatRangeFormFieldTransformer",
"FloatRangeModelFieldTransformer",
"ForceTextTransformer",
"GetRandomStringTransformer",
"HttpRequestXReadLinesTransformer",
"HttpUrlQuotePlusTransformer",
"HttpUrlQuoteTransformer",
Expand Down
36 changes: 36 additions & 0 deletions django_codemod/visitors/crypto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from typing import Sequence

from libcst import Arg, Call, Integer

from django_codemod.constants import DJANGO_3_1, DJANGO_4_0
from django_codemod.utils.calls import find_keyword_arg
from django_codemod.visitors.base import BaseFuncRenameTransformer


class GetRandomStringTransformer(BaseFuncRenameTransformer):
"""Update lengthless uses of get_random_string()"""

deprecated_in = DJANGO_3_1
removed_in = DJANGO_4_0
rename_from = "django.utils.crypto.get_random_string"
rename_to = "django.utils.crypto.get_random_string"

# The default value Django specifies is 12.
default_length_value = Integer("12")

def update_call_args(self, node: Call) -> Sequence[Arg]:
# No args? Just add the default 12.
if not node.args:
return [Arg(value=self.default_length_value)]

# If there's only an allowed chars kwarg, prepend the length arg.
allowed_chars_kwarg = find_keyword_arg(node.args, "allowed_chars")

if len(node.args) == 1 and allowed_chars_kwarg:
return [
Arg(value=self.default_length_value),
allowed_chars_kwarg,
]

# Otherwise don't do anything.
return node.args
87 changes: 87 additions & 0 deletions tests/visitors/test_crypto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from django_codemod.visitors.crypto import GetRandomStringTransformer
from tests.visitors.base import BaseVisitorTest


class TestGetRandomStringTransformer(BaseVisitorTest):

transformer = GetRandomStringTransformer

def test_noop_1(self) -> None:
"""Test when nothing should change."""
before = """
from django.utils.crypto import get_random_string
get_random_string(16)
"""

after = """
from django.utils.crypto import get_random_string
get_random_string(16)
"""

self.assertCodemod(before, after)

def test_noop_2(self) -> None:
"""Test when nothing should change."""
before = """
from django.utils.crypto import get_random_string
get_random_string(16, allowed_chars="abc")
"""

after = """
from django.utils.crypto import get_random_string
get_random_string(16, allowed_chars="abc")
"""

self.assertCodemod(before, after)

def test_noop_3(self) -> None:
"""Test when nothing should change."""
before = """
from django.utils.crypto import get_random_string
get_random_string(length=16, allowed_chars="abc")
"""

after = """
from django.utils.crypto import get_random_string
get_random_string(length=16, allowed_chars="abc")
"""

self.assertCodemod(before, after)

def test_simple_substitution(self) -> None:
"""Test adding the length parameter."""
before = """
from django.utils.crypto import get_random_string
get_random_string()
"""

after = """
from django.utils.crypto import get_random_string
get_random_string(12)
"""

self.assertCodemod(before, after)

def test_allowed_chars_present(self) -> None:
"""Test adding the length parameter when allowed_chars is present."""
before = """
from django.utils.crypto import get_random_string
get_random_string(allowed_chars="abc")
"""

after = """
from django.utils.crypto import get_random_string
get_random_string(12, allowed_chars="abc")
"""

self.assertCodemod(before, after)

0 comments on commit f88f56d

Please sign in to comment.