From 7f230e4b2107a3dc6230baa3a24eb439f895b3c1 Mon Sep 17 00:00:00 2001 From: Jay Chung Date: Wed, 18 Oct 2023 14:10:14 +0800 Subject: [PATCH 1/3] feat: introduce ruff for linter and remove flake8, isort, and autoflake --- .pre-commit-config.yaml | 26 +++------------ .ruff.toml | 46 +++++++++++++++++++++++++++ README.md | 1 - setup.cfg | 33 +------------------ src/stmdency/models/node.py | 2 +- src/stmdency/visitors/assign.py | 3 +- src/stmdency/visitors/function_def.py | 3 +- tests/extractor/test_assign.py | 1 + tests/extractor/test_function.py | 1 + tests/extractor/test_import.py | 1 + tests/extractor/test_module_class.py | 1 + tests/testing.py | 1 + tox.ini | 8 ++--- 13 files changed, 63 insertions(+), 64 deletions(-) create mode 100644 .ruff.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 73e7843..501fe7d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,30 +24,12 @@ default_language_version: python: python3 repos: # Python API Hooks - - repo: https://github.com/pycqa/isort - rev: 5.10.1 - hooks: - - id: isort - name: isort (python) - repo: https://github.com/psf/black rev: 22.3.0 hooks: - id: black - - repo: https://github.com/pycqa/flake8 - rev: 3.8.0 - hooks: - - id: flake8 - pass_filenames: false - additional_dependencies: [ - 'flake8-docstrings>=1.6', - 'flake8-black>=0.2', - ] - - repo: https://github.com/pycqa/autoflake - rev: v1.4 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.0 hooks: - - id: autoflake - args: [ - --remove-all-unused-imports, - --ignore-init-module-imports, - --in-place - ] + - id: ruff + args: [ --fix, --exit-non-zero-on-fix ] diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 0000000..00ce9fa --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,46 @@ +src = ["src"] + +# max-line-length = 88 +line-length = 110 + +extend-select = [ + "I", # isort + "D", # pydocstyle + "UP", # pyupgrade +] + +ignore = [ + # D100 Missing docstring in public module + "D100", + # D100 Missing docstring in public module + "D104", + # D107: Missing docstring in __init__ + "D107", + # D105: Missing docstring in magic method + "D105", + # D418: Function/ Method decorated with @overload shouldn’t contain a docstring + "D418", +] + +# Exclude a variety of commonly ignored directories. +exclude = [ + "__pycache__", + ".egg-info", + ".eggs", + ".git", + ".pytest_cache", + ".tox", + "build", + "dist", + "examples", + "venv", +] + +[isort] +# Mark sqlfluff, test and it's plugins as known first party +known-first-party = [ + "stmdency", +] + +[pydocstyle] +convention = "google" \ No newline at end of file diff --git a/README.md b/README.md index 820feba..81893ec 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ [![Downloads](https://pepy.tech/badge/stmdency/month)](https://pepy.tech/project/stmdency) [![Coverage Status](https://img.shields.io/codecov/c/github/zhongjiajie/stmdency/main.svg?style=flat-square)](https://codecov.io/github/zhongjiajie/stmdency?branch=main) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black) -[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat-square&labelColor=ef8336)](https://pycqa.github.io/isort) [![CI](https://github.com/zhongjiajie/stmdency/actions/workflows/ci.yaml/badge.svg)](https://github.com/zhongjiajie/stmdency/actions/workflows/ci.yaml) [![Documentation Status](https://readthedocs.org/projects/stmdency/badge/?version=latest)](https://stmdency.readthedocs.io/en/latest/?badge=latest) diff --git a/setup.cfg b/setup.cfg index 86360f7..48e2660 100644 --- a/setup.cfg +++ b/setup.cfg @@ -55,11 +55,7 @@ stmdency = dev = # style black>=22.8 - flake8>=4.0 - flake8-docstrings>=1.6 - flake8-black>=0.2 - isort>=5.10 - autoflake>=1.4 + ruff>=0.1 # test pytest>=6.2 pytest-cov>=3.0 @@ -69,33 +65,6 @@ dev = sphinx-copybutton>=0.4.0 sphinx-argparse>=0.3.2 -[flake8] -max-line-length = 110 -exclude = - .git, - __pycache__, - .pytest_cache, - *.egg-info, - build, - dist, - .tox, - examples, - tests, -ignore = - # D107: Don't require docstrings on __init__ - D107, - # D105: Missing docstring in magic method - D105, - # D104: Missing docstring in public package - D104, - # D100: Missing docstring in public module - D100, - # W503: Line breaks before binary operators - W503, - -[isort] -profile=black - [coverage:run] command_line = -m pytest diff --git a/src/stmdency/models/node.py b/src/stmdency/models/node.py index 4994129..b00e682 100644 --- a/src/stmdency/models/node.py +++ b/src/stmdency/models/node.py @@ -15,7 +15,7 @@ class StmdencyNode: # name: str node: cst.CSTNode - parent: list["StmdencyNode"] = field(default_factory=list) + parent: list[StmdencyNode] = field(default_factory=list) def __hash__(self): return hash(self.node) diff --git a/src/stmdency/visitors/assign.py b/src/stmdency/visitors/assign.py index 632e523..1cdcb3a 100644 --- a/src/stmdency/visitors/assign.py +++ b/src/stmdency/visitors/assign.py @@ -7,6 +7,7 @@ from libcst import AssignTarget, Call, Name from stmdency.models.node import StmdencyNode +from stmdency.visitors.base import BaseVisitor @dataclass @@ -19,7 +20,7 @@ class AssignVisitor(cst.CSTVisitor): """ # current: str - PV: "BaseVisitor" # noqa: F821 + PV: BaseVisitor root_node: cst.CSTNode name: str = None diff --git a/src/stmdency/visitors/function_def.py b/src/stmdency/visitors/function_def.py index c5993f4..47a9bc9 100644 --- a/src/stmdency/visitors/function_def.py +++ b/src/stmdency/visitors/function_def.py @@ -7,6 +7,7 @@ from libcst import Assign, Attribute, Call, FunctionDef, Name, Param from stmdency.models.node import StmdencyNode +from stmdency.visitors.base import BaseVisitor @dataclass @@ -19,7 +20,7 @@ class FunctionDefVisitor(cst.CSTVisitor): :param scope: statement scope set to avoid error handle """ - PV: "BaseVisitor" # noqa: F821 + PV: BaseVisitor # noqa: F821 func_name: str | None = None local_param: set[str] = field(default_factory=set) # Add scope to determine if the node is in the same scope diff --git a/tests/extractor/test_assign.py b/tests/extractor/test_assign.py index 28590bc..65fc6ad 100644 --- a/tests/extractor/test_assign.py +++ b/tests/extractor/test_assign.py @@ -82,4 +82,5 @@ @pytest.mark.parametrize("name, source, expects", assign_cases) def test_assign(name: str, source: str, expects: dict[str, str]) -> None: + """Test assignment extraction.""" assert_extract(name, source, expects) diff --git a/tests/extractor/test_function.py b/tests/extractor/test_function.py index bf19d9f..7e23aad 100644 --- a/tests/extractor/test_function.py +++ b/tests/extractor/test_function.py @@ -297,4 +297,5 @@ def foo(): @pytest.mark.parametrize("name, source, expects", func_cases) def test_func(name: str, source: str, expects: dict[str, str]) -> None: + """Test function extraction.""" assert_extract(name, source, expects) diff --git a/tests/extractor/test_import.py b/tests/extractor/test_import.py index 7dd7db3..c3995d9 100644 --- a/tests/extractor/test_import.py +++ b/tests/extractor/test_import.py @@ -125,4 +125,5 @@ def bar(): @pytest.mark.parametrize("name, source, expects", import_cases) def test_import(name: str, source: str, expects: dict[str, str]) -> None: + """Test import statement.""" assert_extract(name, source, expects) diff --git a/tests/extractor/test_module_class.py b/tests/extractor/test_module_class.py index e3f40d4..514aebb 100644 --- a/tests/extractor/test_module_class.py +++ b/tests/extractor/test_module_class.py @@ -31,4 +31,5 @@ def foo(): @pytest.mark.parametrize("name, source, expects", import_cases) def test_import(name: str, source: str, expects: dict[str, str]) -> None: + """Test import statement.""" assert_extract(name, source, expects) diff --git a/tests/testing.py b/tests/testing.py index 3ac4096..106e24f 100644 --- a/tests/testing.py +++ b/tests/testing.py @@ -6,6 +6,7 @@ def assert_extract(name: str, source: str, expects: dict[str, str]) -> None: + """Test tools, asserting the extracted code is the same as expected.""" wrap_source = textwrap.dedent(source) extractor = Extractor(source=wrap_source) for expect in expects: diff --git a/tox.ini b/tox.ini index 06821e3..009286a 100644 --- a/tox.ini +++ b/tox.ini @@ -21,22 +21,18 @@ envlist = auto-lint, lint, code-test, local-ci, doc-build, py{38,39,310,311,312} [testenv] allowlist_externals = make - git [testenv:auto-lint] extras = dev commands = - python -m isort . python -m black . - python -m autoflake --in-place --remove-all-unused-imports --ignore-init-module-imports --recursive . + python -m ruff check --fix . [testenv:lint] extras = dev commands = - python -m isort --check . python -m black --check . - python -m flake8 - python -m autoflake --remove-all-unused-imports --ignore-init-module-imports --check --recursive . + python -m ruff check . [testenv:doc-build] extras = doc From ac976332c64e76f348364bdbd665483999f3423a Mon Sep 17 00:00:00 2001 From: Jay Chung Date: Wed, 18 Oct 2023 14:19:44 +0800 Subject: [PATCH 2/3] Add typing.TYPE_CHECKING avoid circular import --- src/stmdency/visitors/assign.py | 5 ++++- src/stmdency/visitors/function_def.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/stmdency/visitors/assign.py b/src/stmdency/visitors/assign.py index 1cdcb3a..ef8753b 100644 --- a/src/stmdency/visitors/assign.py +++ b/src/stmdency/visitors/assign.py @@ -1,13 +1,16 @@ from __future__ import annotations from dataclasses import dataclass +from typing import TYPE_CHECKING import libcst as cst import libcst.matchers as m from libcst import AssignTarget, Call, Name from stmdency.models.node import StmdencyNode -from stmdency.visitors.base import BaseVisitor + +if TYPE_CHECKING: + from stmdency.visitors.base import BaseVisitor @dataclass diff --git a/src/stmdency/visitors/function_def.py b/src/stmdency/visitors/function_def.py index 47a9bc9..35d6769 100644 --- a/src/stmdency/visitors/function_def.py +++ b/src/stmdency/visitors/function_def.py @@ -1,13 +1,16 @@ from __future__ import annotations from dataclasses import dataclass, field +from typing import TYPE_CHECKING import libcst as cst import libcst.matchers as m from libcst import Assign, Attribute, Call, FunctionDef, Name, Param from stmdency.models.node import StmdencyNode -from stmdency.visitors.base import BaseVisitor + +if TYPE_CHECKING: + from stmdency.visitors.base import BaseVisitor @dataclass From bc07598c645da98b2fe08eb503d70b55687ed50e Mon Sep 17 00:00:00 2001 From: Jay Chung Date: Wed, 18 Oct 2023 14:29:07 +0800 Subject: [PATCH 3/3] Mark no cover for typing.TYPE_CHECKING --- setup.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup.cfg b/setup.cfg index 48e2660..66f3127 100644 --- a/setup.cfg +++ b/setup.cfg @@ -69,6 +69,10 @@ dev = command_line = -m pytest [coverage:report] +# Mark no cover for typing.TYPE_CHECKING, see details https://github.com/nedbat/coveragepy/issues/831 +exclude_lines = + pragma: no cover + if TYPE_CHECKING: # Don’t report files that are 100% covered skip_covered = True show_missing = True