diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2bfc89d..01cb9d5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,14 +1,14 @@ exclude: "vendor/" repos: - - repo: https://github.com/hadialqattan/pycln - rev: v2.3.0 # Possible releases: https://github.com/hadialqattan/pycln/releases - hooks: - - id: pycln - args: [--config=pyproject.toml] + # - repo: https://github.com/hadialqattan/pycln + # rev: v2.4.0 # Possible releases: https://github.com/hadialqattan/pycln/releases + # hooks: + # - id: pycln + # args: [--config=pyproject.toml] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.1.0 + rev: v5.0.0 hooks: - id: check-toml - id: check-yaml @@ -26,51 +26,54 @@ repos: - id: check-executables-have-shebangs - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.6.1 + rev: v4.0.0-alpha.8 hooks: - id: prettier args: [--prose-wrap=always, --print-width=88] - repo: https://github.com/asottile/pyupgrade - rev: v2.31.1 + rev: v3.19.1 hooks: - id: pyupgrade args: [--py37-plus] - repo: https://github.com/pycqa/isort - rev: 5.11.5 + rev: 5.13.2 hooks: - id: isort files: "\\.(py)$" args: [--settings-path=pyproject.toml] - - repo: https://github.com/myint/docformatter - rev: v1.4 - hooks: - - id: docformatter - args: [--in-place] + # - repo: https://github.com/myint/docformatter + # rev: v1.4 + # hooks: + # - id: docformatter + # args: [--in-place] - repo: https://github.com/psf/black - rev: 22.3.0 + rev: 24.10.0 hooks: - id: black args: [--config=pyproject.toml] - repo: https://github.com/pycqa/flake8 - rev: "3.9.2" + rev: "7.1.1" hooks: - id: flake8 additional_dependencies: [pep8-naming] - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.782 # Do not update. - hooks: - - id: mypy - exclude: tests/data/ - args: [--config-file=pyproject.toml] + # - repo: https://github.com/pre-commit/mirrors-mypy + # rev: v1.14.1 + # hooks: + # - id: mypy + # additional_dependencies: + # - types-requests==2.32.0.20241016 + # - types-PyYAML==6.0.12.20241230 + # exclude: tests/data/ + # args: [--config-file=pyproject.toml] - repo: https://github.com/pre-commit/mirrors-pylint - rev: v3.0.0a4 + rev: v3.0.0a5 hooks: - id: pylint args: [--rcfile=.pylintrc] diff --git a/docs/index.html b/docs/index.html index 0481214..acc78a4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,4 +1,4 @@ - + diff --git a/pycln/__init__.py b/pycln/__init__.py index 3a72083..1fc405f 100644 --- a/pycln/__init__.py +++ b/pycln/__init__.py @@ -23,11 +23,11 @@ PYPROJECT_PATH = Path(__file__).parent.parent.joinpath("pyproject.toml") with tokenize.open(PYPROJECT_PATH) as toml_f: - pycln = tomlkit.parse(toml_f.read())["tool"]["poetry"] # type: ignore[index] + pycln = tomlkit.parse(toml_f.read())["tool"]["poetry"] -__name__ = str(pycln["name"]) # type: ignore[index] -__doc__ = str(pycln["description"]) # type: ignore[index] -__version__ = pycln["version"] # type: ignore[index] +__name__ = str(pycln["name"]) +__doc__ = str(pycln["description"]) +__version__ = pycln["version"] def version_callback(value: bool): diff --git a/pycln/__main__.py b/pycln/__main__.py index 97946c1..dd749d6 100644 --- a/pycln/__main__.py +++ b/pycln/__main__.py @@ -1,4 +1,5 @@ """Entry point to run Pycln as a module.""" + from . import __name__ from .cli import app diff --git a/pycln/cli.py b/pycln/cli.py index 091e8ad..14c6b0d 100644 --- a/pycln/cli.py +++ b/pycln/cli.py @@ -1,4 +1,5 @@ """Pycln CLI implementation.""" + from pathlib import Path from typing import Generator, List, Optional @@ -168,9 +169,9 @@ def main( # pylint: disable=R0913,R0914 paths=paths, skip_imports=set(skip_imports), config=config, - include=include, # type: ignore - exclude=exclude, # type: ignore - extend_exclude=extend_exclude, # type: ignore + include=include, + exclude=exclude, + extend_exclude=extend_exclude, all_=all_, check=check, diff=diff, @@ -190,7 +191,7 @@ def main( # pylint: disable=R0913,R0914 gitignore = regexu.get_gitignore( path if path.is_dir() else path.parent, configs.no_gitignore ) - sources: Generator = pathu.yield_sources( # type: ignore + sources: Generator = pathu.yield_sources( path, configs.include, configs.exclude, diff --git a/pycln/utils/_exceptions.py b/pycln/utils/_exceptions.py index 0a64c69..75210d6 100644 --- a/pycln/utils/_exceptions.py +++ b/pycln/utils/_exceptions.py @@ -1,4 +1,5 @@ """Pycln custom exceptions utility.""" + from pathlib import Path from typing import Union @@ -6,7 +7,6 @@ class BaseOSError(Exception): - """Custom OSError.""" def __init__(self, errno: int, strerror: str, filepath: Path): @@ -15,23 +15,19 @@ def __init__(self, errno: int, strerror: str, filepath: Path): class ReadPermissionError(BaseOSError): - """Raises when the file does not have read permission.""" class WritePermissionError(BaseOSError): - """Raises when the file does not have write permission.""" class InitFileDoesNotExistError(BaseOSError): - """Raises when an `__init__.py` file path encountered of a non-existing path.""" class UnexpandableImportStar(Exception): - """Raises when the import `*` statement unexpandable.""" def __init__(self, path: Path, location: NodeLocation, msg: str): @@ -41,7 +37,6 @@ def __init__(self, path: Path, location: NodeLocation, msg: str): class UnparsableFile(Exception): - """Raises when the compiled source code is invalid, or the source code contains null bytes.""" @@ -56,7 +51,7 @@ def __init__( UnparsableFile._type_check(type_) if type_ in {SyntaxError, IndentationError}: - lineno, col, text = err.lineno, err.offset, err.text # type: ignore + lineno, col, text = err.lineno, err.offset, err.text if lineno: location = f"{path}:{lineno}:{col}" if text: @@ -66,7 +61,7 @@ def __init__( elif type_ == ValueError: setattr(err, "msg", str(err)) - msg = err.msg # type: ignore + msg = err.msg message = f"{location} {type_.__name__}: {msg}{postfix}" super().__init__(message) @@ -86,7 +81,6 @@ def _type_check(type_: type) -> None: class UnsupportedCase(Exception): - """Raises when unsupported import case detected.""" def __init__(self, path: Path, location: NodeLocation, msg: str): diff --git a/pycln/utils/_nodes.py b/pycln/utils/_nodes.py index 9df520c..f7178ab 100644 --- a/pycln/utils/_nodes.py +++ b/pycln/utils/_nodes.py @@ -1,4 +1,5 @@ """Pycln import statements nodes utility.""" + import ast from dataclasses import dataclass from typing import List, Optional, Tuple @@ -6,7 +7,6 @@ @dataclass(frozen=True) class NodePosition: - """Node position class.""" #: Line numbers are 1-indexed. @@ -23,7 +23,6 @@ def __hash__(self): @dataclass class NodeLocation: - """Node location class. :param start: tuple of start line and col_offset. @@ -43,7 +42,6 @@ def __len__(self): @dataclass class BaseImport: - """Custom `ast.AST` node.""" #: Location contains: @@ -60,7 +58,6 @@ class BaseImport: @dataclass class Import(BaseImport): - """Custom `ast.Import` node.""" def __hash__(self): @@ -69,7 +66,6 @@ def __hash__(self): @dataclass class ImportFrom(BaseImport): - """Custom `ast.ImportFrom` node.""" #: `ast.ImportFrom.module`. diff --git a/pycln/utils/config.py b/pycln/utils/config.py index 339b17c..2cd71a5 100644 --- a/pycln/utils/config.py +++ b/pycln/utils/config.py @@ -1,4 +1,5 @@ """Pycln configuration management utility.""" + import configparser import json import tokenize @@ -24,7 +25,6 @@ @dataclass class Config: - """Pycln configs dataclass.""" def __post_init__(self): @@ -41,9 +41,9 @@ def __post_init__(self): paths: List[Path] skip_imports: Set[str] config: Optional[Path] = None - include: Pattern[str] = regexu.INCLUDE_REGEX # type: ignore - exclude: Pattern[str] = regexu.EXCLUDE_REGEX # type: ignore - extend_exclude: Pattern[str] = regexu.EMPTY_REGEX # type: ignore + include: Pattern[str] = regexu.INCLUDE_REGEX + exclude: Pattern[str] = regexu.EXCLUDE_REGEX + extend_exclude: Pattern[str] = regexu.EMPTY_REGEX all_: bool = False check: bool = False diff: bool = False @@ -112,7 +112,6 @@ def _check_regex(self) -> None: class ParseConfigFile: - """Conifg file parser. :param file_path: config file path. @@ -154,7 +153,7 @@ def _parse_cfg(self) -> None: # Parse `.cfg` file. parser = configparser.ConfigParser(allow_no_value=True) parser.read(self._path) - cfg_data = parser._sections.get(self._section, {}) # type: ignore + cfg_data = parser._sections.get(self._section, {}) def cast_bool(v: str) -> Union[str, bool]: if v.lower() == "true": @@ -171,9 +170,7 @@ def cast_bool(v: str) -> Union[str, bool]: #: skip_imports = [x, y] #: skip_imports = x,y skip_imports = configs["skip_imports"] - skip_imports = set( - skip_imports.strip('[]"').replace(" ", "").split(",") # type: ignore - ) + skip_imports = set(skip_imports.strip('[]"').replace(" ", "").split(",")) configs["skip_imports"] = skip_imports self._config_loader(configs) diff --git a/pycln/utils/iou.py b/pycln/utils/iou.py index 858413b..351d5fa 100644 --- a/pycln/utils/iou.py +++ b/pycln/utils/iou.py @@ -1,4 +1,5 @@ """Pycln file IO utility.""" + import io import os import sys diff --git a/pycln/utils/pathu.py b/pycln/utils/pathu.py index 4ce4cd7..7209bcf 100644 --- a/pycln/utils/pathu.py +++ b/pycln/utils/pathu.py @@ -1,4 +1,5 @@ """Pycln path finding utility.""" + import os import sys import sysconfig @@ -73,9 +74,9 @@ def yield_sources( is_included, is_excluded = regexu.is_included, regexu.is_excluded if path.is_dir(): - root_dir = os.scandir(path) # type: ignore + root_dir = os.scandir(path) else: - root_dir = {path} # type: ignore + root_dir = {path} path = path.parent for entry in root_dir: @@ -215,7 +216,7 @@ def get_local_import_path(path: Path, module: str) -> Optional[Path]: names = module.split(".") # Test different levels. - for i in [None] + list(range(-10, -0)): # type: ignore + for i in [None] + list(range(-10, -0)): # If it's a file. fpath = os.path.join(*dirnames[:i], *names[:-1], f"{names[-1]}{PY_EXTENSION}") if os.path.isfile(fpath): @@ -267,7 +268,7 @@ def get_local_import_from_path( packages = package.split(".") if package else [] # Test different levels. - for i in [None] + list(range(-10, -0)): # type: ignore + for i in [None] + list(range(-10, -0)): # If it's a file. if modules: fpath = os.path.join( diff --git a/pycln/utils/refactor.py b/pycln/utils/refactor.py index 37ed4cc..4a29b19 100644 --- a/pycln/utils/refactor.py +++ b/pycln/utils/refactor.py @@ -1,4 +1,5 @@ """Pycln code refactoring utility.""" + import ast import os import sys @@ -21,7 +22,7 @@ from .report import Report if sys.version_info < (3, 12): - from pathlib import Path, _posix_flavour, _windows_flavour # type: ignore + from pathlib import Path, _posix_flavour, _windows_flavour _flavour = _windows_flavour if ISWIN else _posix_flavour else: @@ -54,7 +55,6 @@ def is_stub(self) -> bool: class LazyLibCSTLoader: - """`transform.py` takes about '0.3s' to be loaded because of LibCST, therefore I've created this class to load it only if necessary. @@ -75,7 +75,6 @@ def __getattr__(self, name): class Refactor: - """Refactor the given source. >>> refactor = Refactor( @@ -247,7 +246,7 @@ def _output( def _analyze( self, tree: ast.AST, original_lines: List[str] - ) -> Tuple[scan.SourceStats, scan.ImportStats]: + ) -> Tuple[scan.SourceStats, scan.ImportStats] | None: """Analyze the given `tree`. :param tree: a parsed `ast.AST`. @@ -491,7 +490,7 @@ def _has_used(self, name: str, is_star: bool) -> bool: :param is_star: is it a '*' import. :returns: True if the name has used else False. """ - name = name.split(".") if "." in name else name # type: ignore + name = name.split(".") if "." in name else name if isinstance(name, str): if is_star and name in self._source_stats.names_to_skip: return False diff --git a/pycln/utils/regexu.py b/pycln/utils/regexu.py index e7f515f..44b6c2e 100644 --- a/pycln/utils/regexu.py +++ b/pycln/utils/regexu.py @@ -1,4 +1,5 @@ """Pycln regex utility.""" + import os import re import tokenize @@ -38,7 +39,7 @@ def safe_compile(pattern: str, type_: str) -> Pattern[str]: if isinstance(pattern, str): compiled: Pattern[str] = re.compile(pattern, re.IGNORECASE) return compiled - return pattern # type: ignore + return pattern except re.error as err: typer.secho( f"Invalid regular expression for {type_} given: {pattern!r} ⛔", diff --git a/pycln/utils/report.py b/pycln/utils/report.py index 53a2c5e..02c9410 100644 --- a/pycln/utils/report.py +++ b/pycln/utils/report.py @@ -1,4 +1,5 @@ """Pycln report utility.""" + import ast from dataclasses import dataclass from difflib import unified_diff @@ -12,7 +13,6 @@ @dataclass class Report: - """Provide a Pycln report counters. Can be rendered with `str(report)`. diff --git a/pycln/utils/scan.py b/pycln/utils/scan.py index a339cb7..8706c5c 100644 --- a/pycln/utils/scan.py +++ b/pycln/utils/scan.py @@ -1,4 +1,5 @@ """Pycln source code AST analysis utility.""" + import ast import os import sys @@ -108,7 +109,6 @@ def wrapper(self, *args, **kwargs): @dataclass class ImportStats: - """Import statements statistics.""" import_: Set[_nodes.Import] @@ -120,7 +120,6 @@ def __iter__(self): @dataclass class SourceStats: - """Source code (`ast.Name`, `ast.Attribute`) statistics.""" #: Included on `__iter__`. @@ -135,7 +134,6 @@ def __iter__(self): class SourceAnalyzer(ast.NodeVisitor): - """AST source code analyzer. >>> import ast @@ -184,10 +182,11 @@ def visit_Attribute(self, node: ast.Attribute): self._source_stats.attr_.add(node.attr) @recursive - def visit_MatchAs(self, node: "ast.MatchAs"): # type: ignore + def visit_MatchAs(self, node: "ast.MatchAs"): #: Support Match statement (PYTHON >= 3.10). #: PEP0634: https://www.python.org/dev/peps/pep-0634/ - self._source_stats.name_.add(node.name) + if node.name is not None: + self._source_stats.name_.add(node.name) @recursive def visit_Call(self, node: ast.Call): @@ -200,9 +199,9 @@ def visit_Call(self, node: ast.Call): #: Issue: https://github.com/hadialqattan/pycln/issues/26 if getattr(func, "id", "") == "cast" or ( getattr(func, "attr", "") == "cast" - and getattr(func.value, "id", "") == "typing" # type: ignore + and getattr(func.value, "id", "") == "typing" ): - self._parse_string(node.args[0]) # type: ignore + self._parse_string(node.args[0]) #: Support TypeVar cases (when types passed as str). #: >>> from typing import TypeVar @@ -211,7 +210,7 @@ def visit_Call(self, node: ast.Call): #: >>> YBoundedType = TypeVar("YBoundedType", bound="Y") if getattr(func, "id", "") == "TypeVar" or ( getattr(func, "attr", "") == "TypeVar" - and getattr(func.value, "id", "") == "typing" # type: ignore + and getattr(func.value, "id", "") == "typing" ): args = getattr(node, "args", [])[1:] # Skip the TypeVar's name. for arg in args: @@ -239,16 +238,16 @@ def visit_Subscript(self, node: ast.Subscript) -> None: ) if _id in SUBSCRIPT_TYPE_VARIABLE or _id == "typing": if PY39_PLUS: - s_val = node.slice # type: ignore + s_val = node.slice else: - s_val = node.slice.value # type: ignore + s_val = node.slice.value for elt in getattr(s_val, "elts", ()) or (s_val,): if _id == "Callable" and isinstance(elt, ast.List): # See issue: https://github.com/hadialqattan/pycln/issues/208 for sub_elt in getattr(elt, "elts", ()): - self._parse_string(sub_elt) # type: ignore + self._parse_string(sub_elt) else: - self._parse_string(elt) # type: ignore + self._parse_string(elt) @recursive def visit_AnnAssign(self, node: ast.AnnAssign): @@ -270,9 +269,9 @@ def visit_AnnAssign(self, node: ast.AnnAssign): annotation: ast.expr = node.annotation if getattr(annotation, "id", "") == "TypeAlias" or ( getattr(annotation, "attr", "") == "TypeAlias" - and annotation.value.id in ("typing", "typing_extensions") # type: ignore + and annotation.value.id in ("typing", "typing_extensions") ): - self._parse_string(node.value) # type: ignore + self._parse_string(node.value) @recursive def visit_arg(self, node: ast.arg): @@ -332,11 +331,11 @@ def visit_ClassDef(self, node: ast.ClassDef): for base in node.bases: if isinstance(base, ast.Subscript): if PY39_PLUS: - s_val = base.slice # type: ignore + s_val = base.slice else: - s_val = base.slice.value # type: ignore + s_val = base.slice.value for elt in getattr(s_val, "elts", ()) or (s_val,): - self._parse_string(elt) # type: ignore + self._parse_string(elt) @recursive def visit_Assign(self, node: ast.Assign): @@ -431,9 +430,9 @@ def _visit_string_type_annotation( if isinstance(annotation.slice, ast.Constant): annotation = annotation.slice elif isinstance(annotation.slice, ast.Index): - annotation = annotation.slice.value # type: ignore + annotation = annotation.slice.value - self._parse_string(annotation, True) # type: ignore + self._parse_string(annotation, True) def _visit_type_comment( self, node: Union[ast.Assign, ast.arg, FunctionDefT] @@ -589,7 +588,6 @@ def has_all(self) -> bool: class ImportablesAnalyzer(ast.NodeVisitor): - """Get set of all importable names from given `ast.Module`. >>> import ast @@ -797,7 +795,6 @@ class HasSideEffects(Enum): class SideEffectsAnalyzer(ast.NodeVisitor): - """Check if the given `ast.Module` has side effects or not. >>> import ast @@ -930,11 +927,9 @@ def expand_import_star( msg = str(err) # pragma: nocover if hasattr(node, "location"): - location = node.location # type: ignore # pragma: nocover. + location = node.location # pragma: nocover. else: - location = _nodes.NodeLocation( - (node.lineno, node.col_offset), 0 # type: ignore - ) + location = _nodes.NodeLocation((node.lineno, node.col_offset), 0) raise UnexpandableImportStar(path, location, msg) from err diff --git a/pycln/utils/transform.py b/pycln/utils/transform.py index 3e4a420..3e68537 100644 --- a/pycln/utils/transform.py +++ b/pycln/utils/transform.py @@ -1,4 +1,5 @@ """Pycln CST transforming utility.""" + from pathlib import Path from typing import List, Optional, Set, TypeVar, Union, cast @@ -16,7 +17,6 @@ class ImportTransformer(cst.CSTTransformer): - """Import statements transformer. :param used_names: set of all used names to keep. @@ -29,7 +29,7 @@ def __init__(self, used_names: Set[str], location: NodeLocation): raise ValueError("'used_names' parameter can't be empty set.") self._used_names = used_names self._location = location - self._indentation = " " * location.start.col + self._indentation = " " * (location.start.col or 0) # Style preservation. self._lpar: cst.LeftParen = self._multiline_lpar() @@ -72,7 +72,7 @@ def refactor_import(self, updated_node: ImportT) -> ImportT: :returns: refactored node. """ used_aliases: List[cst.ImportAlias] = [] - for alias in updated_node.names: # type: ignore + for alias in updated_node.names: if self._get_alias_name(alias.name) in self._used_names: used_aliases.append(alias) return self._stylize(updated_node, used_aliases) @@ -104,7 +104,7 @@ def _set_rpar(self, node: cst.ImportFrom): def _set_trailing_comma(self, node: ImportT): # Set `self._trailing_comma` base on the original node. - self._trailing_comma = node.names[-1].comma # type: ignore + self._trailing_comma = node.names[-1].comma def _get_alias_name( self, node: Optional[Union[cst.Name, cst.Attribute]], name="" @@ -113,7 +113,7 @@ def _get_alias_name( if isinstance(node, cst.Name): name += node.value return name - return self._get_alias_name(node.value) + "." + node.attr.value # type: ignore + return self._get_alias_name(node.value) + "." + node.attr.value @staticmethod def _multiline_parenthesized_whitespace(indent: str) -> cst.ParenthesizedWhitespace: @@ -200,7 +200,7 @@ def rebuild_import( # Remove `import_stmnt` indentation/last-"\n". stripped_stmnt = import_stmnt.lstrip(" ").rstrip("\n") - indentation = " " * location.start.col + indentation = " " * (location.start.col or 0) # Remove unused aliases. fixed_lines: List[str] = [] diff --git a/tests/__init__.py b/tests/__init__.py index 294bac4..8a29b96 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,4 +1,5 @@ """Pycln unit tests module.""" + from pathlib import Path # Constatns. diff --git a/tests/test_cli.py b/tests/test_cli.py index 6152513..7e71183 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,4 +1,5 @@ """pycln/utils/cli.py tests.""" + # pylint: disable=R0201,W0613 import pytest from typer.testing import CliRunner @@ -14,7 +15,6 @@ class TestCli: - """some `cli.py` tests.""" def _assert_code_in(self, expec_out, *args, stdin=b"", expec_exit_code=0): diff --git a/tests/test_config.py b/tests/test_config.py index 031a46e..1a2dbeb 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,4 +1,5 @@ """pycln/utils/config.py tests.""" + # pylint: disable=R0201,W0613 import re from pathlib import Path @@ -65,7 +66,6 @@ class TestConfig: - """`config.Config` class tests.""" @pytest.mark.parametrize( @@ -180,7 +180,6 @@ def test_check_skip_imports(self, cp, cr, psi, skip_imports, expec_err): class TestParseConfigFile: - """`config.ParseConfigFile` class tests.""" @mock.patch(MOCK % "ParseConfigFile.__init__") diff --git a/tests/test_iou.py b/tests/test_iou.py index 5492f94..ac7be34 100644 --- a/tests/test_iou.py +++ b/tests/test_iou.py @@ -1,4 +1,5 @@ """pycln/utils/iou.py tests.""" + # pylint: disable=R0201,W0613 import os from pathlib import Path @@ -24,7 +25,6 @@ class TestIOU: - """`iou.py` functions test case.""" @pytest.mark.parametrize( diff --git a/tests/test_main.py b/tests/test_main.py index 796f970..0ba67fd 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,4 +1,5 @@ """`pycln/__main__.py` tests.""" + # pylint: disable=R0201,W0613 from importlib import import_module @@ -6,7 +7,6 @@ class TestMain: - """`__main__.py` side effects tests.""" def test_main(self): diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 8efc517..61aa300 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -1,4 +1,5 @@ """pycln `__init__.py`/`pyproject.toml` metadata tests.""" + # pylint: disable=R0201,W0613 import sys import tokenize @@ -23,14 +24,13 @@ # Constants. with tokenize.open(PYPROJECT_PATH) as toml_f: - PYCLN_METADATA = tomlkit.parse(toml_f.read())["tool"]["poetry"] # type: ignore + PYCLN_METADATA = tomlkit.parse(toml_f.read())["tool"]["poetry"] PYCLN_PYPI_JSON_URL = f"https://pypi.org/pypi/{__name__}/json" PYCLN_PYPI_URL = f"https://pypi.org/project/{__name__}/" class TestMetadata: - """`__init__.py`/`pyproject.toml` test case.""" def test_vendor_path(self): diff --git a/tests/test_nodes.py b/tests/test_nodes.py index 702441d..ade44d3 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -1,4 +1,5 @@ """pycln/utils/_nodes.py tests.""" + # pylint: disable=R0201,W0613 import pytest @@ -6,7 +7,6 @@ class TestNodePosition: - """`NodePosition` dataclass test case.""" @pytest.mark.parametrize("line, col", [(1, 0), (1, None)]) @@ -28,7 +28,6 @@ def test_hash_dunder(self, line, col, expec_hash): class TestNodeLocation: - """`NodeLocation` dataclass test case.""" @pytest.mark.parametrize("start, end", [((1, 0), 1)]) @@ -56,7 +55,6 @@ def test_len_dunder(self, start, end, expec_len): class TestImport: - """`Import` dataclass test case.""" @pytest.mark.parametrize( @@ -75,7 +73,6 @@ def test_hash_dunder(self): class TestImportFrom: - """`ImportFrom` dataclass test case.""" @pytest.mark.parametrize( diff --git a/tests/test_pathu.py b/tests/test_pathu.py index c83264e..e4013f0 100644 --- a/tests/test_pathu.py +++ b/tests/test_pathu.py @@ -1,4 +1,5 @@ """pycln/utils/pathu.py tests.""" + # pylint: disable=R0201,W0613 import re import sys @@ -38,7 +39,6 @@ class TestPathu: - """`pathu.py` functions test case.""" @pytest.fixture(autouse=True) diff --git a/tests/test_refactor.py b/tests/test_refactor.py index 2bd8fe1..0659b8c 100644 --- a/tests/test_refactor.py +++ b/tests/test_refactor.py @@ -1,4 +1,5 @@ """pycln/utils/refactor.py tests.""" + # pylint: disable=R0201,W0613 import ast from pathlib import Path @@ -26,7 +27,6 @@ class TestPyPath: - """`PyPath` class test case.""" def test_is_subclass_of_pathlib_path(self): @@ -42,7 +42,6 @@ def test_is_stub_property(self, path, expected_is_stub): class TestRefactor: - """`Refactor` methods test case.""" def setup_method(self, method): diff --git a/tests/test_regexu.py b/tests/test_regexu.py index f3b1382..d78cb59 100644 --- a/tests/test_regexu.py +++ b/tests/test_regexu.py @@ -1,4 +1,5 @@ """pycln/utils/regexu.py tests.""" + # pylint: disable=R0201,W0613 import re from pathlib import Path @@ -20,7 +21,6 @@ class TestRegexU: - """`regexu.py` functions test case.""" @pytest.mark.parametrize( diff --git a/tests/test_report.py b/tests/test_report.py index 8d4f257..aae5501 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -1,4 +1,5 @@ """pycln/utils/report.py tests.""" + # pylint: disable=R0201,W0613 import ast from contextlib import contextmanager @@ -15,7 +16,6 @@ class TestReport: - """`Report` methods test case.""" def setup_method(self, method): diff --git a/tests/test_scan.py b/tests/test_scan.py index 32c280e..ef92db2 100644 --- a/tests/test_scan.py +++ b/tests/test_scan.py @@ -1,4 +1,5 @@ """pycln/utils/scan.py tests.""" + # pylint: disable=R0201,W0613 import ast import sys @@ -21,7 +22,6 @@ class TestDataclasses: - """`scan.py` dataclasses test case.""" def test_import_stats_iter(self): @@ -34,7 +34,6 @@ def test_source_stats_iter(self): class AnalyzerTestCase: - """`scan.*Analyzer` test case.""" def assert_set_equal_or_not(self, set_: set, expec_set: set): @@ -49,7 +48,6 @@ def normalize_set(self, set_: set) -> set: class TestSourceAnalyzer(AnalyzerTestCase): - """`SourceAnalyzer` class tests.""" def _get_analyzer(self, source_code: str): @@ -920,7 +918,6 @@ def test_has_all(self, code, expec): class TestImportablesAnalyzer(AnalyzerTestCase): - """`ImportablesAnalyzer` class tests.""" def _assert_not_importables(self, not_importables: set, expec_not_importables: set): @@ -1114,7 +1111,6 @@ def test_compute_not_importables(self, code, expec_not_importables): class TestSideEffectsAnalyzer: - """`SideEffectsAnalyzer` class tests.""" def _assert_not_side_effects( @@ -1291,7 +1287,6 @@ def test_check_names(self, names, expec_has_side_effects): class TestScanFunctions(AnalyzerTestCase): - """`scan.py` functions test case.""" @pytest.mark.parametrize( @@ -1343,7 +1338,7 @@ def _assert_ast_equal( ast_tree = scan.parse_ast(code, mode=mode) assert ast_tree if type_comment: - tc = ast_tree.body[0].type_comment # type: ignore + tc = ast_tree.body[0].type_comment assert tc == type_comment raise sysu.Pass() diff --git a/tests/test_transform.py b/tests/test_transform.py index 87a2606..585d1b2 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -1,4 +1,5 @@ """pycln/utils/transform.py tests.""" + # pylint: disable=R0201,W0613 from pathlib import Path from typing import Union @@ -18,7 +19,6 @@ class TestImportTransformer: - """`ImportTransformer` methods test case.""" def _assert_import_equal( @@ -390,7 +390,7 @@ def get_name_node(name: str) -> Union[cst.Name, cst.Attribute]: names = name.split(".") value = get_name_node(".".join(names[:-1])) attr = get_name_node(names[-1]) - return cst.Attribute(value=value, attr=attr) # type: ignore + return cst.Attribute(value=value, attr=attr) node = get_name_node(name) transformer = transform.ImportTransformer(None, None) @@ -471,7 +471,6 @@ def test_stylize(self, code, endlineno, ismultiline): class TestTransformFunctions: - """`transform.py` functions test case.""" @pytest.mark.parametrize( diff --git a/tests/utils/sysu.py b/tests/utils/sysu.py index 55a25a3..8a802b1 100644 --- a/tests/utils/sysu.py +++ b/tests/utils/sysu.py @@ -1,4 +1,5 @@ """System hacks utility.""" + import os import sys from contextlib import contextmanager @@ -13,8 +14,8 @@ class STD(Enum): """STD TYPES.""" - OUT: int = 0 - ERR: int = 1 + OUT = 0 + ERR = 1 @contextmanager diff --git a/tests/utils/test_sysu.py b/tests/utils/test_sysu.py index 774a6ac..08705c6 100644 --- a/tests/utils/test_sysu.py +++ b/tests/utils/test_sysu.py @@ -1,4 +1,5 @@ """Test `tests/utils/sysu.py`.""" + # pylint: disable=R0201,W0613 import sys @@ -8,7 +9,6 @@ class TestSTD: - """`sysu.py` functions test case.""" @pytest.mark.parametrize(