diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..3cbe37a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "quarterly" + groups: + actions: + patterns: + - "*" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 65090a5..a362651 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,33 +7,28 @@ exclude: | repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: "cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b" # frozen: v5.0.0 + rev: "3e8a8703264a2f4a69428a0aa4dcb512790b2c8c" # frozen: v6.0.0 hooks: - id: check-added-large-files - id: check-ast - - id: check-builtin-literals - id: check-case-conflict - id: check-merge-conflict - id: check-symlinks - - id: check-yaml - args: [--allow-multiple-documents] - id: check-json - id: check-toml + - id: check-yaml + args: [--allow-multiple-documents] - id: debug-statements - - id: end-of-file-fixer + - id: detect-private-key - id: mixed-line-ending - id: name-tests-test args: ["--pytest-test-first"] - - id: requirements-txt-fixer - id: trailing-whitespace - - - repo: https://github.com/psf/black - rev: "1b2427a2b785cc4aac97c19bb4b9a0de063f9547" # frozen: 24.10.0 - hooks: - - id: black + args: [--markdown-linebreak-ext=md] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "75b98813cfb7e663870a28c74366a1e99d7bfe79" # frozen: v0.6.9 + rev: "0acff885bcb16381b67930fefb91e460202f172c" # frozen: v0.12.10 hooks: - - id: ruff + - id: ruff-check args: ["--fix", "--show-fixes", "--exit-non-zero-on-fix"] + - id: ruff-format diff --git a/examples/example_pkg-stubs/_basic.pyi b/examples/example_pkg-stubs/_basic.pyi index 65cf3c0..8fb3e9b 100644 --- a/examples/example_pkg-stubs/_basic.pyi +++ b/examples/example_pkg-stubs/_basic.pyi @@ -13,8 +13,8 @@ from . import AnotherType, CustomException logger: logging.Logger __all__ = [ - "func_empty", "ExampleClass", + "func_empty", ] def func_empty(a1: Incomplete, a2: Incomplete, a3) -> None: ... diff --git a/examples/example_pkg/_basic.py b/examples/example_pkg/_basic.py index 58d4842..5411cb4 100644 --- a/examples/example_pkg/_basic.py +++ b/examples/example_pkg/_basic.py @@ -19,8 +19,8 @@ __all__ = [ - "func_empty", "ExampleClass", + "func_empty", ] diff --git a/pyproject.toml b/pyproject.toml index 8f042ba..db925e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "docstub" maintainers = [ - {name = "Lars Grüter"}, + {name = "Lars Grüter"}, ] description = "Generate Python stub files from docstrings" readme = "README.md" @@ -17,39 +17,39 @@ license-files = ["LICENSE.txt"] requires-python = ">=3.12" keywords = ["typing", "stub files", "docstings", "numpydoc"] classifiers = [ - "Development Status :: 3 - Alpha", - "Environment :: Console", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "Operating System :: OS Independent", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Topic :: Software Development :: Code Generators", - "Topic :: Scientific/Engineering", + "Development Status :: 3 - Alpha", + "Environment :: Console", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Software Development :: Code Generators", + "Topic :: Scientific/Engineering", ] dynamic = ["version"] dependencies = [ - "numpydoc >=1.7.0", - "click >=8.1.7", - "libcst >=1.3.1", - "lark >=1.1.9", - "black >=24.4.2", - "isort >=5.13.2", + "numpydoc >=1.7.0", + "click >=8.1.7", + "libcst >=1.3.1", + "lark >=1.1.9", + "black >=24.4.2", + "isort >=5.13.2", ] [project.optional-dependencies] dev = [ - "pre-commit >=3.7", - "ipython", + "pre-commit >=4.3.0", + "ipython", ] test = [ - "pytest >=5.0.0", - "pytest-cov >= 5.0.0", - "mypy>=1.16.0", - "basedpyright", + "pytest >=8.4.1", + "pytest-cov >= 5.0.0", + "mypy >=1.17.0", + "basedpyright >=1.31", ] [project.urls] @@ -68,42 +68,49 @@ src = ["src", "tests"] [tool.ruff.lint] extend-select = [ - "B", # flake8-bugbear - "I", # isort - "C4", # flake8-comprehensions - "ICN", # flake8-import-conventions - "G", # flake8-logging-format - "PGH", # pygrep-hooks - "PIE", # flake8-pie - "PL", # pylint - "PT", # flake8-pytest-style - "PTH", # flake8-use-pathlib - "RET", # flake8-return - "RUF", # Ruff-specific - "SIM", # flake8-simplify - "T20", # flake8-print - "UP", # pyupgrade - "YTT", # flake8-2020 - "EXE", # flake8-executable -# "PYI", # flake8-pyi + "B", # flake8-bugbear + "I", # isort + "C4", # flake8-comprehensions + "ICN", # flake8-import-conventions + "G", # flake8-logging-format + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PL", # pylint + "PT", # flake8-pytest-style + "PTH", # flake8-use-pathlib + "RET", # flake8-return + "RUF", # Ruff-specific + "SIM", # flake8-simplify + "T20", # flake8-print + "UP", # pyupgrade + "YTT", # flake8-2020 + "EXE", # flake8-executable +# "PYI", # flake8-pyi ] ignore = [ - "PLR09", # Too many <...> - "PLR2004", # Magic value used in comparison - "ISC001", # Conflicts with formatter - "RET504", # Assignment before `return` statement facilitates debugging - "PTH123", # Using builtin open() instead of Path.open() is fine - "SIM108", # Terniary operator is always more readable - "SIM103", # Don't recommend returning the condition directly + "PLR09", # Too many <...> + "PLR2004", # Magic value used in comparison + "ISC001", # Conflicts with formatter + "RET504", # Assignment before `return` statement facilitates debugging + "PTH123", # Using builtin open() instead of Path.open() is fine + "SIM108", # Terniary operator is always more readable + "SIM103", # Don't recommend returning the condition directly ] [tool.pytest.ini_options] -addopts = "--doctest-modules" -testpaths = [ - "src", - "tests", +minversion = "8" +addopts = [ + "-ra", + "--showlocals", + "--strict-markers", + "--strict-config", + "--doctest-modules" ] +xfail_strict = true +filterwarnings = ["error"] +log_cli_level = "info" +testpaths = ["src", "tests"] [tool.coverage] @@ -126,6 +133,8 @@ Path = "pathlib" [tool.mypy] strict = true +warn_unreachable = false +enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] disable_error_code = ["type-arg"] # Don't type test suite itself but check if usage makes sense with docstub's stubs diff --git a/src/docstub/_cli.py b/src/docstub/_cli.py index 8e77b40..b371204 100644 --- a/src/docstub/_cli.py +++ b/src/docstub/_cli.py @@ -122,7 +122,6 @@ def _collect_type_info(root_path, *, ignore=(), cache=False): collect = TypeCollector.collect for source_path in walk_source_package(root_path, ignore=ignore): - if cache: module = source_path.relative_to(root_path.parent) collect.sub_dir = f"{__version__}/{module}" diff --git a/src/docstub/_stubs.py b/src/docstub/_stubs.py index 6881aca..583b0df 100644 --- a/src/docstub/_stubs.py +++ b/src/docstub/_stubs.py @@ -24,13 +24,13 @@ def try_format_stub(stub: str) -> str: """Try to format a stub file with isort and black if available.""" try: - import isort + import isort # noqa: PLC0415 stub = isort.code(stub) except ImportError: logger.warning("isort is not available, couldn't sort imports") try: - import black + import black # noqa: PLC0415 stub = black.format_str(stub, mode=black.Mode(is_pyi=True)) except ImportError: diff --git a/src/docstub/_utils.py b/src/docstub/_utils.py index 462a646..781bba1 100644 --- a/src/docstub/_utils.py +++ b/src/docstub/_utils.py @@ -235,7 +235,7 @@ def format_location(*, path, line, column): @staticmethod def underline(line): - underlined = f"{line}\n" f"{click.style('^' * len(line), fg='red', bold=True)}" + underlined = f"{line}\n{click.style('^' * len(line), fg='red', bold=True)}" return underlined diff --git a/tests/test_cache.py b/tests/test_cache.py index 8d4ff29..bf1da2f 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -48,7 +48,6 @@ def test_create_validate_cache(tmp_path): class Test_FileCache: def test_basic(self, tmp_path): - class Serializer: suffix = ".txt" diff --git a/tests/test_docs.py b/tests/test_docs.py index ea64f50..4b65884 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -70,7 +70,7 @@ def test_command_line_reference(command, name): with md_file.open("r") as io: md_content = io.read() - guard_name = f"cli-{name.replace(" ", "-")}" + guard_name = f"cli-{name.replace(' ', '-')}" regex = rf"(.*)" matches = re.findall(regex, md_content, flags=re.DOTALL) assert len(matches) == 1