From fc2ea6ec3ea4f6a3d96d0ce84d3ba69a14e15b46 Mon Sep 17 00:00:00 2001 From: MomIsBestFriend <> Date: Mon, 23 Mar 2020 17:38:23 +0200 Subject: [PATCH 1/3] REF: "bare_pytest_raises" now uses the ast module Now it uses the ast module instead of the tokenize module --- scripts/validate_unwanted_patterns.py | 50 ++++++++++++++++++++------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/scripts/validate_unwanted_patterns.py b/scripts/validate_unwanted_patterns.py index c4be85ffe7306..321f836bbdc93 100755 --- a/scripts/validate_unwanted_patterns.py +++ b/scripts/validate_unwanted_patterns.py @@ -11,11 +11,12 @@ """ import argparse +import ast import os import sys import token import tokenize -from typing import IO, Callable, Iterable, List, Tuple +from typing import IO, Callable, Iterable, List, Optional, Tuple FILE_EXTENSIONS_TO_CHECK: Tuple[str, ...] = (".py", ".pyx", ".pxi.ini", ".pxd") @@ -83,23 +84,48 @@ def bare_pytest_raises(file_obj: IO[str]) -> Iterable[Tuple[int, str]]: ----- GH #23922 """ - tokens: List = list(tokenize.generate_tokens(file_obj.readline)) - for counter, current_token in enumerate(tokens, start=1): - if not (current_token.type == token.NAME and current_token.string == "raises"): - continue - for next_token in tokens[counter:]: - if next_token.type == token.NAME and next_token.string == "match": + def get_fqdn(node: ast.AST) -> Optional[str]: + names: List[str] = [] + + while True: + if isinstance(node, ast.Name): + names.append(node.id) break - # token.NEWLINE refers to the end of a logical line - # unlike token.NL or "\n" which represents a newline - if next_token.type == token.NEWLINE: + + if isinstance(node, ast.Attribute): + names.append(node.attr) + node = node.value + else: + return None + + return ".".join(reversed(names)) + + contents = file_obj.read() + tree = ast.parse(contents) + + for node in ast.walk(tree): + if not isinstance(node, ast.Call): + continue + + if not get_fqdn(node.func) == "pytest.raises": + continue + + if not node.keywords: + yield ( + node.lineno, + "Bare pytests raise have been found. " + "Please pass in the argument 'match' as well the exception.", + ) + else: + # Means that there are arguments that are being passed in, + # now we validate that `match` is one of the passed in arguments + if not any(keyword.arg == "match" for keyword in node.keywords): yield ( - current_token.start[0], + node.lineno, "Bare pytests raise have been found. " "Please pass in the argument 'match' as well the exception.", ) - break def strings_to_concatenate(file_obj: IO[str]) -> Iterable[Tuple[int, str]]: From e901cb898d770b74e367d47c5148c18a549f7e5e Mon Sep 17 00:00:00 2001 From: MomIsBestFriend <> Date: Sun, 29 Mar 2020 15:15:10 +0300 Subject: [PATCH 2/3] Removed `get_fqdn` function XREF: https://github.com/pandas-dev/pandas/pull/32932#discussion_r399549382 --- scripts/validate_unwanted_patterns.py | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/scripts/validate_unwanted_patterns.py b/scripts/validate_unwanted_patterns.py index 321f836bbdc93..5247e41332166 100755 --- a/scripts/validate_unwanted_patterns.py +++ b/scripts/validate_unwanted_patterns.py @@ -84,23 +84,6 @@ def bare_pytest_raises(file_obj: IO[str]) -> Iterable[Tuple[int, str]]: ----- GH #23922 """ - - def get_fqdn(node: ast.AST) -> Optional[str]: - names: List[str] = [] - - while True: - if isinstance(node, ast.Name): - names.append(node.id) - break - - if isinstance(node, ast.Attribute): - names.append(node.attr) - node = node.value - else: - return None - - return ".".join(reversed(names)) - contents = file_obj.read() tree = ast.parse(contents) @@ -108,7 +91,10 @@ def get_fqdn(node: ast.AST) -> Optional[str]: if not isinstance(node, ast.Call): continue - if not get_fqdn(node.func) == "pytest.raises": + try: + if not (node.func.value.id == "pytest" and node.func.attr == "raises"): + continue + except AttributeError: continue if not node.keywords: From 60524fa305e81558d60f869bdcfcaf27f91978c1 Mon Sep 17 00:00:00 2001 From: MomIsBestFriend <> Date: Sun, 29 Mar 2020 15:36:27 +0300 Subject: [PATCH 3/3] Lint issues --- scripts/validate_unwanted_patterns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/validate_unwanted_patterns.py b/scripts/validate_unwanted_patterns.py index 5247e41332166..613423b3a9a35 100755 --- a/scripts/validate_unwanted_patterns.py +++ b/scripts/validate_unwanted_patterns.py @@ -16,7 +16,7 @@ import sys import token import tokenize -from typing import IO, Callable, Iterable, List, Optional, Tuple +from typing import IO, Callable, Iterable, List, Tuple FILE_EXTENSIONS_TO_CHECK: Tuple[str, ...] = (".py", ".pyx", ".pxi.ini", ".pxd")