Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ci/code_checks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,14 @@ if [[ -z "$CHECK" || "$CHECK" == "patterns" ]]; then
invgrep -R --include=*.{py,pyx} 'xrange' pandas
RET=$(($RET + $?)) ; echo $MSG "DONE"

MSG='Check for use of private functions across modules' ; echo $MSG
if [[ "$GITHUB_ACTIONS" == "true" ]]; then
$BASE_DIR/scripts/validate_unwanted_patterns.py --validation-type="private_function_across_module" --format="##[error]{source_path}:{line_number}:{msg}" pandas/core/
else
$BASE_DIR/scripts/validate_unwanted_patterns.py --validation-type="private_function_across_module" pandas/core
fi
RET=$(($RET + $?)) ; echo $MSG "DONE"

MSG='Check that no file in the repo contains trailing whitespaces' ; echo $MSG
INVGREP_APPEND=" <- trailing whitespaces found"
invgrep -RI --exclude=\*.{svg,c,cpp,html,js} --exclude-dir=env "\s$" *
Expand Down
42 changes: 41 additions & 1 deletion scripts/validate_unwanted_patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@
import sys
import token
import tokenize
from typing import IO, Callable, Iterable, List, Tuple
from typing import IO, Callable, Iterable, List, Set, Tuple

FILE_EXTENSIONS_TO_CHECK: Tuple[str, ...] = (".py", ".pyx", ".pxi.ini", ".pxd")
PATHS_TO_IGNORE: Tuple[str, ...] = ("asv_bench/env",)

PRIVATE_IMPORTS_TO_IGNORE: Set[str] = {
"_extension_array_shared_docs",
"_index_shared_docs",
"_merge_doc",
"_shared_docs",
}


def _get_literal_string_prefix_len(token_string: str) -> int:
"""
Expand Down Expand Up @@ -115,6 +122,38 @@ def bare_pytest_raises(file_obj: IO[str]) -> Iterable[Tuple[int, str]]:
)


def private_function_across_module(file_obj: IO[str]) -> Iterable[Tuple[int, str]]:
"""
Checking that a private function is not used across modules.

Parameters
----------
file_obj : IO
File-like object containing the Python code to validate.

Yields
------
line_number : int
Line number of import statement, that imports the private function.
msg : str
Explenation of the error.
"""
contents = file_obj.read()
tree = ast.parse(contents)

for node in ast.walk(tree):
if not (isinstance(node, ast.Import) or isinstance(node, ast.ImportFrom)):
continue

for module in node.names:
module_name = module.name.split(".")[-1]
if module_name in PRIVATE_IMPORTS_TO_IGNORE:
continue

if module_name.startswith("_"):
yield (node.lineno, f"Import of internal function {repr(module_name)}")


def strings_to_concatenate(file_obj: IO[str]) -> Iterable[Tuple[int, str]]:
"""
This test case is necessary after 'Black' (https://github.com/psf/black),
Expand Down Expand Up @@ -358,6 +397,7 @@ def main(
if __name__ == "__main__":
available_validation_types: List[str] = [
"bare_pytest_raises",
"private_function_across_module",
"strings_to_concatenate",
"strings_with_wrong_placed_whitespace",
]
Expand Down