Skip to content

Commit 2866a12

Browse files
committed
Switch CLI to Typer from Click
1 parent d19109b commit 2866a12

File tree

6 files changed

+88
-96
lines changed

6 files changed

+88
-96
lines changed

openapi_python_client/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,23 @@
99
from .openapi_parser import OpenAPI, import_string_from_reference
1010

1111

12-
def main(*, url: Optional[str], path: Optional[str]) -> None:
12+
def main(*, url: Optional[str], path: Optional[Path]) -> None:
1313
""" Generate the client library """
1414
data_dict = _get_json(url=url, path=path)
1515
openapi = OpenAPI.from_dict(data_dict)
1616
project = _Project(openapi=openapi)
1717
project.build()
1818

1919

20-
def _get_json(*, url: Optional[str], path: Optional[str]) -> Dict[str, Any]:
20+
def _get_json(*, url: Optional[str], path: Optional[Path]) -> Dict[str, Any]:
2121
json_bytes: bytes
2222
if url is not None and path is not None:
2323
raise ValueError("Provide URL or Path, not both.")
2424
elif url is not None:
2525
response = requests.get(url)
2626
json_bytes = response.content
2727
elif path is not None:
28-
json_bytes = Path(path).read_bytes()
28+
json_bytes = path.read_bytes()
2929
else:
3030
raise ValueError("No URL or Path provided")
3131
return json.loads(json_bytes)

openapi_python_client/cli.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
1-
from importlib.metadata import version
1+
import pathlib
22
from typing import Optional
33

4-
import click
4+
import typer
55

66
from . import main
77

8+
app = typer.Typer()
89

9-
@click.group()
10-
@click.version_option(version(__package__), prog_name="OpenAPI Python Client")
10+
11+
@app.callback()
1112
def cli() -> None:
12-
""" Entrypoint into CLI """
13+
""" Generate a Python client from an OpenAPI JSON document """
1314
pass
1415

1516

16-
@cli.command()
17-
@click.option("--url", help="The URL to the openapi.json file")
18-
@click.option("--path", help="The path to the openapi.json file")
19-
def generate(url: Optional[str], path: Optional[str]) -> None:
17+
@app.command()
18+
def generate(
19+
url: Optional[str] = typer.Option(None, help="A URL to read the JSON from"),
20+
path: Optional[pathlib.Path] = typer.Option(None, help="A path to the JSON file")
21+
) -> None:
2022
""" Generate a new OpenAPI Client library """
2123
if not url and not path:
22-
click.secho("You must either provide --url or --path", fg="red")
23-
exit(1)
24+
typer.secho("You must either provide --url or --path", fg=typer.colors.RED)
25+
raise typer.Exit(code=1)
2426
elif url and path:
25-
click.secho("Provide either --url or --path, not both", fg="red")
26-
exit(1)
27+
typer.secho("Provide either --url or --path, not both", fg=typer.colors.RED)
28+
raise typer.Exit(code=1)
2729
main(url=url, path=path)

poetry.lock

Lines changed: 53 additions & 33 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ python = "==3.*,>=3.8.0"
1919
requests = "^2.22.0"
2020
jinja2 = "^2.11.1"
2121
stringcase = "^1.2.0"
22-
click = "^7.0"
22+
typer = "^0.0.8"
23+
colorama = {version = "^0.4.3", markers = "sys_platform == 'win32'"}
2324

2425
[tool.poetry.scripts]
25-
openapi-python-client = "openapi_python_client.cli:cli"
26+
openapi-python-client = "openapi_python_client.cli:app"
2627

2728
[tool.poetry.dev-dependencies]
2829
pytest = "*"

tests/test___init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ def test__get_json_url_no_path(self, mocker):
6565

6666
def test__get_json_path_no_url(self, mocker):
6767
get = mocker.patch("requests.get")
68-
Path = mocker.patch("openapi_python_client.Path")
6968
loads = mocker.patch("json.loads")
7069

7170
from openapi_python_client import _get_json
@@ -74,8 +73,8 @@ def test__get_json_path_no_url(self, mocker):
7473
_get_json(url=None, path=path)
7574

7675
get.assert_not_called()
77-
Path.assert_called_once_with(path)
78-
loads.assert_called_once_with(Path().read_bytes())
76+
path.read_bytes.assert_called_once()
77+
loads.assert_called_once_with(path.read_bytes())
7978

8079

8180
class TestProject:

tests/test_cli.py

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,22 @@
1-
from click.testing import CliRunner
1+
import pytest
2+
import typer
23

34

45
def test_generate_no_params(mocker):
56
main = mocker.patch("openapi_python_client.cli.main")
67
from openapi_python_client.cli import generate
7-
8-
runner = CliRunner()
9-
result = runner.invoke(generate)
10-
11-
assert result.exit_code == 1
12-
assert result.output == "You must either provide --url or --path\n"
8+
with pytest.raises(typer.Exit) as exc_info:
9+
generate()
10+
assert exc_info.value.exit_code == 1
1311
main.assert_not_called()
1412

1513

1614
def test_generate_url_and_path(mocker):
1715
main = mocker.patch("openapi_python_client.cli.main")
1816
from openapi_python_client.cli import generate
19-
20-
runner = CliRunner()
21-
result = runner.invoke(generate, ["--url=blah", "--path=blahblah"])
22-
23-
assert result.exit_code == 1
24-
assert result.output == "Provide either --url or --path, not both\n"
17+
with pytest.raises(typer.Exit) as exc_info:
18+
generate(url="blah", path="other_blah")
19+
assert exc_info.value.exit_code == 1
2520
main.assert_not_called()
2621

2722

@@ -30,41 +25,16 @@ def test_generate_url(mocker):
3025
url = mocker.MagicMock()
3126
from openapi_python_client.cli import generate
3227

33-
runner = CliRunner()
34-
result = runner.invoke(generate, [f"--url={url}"])
28+
generate(url=url, path=None)
3529

36-
assert result.exit_code == 0
37-
main.assert_called_once_with(url=str(url), path=None)
30+
main.assert_called_once_with(url=url, path=None)
3831

3932

4033
def test_generate_path(mocker):
4134
main = mocker.patch("openapi_python_client.cli.main")
4235
path = mocker.MagicMock()
4336
from openapi_python_client.cli import generate
4437

45-
runner = CliRunner()
46-
result = runner.invoke(generate, [f"--path={path}"])
47-
48-
assert result.exit_code == 0
49-
main.assert_called_once_with(path=str(path), url=None)
50-
51-
52-
def test_version():
53-
from importlib.metadata import version
54-
from openapi_python_client.cli import cli
55-
56-
runner = CliRunner()
57-
result = runner.invoke(cli, ["--version"])
58-
59-
assert result.exit_code == 0
60-
assert result.output == f"OpenAPI Python Client, version {version('openapi-python-client')}\n"
61-
62-
63-
def test_no_params():
64-
from openapi_python_client.cli import cli
65-
66-
runner = CliRunner()
67-
result = runner.invoke(cli, [])
38+
generate(url=None, path=path)
6839

69-
assert result.exit_code == 0
70-
assert "Usage" in result.output
40+
main.assert_called_once_with(url=None, path=path)

0 commit comments

Comments
 (0)