From beb936611888d5c306fea2a56843983948291489 Mon Sep 17 00:00:00 2001 From: Alessandro Ferrini Date: Tue, 6 Feb 2024 16:50:54 +0100 Subject: [PATCH 01/18] fix issue #419 --- .../fixers/request_user_is_authenticated .py | 86 +++++++++ tests/fixers/test_is_authenticated.py | 175 ++++++++++++++++++ 2 files changed, 261 insertions(+) create mode 100644 src/django_upgrade/fixers/request_user_is_authenticated .py create mode 100644 tests/fixers/test_is_authenticated.py diff --git a/src/django_upgrade/fixers/request_user_is_authenticated .py b/src/django_upgrade/fixers/request_user_is_authenticated .py new file mode 100644 index 00000000..d6cbc918 --- /dev/null +++ b/src/django_upgrade/fixers/request_user_is_authenticated .py @@ -0,0 +1,86 @@ +""" +Update use of request.user.is_authenticated() to use request.user.is_authenticated +https://docs.djangoproject.com/en/1.10/releases/1.10/#using-user-is-authenticated-and-user-is-anonymous-as-methods +""" +from __future__ import annotations + +import ast +import sys +from functools import partial +from typing import Iterable + +from tokenize_rt import Offset +from tokenize_rt import Token + +from django_upgrade.ast import ast_start_offset +from django_upgrade.data import Fixer +from django_upgrade.data import State +from django_upgrade.data import TokenFunc +from django_upgrade.tokens import find +from django_upgrade.tokens import NAME +from django_upgrade.tokens import OP + + +fixer = Fixer( + __name__, + min_version=(1, 10), +) + + +@fixer.register(ast.Call) +def visit_Call( + state: State, + node: ast.Call, + parents: list[ast.AST], +) -> Iterable[tuple[Offset, TokenFunc]]: + if ( + isinstance(node.func, ast.Attribute) + and node.func.attr == "is_authenticated" + and is_request_user_or_self_request_user(node.func.value) + and len(node.args) == 0 + ): + yield ( + ast_start_offset(node), + partial(rewrite_user_is_auth), + ) + + +def is_request_user_or_self_request_user(node: ast.AST) -> bool: + return ( + isinstance(node, ast.Attribute) + and node.attr == "user" + and ( + (isinstance(node.value, ast.Name) and node.value.id == "request") + or ( + isinstance(node.value, ast.Attribute) + and isinstance(node.value.value, ast.Name) + and node.value.value.id == "self" + and node.value.attr == "request" + ) + ) + ) + + +if sys.version_info >= (3, 9): + + def extract_constant(node: ast.AST) -> str | None: + if isinstance(node, ast.Constant) and isinstance(node.value, str): + return node.value + return None + +else: + + def extract_constant(node: ast.AST) -> str | None: + if ( + isinstance(node, ast.Index) + and isinstance(node.value, ast.Constant) + and isinstance(node.value.value, str) + ): + return node.value.value + return None + + +def rewrite_user_is_auth(tokens: list[Token], i: int) -> None: + j = find(tokens, i, name=NAME, src="is_authenticated") + y = find(tokens, i, name=OP, src=")") + del tokens[j + 1 : y + 1] diff --git a/tests/fixers/test_is_authenticated.py b/tests/fixers/test_is_authenticated.py new file mode 100644 index 00000000..130974e8 --- /dev/null +++ b/tests/fixers/test_is_authenticated.py @@ -0,0 +1,175 @@ +from __future__ import annotations + +from django_upgrade.data import Settings +from tests.fixers.tools import check_noop +from tests.fixers.tools import check_transformed + +settings = Settings(target_version=(1, 10)) + + +def test_not_request(): + check_noop( + """\ + user.is_authenticated() + """, + settings, + ) + + +def test_not_self_request(): + check_noop( + """\ + self.user.is_authenticated() + """, + settings, + ) + + +def test_not_user(): + check_noop( + """\ + request.is_authenticated() + """, + settings, + ) + + +def test_not_self_user(): + check_noop( + """\ + self.request.is_authenticated() + """, + settings, + ) + + +def test_request_user_simple(): + check_transformed( + """\ + request.user.is_authenticated() + """, + """\ + request.user.is_authenticated + """, + settings, + ) + + +def test_self_request_user_simple(): + check_transformed( + """\ + self.request.user.is_authenticated() + """, + """\ + self.request.user.is_authenticated + """, + settings, + ) + + +def test_request_user_assigned(): + check_transformed( + """\ + auth = request.user.is_authenticated() + """, + """\ + auth = request.user.is_authenticated + """, + settings, + ) + + +def test_self_request_user_assigned(): + check_transformed( + """\ + auth = self.request.user.is_authenticated() + """, + """\ + auth = self.request.user.is_authenticated + """, + settings, + ) + + +def test_if_request_user(): + check_transformed( + """\ + if request.user.is_authenticated(): + ... + """, + """\ + if request.user.is_authenticated: + ... + """, + settings, + ) + + +def test_if_self_request_user(): + check_transformed( + """\ + if self.request.user.is_authenticated(): + ... + """, + """\ + if self.request.user.is_authenticated: + ... + """, + settings, + ) + + +def test_if_request_user_warlus(): + check_transformed( + """\ + if auth:= request.user.is_authenticated(): + ... + """, + """\ + if auth:= request.user.is_authenticated: + ... + """, + settings, + ) + + +def test_if_self_request_user_warlus(): + check_transformed( + """\ + if auth:= self.request.user.is_authenticated(): + ... + """, + """\ + if auth:= self.request.user.is_authenticated: + ... + """, + settings, + ) + + +def test_if_request_user_equal(): + check_transformed( + """\ + if request.user.is_authenticated() == True: + ... + """, + """\ + if request.user.is_authenticated == True: + ... + """, + settings, + ) + + +def test_if_self_request_user_equal(): + check_transformed( + """\ + if request.user.is_authenticated() == True: + ... + """, + """\ + if request.user.is_authenticated == True: + ... + """, + settings, + ) From c2af2667abd21f2bca4d752f184576577f4ab882 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 16:03:30 +0000 Subject: [PATCH 02/18] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../fixers/request_user_is_authenticated .py | 2 +- tests/fixers/test_is_authenticated.py | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/django_upgrade/fixers/request_user_is_authenticated .py b/src/django_upgrade/fixers/request_user_is_authenticated .py index d6cbc918..cdb9486f 100644 --- a/src/django_upgrade/fixers/request_user_is_authenticated .py +++ b/src/django_upgrade/fixers/request_user_is_authenticated .py @@ -1,5 +1,5 @@ """ -Update use of request.user.is_authenticated() to use request.user.is_authenticated +Update use of request.user.is_authenticated() to use request.user.is_authenticated https://docs.djangoproject.com/en/1.10/releases/1.10/#using-user-is-authenticated-and-user-is-anonymous-as-methods """ from __future__ import annotations diff --git a/tests/fixers/test_is_authenticated.py b/tests/fixers/test_is_authenticated.py index 130974e8..d4c96932 100644 --- a/tests/fixers/test_is_authenticated.py +++ b/tests/fixers/test_is_authenticated.py @@ -95,11 +95,11 @@ def test_if_request_user(): check_transformed( """\ if request.user.is_authenticated(): - ... + ... """, """\ if request.user.is_authenticated: - ... + ... """, settings, ) @@ -109,11 +109,11 @@ def test_if_self_request_user(): check_transformed( """\ if self.request.user.is_authenticated(): - ... + ... """, """\ if self.request.user.is_authenticated: - ... + ... """, settings, ) @@ -123,11 +123,11 @@ def test_if_request_user_warlus(): check_transformed( """\ if auth:= request.user.is_authenticated(): - ... + ... """, """\ if auth:= request.user.is_authenticated: - ... + ... """, settings, ) @@ -137,11 +137,11 @@ def test_if_self_request_user_warlus(): check_transformed( """\ if auth:= self.request.user.is_authenticated(): - ... + ... """, """\ if auth:= self.request.user.is_authenticated: - ... + ... """, settings, ) @@ -151,11 +151,11 @@ def test_if_request_user_equal(): check_transformed( """\ if request.user.is_authenticated() == True: - ... + ... """, """\ if request.user.is_authenticated == True: - ... + ... """, settings, ) @@ -165,11 +165,11 @@ def test_if_self_request_user_equal(): check_transformed( """\ if request.user.is_authenticated() == True: - ... + ... """, """\ if request.user.is_authenticated == True: - ... + ... """, settings, ) From 5e39d6479049f64f46cf2e1a3b2e50c3def6a3da Mon Sep 17 00:00:00 2001 From: Alessandro Ferrini Date: Wed, 7 Feb 2024 09:07:05 +0100 Subject: [PATCH 03/18] fix: removed unused code --- .../fixers/request_user_is_authenticated .py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/django_upgrade/fixers/request_user_is_authenticated .py b/src/django_upgrade/fixers/request_user_is_authenticated .py index cdb9486f..40d8f0b1 100644 --- a/src/django_upgrade/fixers/request_user_is_authenticated .py +++ b/src/django_upgrade/fixers/request_user_is_authenticated .py @@ -61,25 +61,6 @@ def is_request_user_or_self_request_user(node: ast.AST) -> bool: ) -if sys.version_info >= (3, 9): - - def extract_constant(node: ast.AST) -> str | None: - if isinstance(node, ast.Constant) and isinstance(node.value, str): - return node.value - return None - -else: - - def extract_constant(node: ast.AST) -> str | None: - if ( - isinstance(node, ast.Index) - and isinstance(node.value, ast.Constant) - and isinstance(node.value.value, str) - ): - return node.value.value - return None - - def rewrite_user_is_auth(tokens: list[Token], i: int) -> None: j = find(tokens, i, name=NAME, src="is_authenticated") y = find(tokens, i, name=OP, src=")") From 87c35e20fd09b99c6b016ce820e8c0fbc90c98e4 Mon Sep 17 00:00:00 2001 From: Alessandro Ferrini Date: Sat, 10 Feb 2024 12:08:43 +0100 Subject: [PATCH 04/18] fix: remove unused import --- src/django_upgrade/fixers/request_user_is_authenticated .py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/django_upgrade/fixers/request_user_is_authenticated .py b/src/django_upgrade/fixers/request_user_is_authenticated .py index 40d8f0b1..19196f36 100644 --- a/src/django_upgrade/fixers/request_user_is_authenticated .py +++ b/src/django_upgrade/fixers/request_user_is_authenticated .py @@ -5,7 +5,6 @@ from __future__ import annotations import ast -import sys from functools import partial from typing import Iterable From 561ce2c9b4496686743a47f1eca4fbd437d4ad7b Mon Sep 17 00:00:00 2001 From: Alessandro Ferrini Date: Sat, 10 Feb 2024 12:09:37 +0100 Subject: [PATCH 05/18] fix: remove whitespace in filename --- ...user_is_authenticated .py => request_user_is_authenticated.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/django_upgrade/fixers/{request_user_is_authenticated .py => request_user_is_authenticated.py} (100%) diff --git a/src/django_upgrade/fixers/request_user_is_authenticated .py b/src/django_upgrade/fixers/request_user_is_authenticated.py similarity index 100% rename from src/django_upgrade/fixers/request_user_is_authenticated .py rename to src/django_upgrade/fixers/request_user_is_authenticated.py From b1d4302aa3aca9af049c1f02e4ee27dfe335fbae Mon Sep 17 00:00:00 2001 From: Alessandro Ferrini Date: Sat, 10 Feb 2024 12:17:10 +0100 Subject: [PATCH 06/18] add new testcases to check spaces between --- tests/fixers/test_is_authenticated.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/fixers/test_is_authenticated.py b/tests/fixers/test_is_authenticated.py index d4c96932..8bc97a7b 100644 --- a/tests/fixers/test_is_authenticated.py +++ b/tests/fixers/test_is_authenticated.py @@ -173,3 +173,18 @@ def test_if_self_request_user_equal(): """, settings, ) + + +def test_spaces_between_noop(): + check_noop( + "request . user . is_authenticated ", + settings, + ) + + +def test_spaces_between(): + check_transformed( + "request . user . is_authenticated ( )", + "request . user . is_authenticated ", + settings, + ) From 981550d0a179cf8c184f45bd2f660d3863247cc8 Mon Sep 17 00:00:00 2001 From: Alessandro Ferrini Date: Sun, 11 Feb 2024 10:44:01 +0100 Subject: [PATCH 07/18] add new testaces to check spaces and comments --- tests/fixers/test_is_authenticated.py | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/tests/fixers/test_is_authenticated.py b/tests/fixers/test_is_authenticated.py index 8bc97a7b..03db10f5 100644 --- a/tests/fixers/test_is_authenticated.py +++ b/tests/fixers/test_is_authenticated.py @@ -188,3 +188,41 @@ def test_spaces_between(): "request . user . is_authenticated ", settings, ) + + +def test_spaces_and_comments(): + check_transformed( + """\ + if ( + request + .user + .is_authenticated # bla + () # bla + ): + ... + """, + """\ + if ( + request + .user + .is_authenticated # bla + # bla + ): + ... + """, + settings, + ) + + +def test_spaces_and_comments_noop(): + check_noop( + """\ + if ( + request + .user + .is_authenticated # bla + ): + ... + """, + settings, + ) From d046dd829f283d7760dde93c20b45c94390766a5 Mon Sep 17 00:00:00 2001 From: Alessandro Ferrini Date: Sun, 11 Feb 2024 10:44:56 +0100 Subject: [PATCH 08/18] update rewrite function --- src/django_upgrade/fixers/request_user_is_authenticated.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/django_upgrade/fixers/request_user_is_authenticated.py b/src/django_upgrade/fixers/request_user_is_authenticated.py index 19196f36..4f76c16e 100644 --- a/src/django_upgrade/fixers/request_user_is_authenticated.py +++ b/src/django_upgrade/fixers/request_user_is_authenticated.py @@ -62,5 +62,7 @@ def is_request_user_or_self_request_user(node: ast.AST) -> bool: def rewrite_user_is_auth(tokens: list[Token], i: int) -> None: j = find(tokens, i, name=NAME, src="is_authenticated") - y = find(tokens, i, name=OP, src=")") - del tokens[j + 1 : y + 1] + y = find(tokens, j, name=OP, src="(") + z = find(tokens, y, name=OP, src=")") + del tokens[z] + del tokens[y] From bfb65f4d7e5e543f7ac78049f0a7eb7760a6e98e Mon Sep 17 00:00:00 2001 From: Alessandro Ferrini Date: Sun, 11 Feb 2024 11:21:22 +0100 Subject: [PATCH 09/18] update README and CHANGELOG --- CHANGELOG.rst | 4 ++++ README.rst | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cf8acc98..bbf6e61e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,10 @@ Changelog ========= +* Add Django 1.10 fixer to rewrite ``user.is_authenticated()`` -> ``user.is_authenticated``. + + Thanks to Alessandro Ferrini in `PR #423 `__. + 1.15.0 (2023-09-24) ------------------- diff --git a/README.rst b/README.rst index 5fe30408..0cb49fa8 100644 --- a/README.rst +++ b/README.rst @@ -321,6 +321,15 @@ Whilst mentioned in the `Django 2.1 release notes Date: Sun, 11 Feb 2024 10:22:07 +0000 Subject: [PATCH 10/18] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/django_upgrade/fixers/request_user_is_authenticated.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/django_upgrade/fixers/request_user_is_authenticated.py b/src/django_upgrade/fixers/request_user_is_authenticated.py index 4f76c16e..65c0a99c 100644 --- a/src/django_upgrade/fixers/request_user_is_authenticated.py +++ b/src/django_upgrade/fixers/request_user_is_authenticated.py @@ -2,6 +2,7 @@ Update use of request.user.is_authenticated() to use request.user.is_authenticated https://docs.djangoproject.com/en/1.10/releases/1.10/#using-user-is-authenticated-and-user-is-anonymous-as-methods """ + from __future__ import annotations import ast @@ -15,10 +16,9 @@ from django_upgrade.data import Fixer from django_upgrade.data import State from django_upgrade.data import TokenFunc -from django_upgrade.tokens import find from django_upgrade.tokens import NAME from django_upgrade.tokens import OP - +from django_upgrade.tokens import find fixer = Fixer( __name__, From e7fca01d89a7bd35aab571a8d55e8e3163160263 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 11 Feb 2024 17:34:24 +0000 Subject: [PATCH 11/18] Apply suggestions from code review --- README.rst | 11 +++++++---- .../fixers/request_user_is_authenticated.py | 9 ++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/README.rst b/README.rst index 0cb49fa8..a5db918a 100644 --- a/README.rst +++ b/README.rst @@ -321,15 +321,18 @@ Whilst mentioned in the `Django 2.1 release notes `__. .. code-block:: diff - -user.is_authenticated() - +user.is_authenticated + -request.user.is_authenticated() + +requestuser.is_authenticated + + -self.request.user.is_anonymous() + +self.request.user.is_anonymous Django 1.11 ----------- diff --git a/src/django_upgrade/fixers/request_user_is_authenticated.py b/src/django_upgrade/fixers/request_user_is_authenticated.py index 65c0a99c..47e0e760 100644 --- a/src/django_upgrade/fixers/request_user_is_authenticated.py +++ b/src/django_upgrade/fixers/request_user_is_authenticated.py @@ -34,13 +34,13 @@ def visit_Call( ) -> Iterable[tuple[Offset, TokenFunc]]: if ( isinstance(node.func, ast.Attribute) - and node.func.attr == "is_authenticated" + and node.func.attr in ("is_anonymous", "is_authenticated") and is_request_user_or_self_request_user(node.func.value) and len(node.args) == 0 ): yield ( ast_start_offset(node), - partial(rewrite_user_is_auth), + partial(rewrite_user_attribute), ) @@ -60,9 +60,8 @@ def is_request_user_or_self_request_user(node: ast.AST) -> bool: ) -def rewrite_user_is_auth(tokens: list[Token], i: int) -> None: +def rewrite_user_attribute(tokens: list[Token], i: int) -> None: j = find(tokens, i, name=NAME, src="is_authenticated") y = find(tokens, j, name=OP, src="(") z = find(tokens, y, name=OP, src=")") - del tokens[z] - del tokens[y] + del tokens[y:z+1] From e375f0b88afb50e4e370217a804fc571d188b925 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 11 Feb 2024 17:40:50 +0000 Subject: [PATCH 12/18] Improve README section --- README.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.rst b/README.rst index a5db918a..bd59cec9 100644 --- a/README.rst +++ b/README.rst @@ -306,6 +306,19 @@ Django 1.10 `Release Notes `__ +``request.user`` boolean attributes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Rewrites calls to ``request.user.is_authenticated()`` and ``request.user.is_anonymous()`` to remove the parentheses, per `the deprecation `__. + +.. code-block:: diff + + -request.user.is_authenticated() + +request.user.is_authenticated + + -self.request.user.is_anonymous() + +self.request.user.is_anonymous + Compatibility imports ~~~~~~~~~~~~~~~~~~~~~ @@ -321,19 +334,6 @@ Whilst mentioned in the `Django 2.1 release notes `__. - -.. code-block:: diff - - -request.user.is_authenticated() - +requestuser.is_authenticated - - -self.request.user.is_anonymous() - +self.request.user.is_anonymous - Django 1.11 ----------- From 19e817581826833816e9a5490a741cefd21a2127 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 11 Feb 2024 17:41:13 +0000 Subject: [PATCH 13/18] Rename fixer and test file --- ..._authenticated.py => request_user_attributes.py} | 13 +++++++------ ...enticated.py => test_request_user_attributes.py} | 0 2 files changed, 7 insertions(+), 6 deletions(-) rename src/django_upgrade/fixers/{request_user_is_authenticated.py => request_user_attributes.py} (82%) rename tests/fixers/{test_is_authenticated.py => test_request_user_attributes.py} (100%) diff --git a/src/django_upgrade/fixers/request_user_is_authenticated.py b/src/django_upgrade/fixers/request_user_attributes.py similarity index 82% rename from src/django_upgrade/fixers/request_user_is_authenticated.py rename to src/django_upgrade/fixers/request_user_attributes.py index 47e0e760..060027c2 100644 --- a/src/django_upgrade/fixers/request_user_is_authenticated.py +++ b/src/django_upgrade/fixers/request_user_attributes.py @@ -35,16 +35,16 @@ def visit_Call( if ( isinstance(node.func, ast.Attribute) and node.func.attr in ("is_anonymous", "is_authenticated") - and is_request_user_or_self_request_user(node.func.value) + and is_request_or_self_request_user(node.func.value) and len(node.args) == 0 ): yield ( ast_start_offset(node), - partial(rewrite_user_attribute), + partial(rewrite_user_attribute, attr=node.func.attr), ) -def is_request_user_or_self_request_user(node: ast.AST) -> bool: +def is_request_or_self_request_user(node: ast.AST) -> bool: return ( isinstance(node, ast.Attribute) and node.attr == "user" @@ -60,8 +60,9 @@ def is_request_user_or_self_request_user(node: ast.AST) -> bool: ) -def rewrite_user_attribute(tokens: list[Token], i: int) -> None: - j = find(tokens, i, name=NAME, src="is_authenticated") +def rewrite_user_attribute(tokens: list[Token], i: int, *, attr: str) -> None: + j = find(tokens, i, name=NAME, src=attr) y = find(tokens, j, name=OP, src="(") z = find(tokens, y, name=OP, src=")") - del tokens[y:z+1] + del tokens[z] + del tokens[y] diff --git a/tests/fixers/test_is_authenticated.py b/tests/fixers/test_request_user_attributes.py similarity index 100% rename from tests/fixers/test_is_authenticated.py rename to tests/fixers/test_request_user_attributes.py From 0f9ba24cc5b397314c78495e92e7d80520009386 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 11 Feb 2024 21:50:37 +0000 Subject: [PATCH 14/18] Improve tests - add more coverage, remove unnecessary ones --- tests/fixers/test_request_user_attributes.py | 96 +++++++------------- 1 file changed, 34 insertions(+), 62 deletions(-) diff --git a/tests/fixers/test_request_user_attributes.py b/tests/fixers/test_request_user_attributes.py index 03db10f5..dd409c66 100644 --- a/tests/fixers/test_request_user_attributes.py +++ b/tests/fixers/test_request_user_attributes.py @@ -43,132 +43,104 @@ def test_not_self_user(): ) -def test_request_user_simple(): +def test_request_user_is_anonymous_simple(): check_transformed( """\ - request.user.is_authenticated() + request.user.is_anonymous() """, """\ - request.user.is_authenticated + request.user.is_anonymous """, settings, ) -def test_self_request_user_simple(): +def test_request_user_is_authenticated_simple(): check_transformed( """\ - self.request.user.is_authenticated() - """, - """\ - self.request.user.is_authenticated - """, - settings, - ) - - -def test_request_user_assigned(): - check_transformed( - """\ - auth = request.user.is_authenticated() - """, - """\ - auth = request.user.is_authenticated - """, - settings, - ) - - -def test_self_request_user_assigned(): - check_transformed( - """\ - auth = self.request.user.is_authenticated() + request.user.is_authenticated() """, """\ - auth = self.request.user.is_authenticated + request.user.is_authenticated """, settings, ) -def test_if_request_user(): +def test_self_request_user_is_anonymous_simple(): check_transformed( """\ - if request.user.is_authenticated(): - ... + self.request.user.is_anonymous() """, """\ - if request.user.is_authenticated: - ... + self.request.user.is_anonymous """, settings, ) -def test_if_self_request_user(): +def test_self_request_user_is_authenticated_simple(): check_transformed( """\ - if self.request.user.is_authenticated(): - ... + self.request.user.is_authenticated() """, """\ - if self.request.user.is_authenticated: - ... + self.request.user.is_authenticated """, settings, ) -def test_if_request_user_warlus(): +def test_if_request_user_is_anonymous(): check_transformed( """\ - if auth:= request.user.is_authenticated(): + if request.user.is_anonymous(): ... """, """\ - if auth:= request.user.is_authenticated: + if request.user.is_anonymous: ... """, settings, ) -def test_if_self_request_user_warlus(): +def test_if_request_user_is_authenticated(): check_transformed( """\ - if auth:= self.request.user.is_authenticated(): + if request.user.is_authenticated(): ... """, """\ - if auth:= self.request.user.is_authenticated: + if request.user.is_authenticated: ... """, settings, ) -def test_if_request_user_equal(): +def test_if_self_request_user_is_anonymous(): check_transformed( """\ - if request.user.is_authenticated() == True: + if self.request.user.is_anonymous(): ... """, """\ - if request.user.is_authenticated == True: + if self.request.user.is_anonymous: ... """, settings, ) -def test_if_self_request_user_equal(): +def test_if_self_request_user_is_authenticated(): check_transformed( """\ - if request.user.is_authenticated() == True: + if self.request.user.is_authenticated(): ... """, """\ - if request.user.is_authenticated == True: + if self.request.user.is_authenticated: ... """, settings, @@ -190,37 +162,37 @@ def test_spaces_between(): ) -def test_spaces_and_comments(): - check_transformed( +def test_spaces_and_comments_noop(): + check_noop( """\ if ( request .user .is_authenticated # bla - () # bla ): ... """, + settings, + ) + + +def test_spaces_and_comments(): + check_transformed( """\ if ( request .user .is_authenticated # bla - # bla + () # bla ): ... """, - settings, - ) - - -def test_spaces_and_comments_noop(): - check_noop( """\ if ( request .user .is_authenticated # bla + # bla ): ... """, From 5c0b9915536ed9abb771319cec278bee17c423cb Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 11 Feb 2024 21:52:17 +0000 Subject: [PATCH 15/18] Delete token range --- .../fixers/request_user_attributes.py | 3 +-- tests/fixers/test_request_user_attributes.py | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/django_upgrade/fixers/request_user_attributes.py b/src/django_upgrade/fixers/request_user_attributes.py index 060027c2..234bfe86 100644 --- a/src/django_upgrade/fixers/request_user_attributes.py +++ b/src/django_upgrade/fixers/request_user_attributes.py @@ -64,5 +64,4 @@ def rewrite_user_attribute(tokens: list[Token], i: int, *, attr: str) -> None: j = find(tokens, i, name=NAME, src=attr) y = find(tokens, j, name=OP, src="(") z = find(tokens, y, name=OP, src=")") - del tokens[z] - del tokens[y] + del tokens[y : z + 1] diff --git a/tests/fixers/test_request_user_attributes.py b/tests/fixers/test_request_user_attributes.py index dd409c66..adfca96a 100644 --- a/tests/fixers/test_request_user_attributes.py +++ b/tests/fixers/test_request_user_attributes.py @@ -149,7 +149,7 @@ def test_if_self_request_user_is_authenticated(): def test_spaces_between_noop(): check_noop( - "request . user . is_authenticated ", + "request . user . is_authenticated ", settings, ) @@ -157,7 +157,20 @@ def test_spaces_between_noop(): def test_spaces_between(): check_transformed( "request . user . is_authenticated ( )", - "request . user . is_authenticated ", + "request . user . is_authenticated ", + settings, + ) + + +def test_comment_between(): + check_transformed( + """\ + request.user.is_anonymous( # something + ) + """, + """\ + request.user.is_anonymous + """, settings, ) From 00c05f53b1481d31674847e500b63986b6e92d75 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 11 Feb 2024 21:56:18 +0000 Subject: [PATCH 16/18] Improve docs --- CHANGELOG.rst | 2 +- README.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bbf6e61e..36740558 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,7 +2,7 @@ Changelog ========= -* Add Django 1.10 fixer to rewrite ``user.is_authenticated()`` -> ``user.is_authenticated``. +* Add Django 1.10+ fixer to rewrite ``request.user`` functions that changed to boolean attributes: ``is_authenticated`` and ``is_anonymous``. Thanks to Alessandro Ferrini in `PR #423 `__. diff --git a/README.rst b/README.rst index bd59cec9..224f8cfc 100644 --- a/README.rst +++ b/README.rst @@ -307,7 +307,7 @@ Django 1.10 `Release Notes `__ ``request.user`` boolean attributes -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Rewrites calls to ``request.user.is_authenticated()`` and ``request.user.is_anonymous()`` to remove the parentheses, per `the deprecation `__. From 7c170aac5487eb2e4b5d4e3d2acbc448ad72aaa3 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 11 Feb 2024 21:59:37 +0000 Subject: [PATCH 17/18] Update docstring --- src/django_upgrade/fixers/request_user_attributes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/django_upgrade/fixers/request_user_attributes.py b/src/django_upgrade/fixers/request_user_attributes.py index 234bfe86..f45450a0 100644 --- a/src/django_upgrade/fixers/request_user_attributes.py +++ b/src/django_upgrade/fixers/request_user_attributes.py @@ -1,5 +1,7 @@ """ -Update use of request.user.is_authenticated() to use request.user.is_authenticated +Update use of request.user methods is_anonymous() and is_authenticated() to +attribute accesses. + https://docs.djangoproject.com/en/1.10/releases/1.10/#using-user-is-authenticated-and-user-is-anonymous-as-methods """ From b24245ac35f97c3206a659c6799baac121b6d9e4 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 11 Feb 2024 22:00:12 +0000 Subject: [PATCH 18/18] Reorder for slight optimization --- src/django_upgrade/fixers/request_user_attributes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/django_upgrade/fixers/request_user_attributes.py b/src/django_upgrade/fixers/request_user_attributes.py index f45450a0..3b2af748 100644 --- a/src/django_upgrade/fixers/request_user_attributes.py +++ b/src/django_upgrade/fixers/request_user_attributes.py @@ -37,8 +37,8 @@ def visit_Call( if ( isinstance(node.func, ast.Attribute) and node.func.attr in ("is_anonymous", "is_authenticated") - and is_request_or_self_request_user(node.func.value) and len(node.args) == 0 + and is_request_or_self_request_user(node.func.value) ): yield ( ast_start_offset(node),