django-codemod 2.5.0__tar.gz → 2.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_codemod-2.5.0/src/django_codemod.egg-info → django_codemod-2.6.0}/PKG-INFO +2 -2
- {django_codemod-2.5.0 → django_codemod-2.6.0}/pyproject.toml +3 -3
- django_codemod-2.6.0/src/django_codemod/__init__.py +1 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/path_utils.py +3 -3
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/__init__.py +2 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/base.py +4 -1
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/models.py +51 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0/src/django_codemod.egg-info}/PKG-INFO +2 -2
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod.egg-info/SOURCES.txt +0 -1
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod.egg-info/requires.txt +1 -1
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/base.py +4 -2
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_models.py +94 -0
- django_codemod-2.5.0/src/django_codemod/__init__.py +0 -1
- django_codemod-2.5.0/tests/test_e2e.sh +0 -39
- {django_codemod-2.5.0 → django_codemod-2.6.0}/LICENSE +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/MANIFEST.in +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/README.md +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/docs/Makefile +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/docs/conf.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/docs/make.bat +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/setup.cfg +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/cli.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/commands.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/constants.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/feature_flags.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/utils/__init__.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/utils/calls.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/admin.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/core.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/crypto.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/decorators.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/encoding.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/exceptions.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/forms.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/html.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/http.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/lru_cache.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/os_utils.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/paginator.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/postgres_fields.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/shortcuts.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/signals.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/template_context.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/template_tags.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/timezone.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/translations.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/urls.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod.egg-info/dependency_links.txt +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod.egg-info/entry_points.txt +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod.egg-info/top_level.txt +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/__init__.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/test_cli.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/test_path_utils.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/__init__.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_admin.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_base.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_core.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_crypto.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_decorators.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_encoding.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_exceptions.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_forms.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_html.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_http.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_lru_cache.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_os_utils.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_paginator.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_postgres_fields.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_shortcuts.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_signals.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_template_context.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_template_tags.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_timezone.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_translations.py +0 -0
- {django_codemod-2.5.0 → django_codemod-2.6.0}/tests/visitors/test_urls.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-codemod
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.0
|
|
4
4
|
Summary: A command line tool to automatically fix Django deprecations.
|
|
5
5
|
Author-email: Bruno Alla <alla.brunoo@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,7 +26,7 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
26
26
|
Requires-Python: >=3.10
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
28
28
|
License-File: LICENSE
|
|
29
|
-
Requires-Dist: click<8.
|
|
29
|
+
Requires-Dist: click<8.6
|
|
30
30
|
Requires-Dist: libcst==1.9
|
|
31
31
|
Requires-Dist: pathspec<2,>=0.6
|
|
32
32
|
Requires-Dist: rich>=10
|
|
@@ -4,7 +4,7 @@ requires = [ "setuptools>=77.0.3" ]
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "django-codemod"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.6.0"
|
|
8
8
|
description = "A command line tool to automatically fix Django deprecations."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
keywords = [
|
|
@@ -32,7 +32,7 @@ classifiers = [
|
|
|
32
32
|
"Topic :: Software Development :: Libraries",
|
|
33
33
|
]
|
|
34
34
|
dependencies = [
|
|
35
|
-
"click<8.
|
|
35
|
+
"click<8.6",
|
|
36
36
|
"libcst==1.9",
|
|
37
37
|
"pathspec>=0.6,<2",
|
|
38
38
|
"rich>=10",
|
|
@@ -52,7 +52,7 @@ dev = [
|
|
|
52
52
|
"pytest>=9,<10",
|
|
53
53
|
"pytest-cov>=7,<8",
|
|
54
54
|
"pytest-mock>=3.3,<4",
|
|
55
|
-
"ty==0.0.
|
|
55
|
+
"ty==0.0.99",
|
|
56
56
|
]
|
|
57
57
|
docs = [
|
|
58
58
|
"furo>=2023.5.20; python_version>='3.11'",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.6.0"
|
|
@@ -5,13 +5,13 @@ Inspired or taken from black:
|
|
|
5
5
|
https://github.com/psf/black
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from collections.abc import Iterable, Iterator
|
|
8
|
+
from collections.abc import Collection, Iterable, Iterator
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
|
|
11
11
|
from pathspec import PathSpec
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def get_sources(src:
|
|
14
|
+
def get_sources(src: Collection[str]) -> list[Path]:
|
|
15
15
|
"""
|
|
16
16
|
Return a list of sources to codemod.
|
|
17
17
|
|
|
@@ -33,7 +33,7 @@ def get_sources(src: Iterable[str]) -> list[Path]:
|
|
|
33
33
|
return sorted(sources)
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
def find_project_root(sources:
|
|
36
|
+
def find_project_root(sources: Collection[str]) -> Path:
|
|
37
37
|
"""
|
|
38
38
|
Return a directory containing .git, .hg, or pyproject.toml.
|
|
39
39
|
|
|
@@ -29,6 +29,7 @@ from .models import (
|
|
|
29
29
|
ModelsPermalinkTransformer,
|
|
30
30
|
NullBooleanFieldTransformer,
|
|
31
31
|
OnDeleteTransformer,
|
|
32
|
+
QuerySetDateFieldTransformer,
|
|
32
33
|
)
|
|
33
34
|
from .os_utils import AbsPathTransformer
|
|
34
35
|
from .paginator import QuerySetPaginatorTransformer
|
|
@@ -88,6 +89,7 @@ __all__ = (
|
|
|
88
89
|
"OnDeleteTransformer",
|
|
89
90
|
"PrettyNameTransformer",
|
|
90
91
|
"QueryEmptyResultSetTransformer",
|
|
92
|
+
"QuerySetDateFieldTransformer",
|
|
91
93
|
"QuerySetPaginatorTransformer",
|
|
92
94
|
"RenderToResponseTransformer",
|
|
93
95
|
"RequestContextTransformer",
|
|
@@ -267,7 +267,10 @@ class BaseRenameTransformer(BaseDjCodemodTransformer, ABC):
|
|
|
267
267
|
|
|
268
268
|
def resolve_scope(self, node: CSTNode) -> Scope:
|
|
269
269
|
scopes_map = self.context.wrapper.resolve(ScopeProvider) # type: ignore
|
|
270
|
-
|
|
270
|
+
scope = scopes_map[node]
|
|
271
|
+
if scope is None:
|
|
272
|
+
raise KeyError(f"Scope not found for node {node}")
|
|
273
|
+
return scope
|
|
271
274
|
|
|
272
275
|
def save_import_scope(self, import_from: ImportFrom) -> None:
|
|
273
276
|
scope = self.resolve_scope(import_from)
|
|
@@ -2,10 +2,12 @@ from collections.abc import Sequence
|
|
|
2
2
|
|
|
3
3
|
from libcst import (
|
|
4
4
|
Arg,
|
|
5
|
+
AssignEqual,
|
|
5
6
|
BaseExpression,
|
|
6
7
|
BaseSmallStatement,
|
|
7
8
|
BaseStatement,
|
|
8
9
|
Call,
|
|
10
|
+
ConcatenatedString,
|
|
9
11
|
FlattenSentinel,
|
|
10
12
|
FunctionDef,
|
|
11
13
|
ImportFrom,
|
|
@@ -15,6 +17,8 @@ from libcst import (
|
|
|
15
17
|
RemovalSentinel,
|
|
16
18
|
RemoveFromParent,
|
|
17
19
|
Return,
|
|
20
|
+
SimpleString,
|
|
21
|
+
SimpleWhitespace,
|
|
18
22
|
)
|
|
19
23
|
from libcst import matchers as m
|
|
20
24
|
from libcst.codemod.visitors import AddImportsVisitor
|
|
@@ -24,6 +28,7 @@ from django_codemod.constants import (
|
|
|
24
28
|
DJANGO_1_11,
|
|
25
29
|
DJANGO_2_0,
|
|
26
30
|
DJANGO_2_1,
|
|
31
|
+
DJANGO_3_0,
|
|
27
32
|
DJANGO_3_1,
|
|
28
33
|
DJANGO_4_0,
|
|
29
34
|
)
|
|
@@ -214,3 +219,49 @@ class NullBooleanFieldTransformer(BaseFuncRenameTransformer):
|
|
|
214
219
|
*node.args,
|
|
215
220
|
parse_arg("null=True"),
|
|
216
221
|
)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class QuerySetDateFieldTransformer(BaseDjCodemodTransformer):
|
|
225
|
+
"""Pass literal field names positionally to `earliest()` and `latest()`."""
|
|
226
|
+
|
|
227
|
+
deprecated_in = DJANGO_2_0
|
|
228
|
+
removed_in = DJANGO_3_0
|
|
229
|
+
|
|
230
|
+
def leave_Call(self, original_node: Call, updated_node: Call) -> BaseExpression:
|
|
231
|
+
if not m.matches(
|
|
232
|
+
updated_node.func,
|
|
233
|
+
m.Attribute(attr=m.Name("earliest") | m.Name("latest")),
|
|
234
|
+
):
|
|
235
|
+
return updated_node
|
|
236
|
+
arg = find_keyword_arg(updated_node.args, "field_name")
|
|
237
|
+
if arg is None:
|
|
238
|
+
return updated_node
|
|
239
|
+
if not isinstance(
|
|
240
|
+
arg.value, (SimpleString, ConcatenatedString)
|
|
241
|
+
) or not isinstance(arg.value.evaluated_value, str):
|
|
242
|
+
self.warn(
|
|
243
|
+
"Cannot safely rewrite non-literal field_name in earliest()/latest(); "
|
|
244
|
+
"review this call manually."
|
|
245
|
+
)
|
|
246
|
+
return updated_node
|
|
247
|
+
if len(updated_node.args) != 1:
|
|
248
|
+
return updated_node
|
|
249
|
+
if isinstance(arg.equal, AssignEqual) and (
|
|
250
|
+
any(
|
|
251
|
+
not isinstance(whitespace, SimpleWhitespace)
|
|
252
|
+
or "\n" in whitespace.value
|
|
253
|
+
or "\r" in whitespace.value
|
|
254
|
+
for whitespace in (
|
|
255
|
+
arg.equal.whitespace_before,
|
|
256
|
+
arg.equal.whitespace_after,
|
|
257
|
+
)
|
|
258
|
+
)
|
|
259
|
+
):
|
|
260
|
+
self.warn(
|
|
261
|
+
"Cannot safely rewrite field_name with comments or line breaks "
|
|
262
|
+
"around '=' in earliest()/latest(); review this call manually."
|
|
263
|
+
)
|
|
264
|
+
return updated_node
|
|
265
|
+
return updated_node.with_changes(
|
|
266
|
+
args=[arg.with_changes(keyword=None, equal=MaybeSentinel.DEFAULT)]
|
|
267
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-codemod
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.6.0
|
|
4
4
|
Summary: A command line tool to automatically fix Django deprecations.
|
|
5
5
|
Author-email: Bruno Alla <alla.brunoo@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,7 +26,7 @@ Classifier: Topic :: Software Development :: Libraries
|
|
|
26
26
|
Requires-Python: >=3.10
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
28
28
|
License-File: LICENSE
|
|
29
|
-
Requires-Dist: click<8.
|
|
29
|
+
Requires-Dist: click<8.6
|
|
30
30
|
Requires-Dist: libcst==1.9
|
|
31
31
|
Requires-Dist: pathspec<2,>=0.6
|
|
32
32
|
Requires-Dist: rich>=10
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from libcst.codemod import CodemodTest
|
|
1
|
+
from libcst.codemod import CodemodContext, CodemodTest
|
|
2
2
|
|
|
3
3
|
from django_codemod.commands import BaseCodemodCommand
|
|
4
4
|
from django_codemod.visitors.base import BaseDjCodemodTransformer
|
|
@@ -9,6 +9,8 @@ class BaseVisitorTest(CodemodTest):
|
|
|
9
9
|
|
|
10
10
|
transformer: type[BaseDjCodemodTransformer]
|
|
11
11
|
|
|
12
|
-
def TRANSFORM(
|
|
12
|
+
def TRANSFORM( # ty: ignore[invalid-attribute-override]
|
|
13
|
+
self, context: CodemodContext
|
|
14
|
+
) -> BaseCodemodCommand:
|
|
13
15
|
"""Create a command for the transformer under test."""
|
|
14
16
|
return BaseCodemodCommand([self.transformer], context)
|
|
@@ -5,6 +5,7 @@ from django_codemod.visitors.models import (
|
|
|
5
5
|
ModelsPermalinkTransformer,
|
|
6
6
|
NullBooleanFieldTransformer,
|
|
7
7
|
OnDeleteTransformer,
|
|
8
|
+
QuerySetDateFieldTransformer,
|
|
8
9
|
)
|
|
9
10
|
from tests.visitors.base import BaseVisitorTest
|
|
10
11
|
|
|
@@ -382,3 +383,96 @@ class TestNullBooleanFieldTransformer(BaseVisitorTest):
|
|
|
382
383
|
is_active = models.BooleanField(null=True)
|
|
383
384
|
"""
|
|
384
385
|
self.assertCodemod(before, after)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class TestQuerySetDateFieldTransformer(BaseVisitorTest):
|
|
389
|
+
transformer = QuerySetDateFieldTransformer
|
|
390
|
+
|
|
391
|
+
@parameterized.expand([("earliest",), ("latest",)])
|
|
392
|
+
def test_literal_field(self, method):
|
|
393
|
+
self.assertCodemod(
|
|
394
|
+
f"result = Article.objects.{method}(field_name='pub_date')",
|
|
395
|
+
f"result = Article.objects.{method}('pub_date')",
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
def test_chained_multiline_call(self):
|
|
399
|
+
self.assertCodemod(
|
|
400
|
+
"""
|
|
401
|
+
result = Article.objects.filter(published=True).latest(
|
|
402
|
+
field_name = "pub_date", # Keep the field comment.
|
|
403
|
+
)
|
|
404
|
+
""",
|
|
405
|
+
"""
|
|
406
|
+
result = Article.objects.filter(published=True).latest(
|
|
407
|
+
"pub_date", # Keep the field comment.
|
|
408
|
+
)
|
|
409
|
+
""",
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
@parameterized.expand(
|
|
413
|
+
[
|
|
414
|
+
("qs.latest()",),
|
|
415
|
+
("qs.earliest('pub_date')",),
|
|
416
|
+
("qs.in_bulk(field_name='slug')",),
|
|
417
|
+
("latest(field_name='pub_date')",),
|
|
418
|
+
("qs.latest(**kwargs)",),
|
|
419
|
+
("qs.latest('pub_date', field_name='created')",),
|
|
420
|
+
]
|
|
421
|
+
)
|
|
422
|
+
def test_other_calls_unchanged(self, source):
|
|
423
|
+
self.assertCodemod(source, source)
|
|
424
|
+
|
|
425
|
+
@parameterized.expand(
|
|
426
|
+
[
|
|
427
|
+
(extra_args, value)
|
|
428
|
+
for extra_args in ("", "'other', ", "**kwargs, ")
|
|
429
|
+
for value in (
|
|
430
|
+
"None",
|
|
431
|
+
"field",
|
|
432
|
+
"get_field()",
|
|
433
|
+
"b'pub_date'",
|
|
434
|
+
"f'{field}'",
|
|
435
|
+
"'pub_' f'{field}'",
|
|
436
|
+
"b'pub_' b'date'",
|
|
437
|
+
)
|
|
438
|
+
]
|
|
439
|
+
)
|
|
440
|
+
def test_non_literal_requires_review(self, extra_args, value):
|
|
441
|
+
source = f"qs.latest({extra_args}field_name={value})"
|
|
442
|
+
self.assertCodemod(
|
|
443
|
+
source,
|
|
444
|
+
source,
|
|
445
|
+
expected_warnings=[
|
|
446
|
+
"Cannot safely rewrite non-literal field_name in earliest()/latest(); "
|
|
447
|
+
"review this call manually."
|
|
448
|
+
],
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
@parameterized.expand([("earliest",), ("latest",)])
|
|
452
|
+
def test_adjacent_literal_strings(self, method):
|
|
453
|
+
self.assertCodemod(
|
|
454
|
+
f"qs.{method}(field_name=('pub_' 'date'))",
|
|
455
|
+
f"qs.{method}(('pub_' 'date'))",
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
@parameterized.expand(
|
|
459
|
+
[
|
|
460
|
+
(" # Before the equals.\n =",),
|
|
461
|
+
("= # After the equals.\n ",),
|
|
462
|
+
(" # Before.\n = # After.\n ",),
|
|
463
|
+
("=\n # On its own line.\n ",),
|
|
464
|
+
("=\n ",),
|
|
465
|
+
("= \\\n ",),
|
|
466
|
+
(" \\\n =",),
|
|
467
|
+
]
|
|
468
|
+
)
|
|
469
|
+
def test_multiline_keyword_requires_review(self, equal):
|
|
470
|
+
source = f"qs.latest(field_name{equal}'pub_date')"
|
|
471
|
+
self.assertCodemod(
|
|
472
|
+
source,
|
|
473
|
+
source,
|
|
474
|
+
expected_warnings=[
|
|
475
|
+
"Cannot safely rewrite field_name with comments or line breaks "
|
|
476
|
+
"around '=' in earliest()/latest(); review this call manually."
|
|
477
|
+
],
|
|
478
|
+
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.5.0"
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
|
|
3
|
-
set -xu
|
|
4
|
-
|
|
5
|
-
mkdir -p e2e
|
|
6
|
-
cd e2e
|
|
7
|
-
django-admin startproject djcme2e
|
|
8
|
-
cd djcme2e
|
|
9
|
-
django-admin startapp app1
|
|
10
|
-
|
|
11
|
-
echo "from django.db import models
|
|
12
|
-
from django.utils.encoding import force_text
|
|
13
|
-
from django.utils.translation import ugettext_lazy as _
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class AppModel(models.Model):
|
|
17
|
-
name = models.CharField(_('Name'))
|
|
18
|
-
slug = models.SlugField(_('Name'))
|
|
19
|
-
|
|
20
|
-
def __str__(self):
|
|
21
|
-
return force_text(self.name)
|
|
22
|
-
" > app1/models.py
|
|
23
|
-
|
|
24
|
-
cp -r ../djcme2e ../djcme2e_orig
|
|
25
|
-
|
|
26
|
-
djcodemod run --deprecated-in 3.0 .
|
|
27
|
-
|
|
28
|
-
cd ..
|
|
29
|
-
|
|
30
|
-
OUT=$(diff -qr djcme2e_orig/ djcme2e/ | grep -v 'models.py differ')
|
|
31
|
-
|
|
32
|
-
if [ "${OUT}" != "" ]
|
|
33
|
-
then
|
|
34
|
-
echo "ERROR: unexpected differences found:"
|
|
35
|
-
diff -r djcme2e_orig/ djcme2e/
|
|
36
|
-
exit 1
|
|
37
|
-
else
|
|
38
|
-
exit 0
|
|
39
|
-
fi
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/postgres_fields.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod/visitors/template_context.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{django_codemod-2.5.0 → django_codemod-2.6.0}/src/django_codemod.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|