diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 524f1aa..938737c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,10 @@ jobs: allow-prereleases: true - name: Install package - run: python -m pip install .[test,optional] + run: | + python -m pip install .[test,optional] + python -m docstub --version + docstub --help - name: Run pytest run: >- @@ -70,12 +73,12 @@ jobs: - name: Compare example stubs run: | - python -m docstub -v --config=examples/docstub.toml examples/example_pkg + python -m docstub run -v --config=examples/docstub.toml examples/example_pkg git diff --exit-code examples/ && echo "Stubs for example_pkg did not change" - name: Generate stubs for docstub run: | - python -m docstub -v src/docstub -o ${MYPYPATH}/docstub + python -m docstub run -v src/docstub -o ${MYPYPATH}/docstub - name: Check with mypy.stubtest run: | diff --git a/doc/command_line.md b/doc/command_line.md index 168893e..8e7d92e 100644 --- a/doc/command_line.md +++ b/doc/command_line.md @@ -1,25 +1,41 @@ # Command line reference -Running -``` -docstub --help +## Command `docstub` + + + + +```plain +Usage: docstub [OPTIONS] COMMAND [ARGS]... + + Generate Python stub files from docstrings. + +Options: + --version Show the version and exit. + -h, --help Show this message and exit. + +Commands: + run Generate Python stub files. ``` -will print + + + + +## Command `docstub run` - + ```plain -Usage: docstub [OPTIONS] PACKAGE_PATH +Usage: docstub run [OPTIONS] PACKAGE_PATH - Generate Python stub files with type annotations from docstrings. + Generate Python stub files. - Given a path `PACKAGE_PATH` to a Python package, generate stub files for it. - Type descriptions in docstrings will be used to fill in missing inline type + Given a `PACKAGE_PATH` to a Python package, generate stub files for it. Type + descriptions in docstrings will be used to fill in missing inline type annotations or to override them. Options: - --version Show the version and exit. -o, --out-dir PATH Set output directory explicitly. Stubs will be directly written into that directory while preserving the directory structure under `PACKAGE_PATH`. Otherwise, @@ -38,4 +54,4 @@ Options: -h, --help Show this message and exit. ``` - + diff --git a/doc/user_guide.md b/doc/user_guide.md index 99d738a..786e2d2 100644 --- a/doc/user_guide.md +++ b/doc/user_guide.md @@ -56,7 +56,7 @@ def example_metric(image, *, mask=None, sigma=1.0, method='standard'): Feeding this input to docstub with ```shell -docstub example.py +docstub run example.py ``` will create `example.pyi` in the same directory diff --git a/pyproject.toml b/pyproject.toml index 08011a0..7963789 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,7 @@ test = [ Home = "https://github.com/lagru/docstub" [project.scripts] -docstub = "docstub.__main__:main" +docstub = "docstub.__main__:cli" [tool.setuptools_scm] diff --git a/src/docstub/__main__.py b/src/docstub/__main__.py index 1b61679..db4f0cb 100644 --- a/src/docstub/__main__.py +++ b/src/docstub/__main__.py @@ -1,4 +1,4 @@ -from ._cli import main +from ._cli import cli if __name__ == "__main__": - main() + cli() diff --git a/src/docstub/_cli.py b/src/docstub/_cli.py index 6128096..23d5644 100644 --- a/src/docstub/_cli.py +++ b/src/docstub/_cli.py @@ -128,11 +128,19 @@ def report_execution_time(): click.echo(f"Finished in {formated_duration}") -# Preserve click.command below to keep type checker happy # docstub: off -@click.command() +@click.group() # docstub: on @click.version_option(__version__) +@click.help_option("-h", "--help") +def cli(): + """Generate Python stub files from docstrings.""" + + +# Preserve click.command below to keep type checker happy +# docstub: off +@cli.command() +# docstub: on @click.argument("root_path", type=click.Path(exists=True), metavar="PACKAGE_PATH") @click.option( "-o", @@ -174,10 +182,10 @@ def report_execution_time(): @click.option("-v", "--verbose", count=True, help="Print more details (repeatable).") @click.help_option("-h", "--help") @report_execution_time() -def main(root_path, out_dir, config_paths, group_errors, allow_errors, verbose): - """Generate Python stub files with type annotations from docstrings. +def run(root_path, out_dir, config_paths, group_errors, allow_errors, verbose): + """Generate Python stub files. - Given a path `PACKAGE_PATH` to a Python package, generate stub files for it. + Given a `PACKAGE_PATH` to a Python package, generate stub files for it. Type descriptions in docstrings will be used to fill in missing inline type annotations or to override them. \f diff --git a/tests/test_analysis.py b/tests/test_analysis.py index c23bada..3f0cb5c 100644 --- a/tests/test_analysis.py +++ b/tests/test_analysis.py @@ -7,7 +7,7 @@ class Test_KnownImport: def test_dot_in_alias(self): - with pytest.raises(ValueError, match=".*can't contain a '\.'"): + with pytest.raises(ValueError, match=r".*can't contain a '\.'"): KnownImport(import_name="foo.bar.baz", import_alias="bar.baz") diff --git a/tests/test_doc.py b/tests/test_doc.py index 35c83ee..746d6bb 100644 --- a/tests/test_doc.py +++ b/tests/test_doc.py @@ -4,14 +4,15 @@ from pathlib import Path import click +import pytest from click.testing import CliRunner -from docstub._cli import main as docstub_main +from docstub import _cli PROJECT_ROOT = Path(__file__).parent.parent -def test_getting_started_example(tmp_path): +def test_user_guide_example(tmp_path): # Load user guide md_file = PROJECT_ROOT / "doc/user_guide.md" with md_file.open("r") as io: @@ -32,7 +33,7 @@ def test_getting_started_example(tmp_path): with py_file.open("x") as io: io.write(py_source) runner = CliRunner() - run_result = runner.invoke(docstub_main, [str(py_file)]) # noqa: F841 + run_result = runner.invoke(_cli.run, [str(py_file)]) # noqa: F841 # Load created PYI file, this is what we expect to find in the user guide's # code block for example.pyi @@ -54,18 +55,22 @@ def test_getting_started_example(tmp_path): assert expected_pyi == actual_pyi -def test_command_line_help(): - ctx = click.Context(docstub_main, info_name="docstub") +@pytest.mark.parametrize( + ("command", "name"), [(_cli.cli, "docstub"), (_cli.run, "docstub run")] +) +def test_command_line_reference(command, name): + ctx = click.Context(command, info_name=name) expected_help = f""" ```plain -{docstub_main.get_help(ctx)} +{command.get_help(ctx)} ``` """.strip() md_file = PROJECT_ROOT / "doc/command_line.md" with md_file.open("r") as io: md_content = io.read() - regex = r"(.*)" + guard_name = f"cli-{name.replace(" ", "-")}" + regex = rf"(.*)" matches = re.findall(regex, md_content, flags=re.DOTALL) assert len(matches) == 1