Skip to content

Commit 2e528c6

Browse files
committed
Add CLI
1 parent fc0fb8a commit 2e528c6

4 files changed

Lines changed: 104 additions & 3 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ optional-dependencies.test = [
5454
urls.Documentation = "https://github.com/flying-sheep/session-info2#readme"
5555
urls.Issues = "https://github.com/flying-sheep/session-info2/issues"
5656
urls.Source = "https://github.com/flying-sheep/session-info2"
57+
scripts.session-info = "session_info2.cli:main"
5758

5859
[tool.hatch.version]
5960
source = "vcs"
@@ -105,7 +106,7 @@ lint.per-file-ignores."**/*.ipynb" = [
105106
lint.per-file-ignores."docs/conf.py" = [
106107
"INP001", # __init__.py
107108
]
108-
lint.per-file-ignores."src/session_info2/__main__.py" = [
109+
lint.per-file-ignores."src/session_info2/cli.py" = [
109110
"T201", # print is fine
110111
]
111112
lint.per-file-ignores."tests/*" = [

src/session_info2/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33

44
from __future__ import annotations
55

6-
from . import session_info
6+
from .cli import main
77

8-
print(session_info(cpu=True, dependencies=True))
8+
main()

src/session_info2/cli.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
"""CLI."""
3+
4+
from __future__ import annotations
5+
6+
import sys
7+
from argparse import ArgumentParser, Namespace
8+
from argparse import BooleanOptionalAction as Ba
9+
from types import ModuleType
10+
from typing import Literal, get_args
11+
from unittest.mock import patch
12+
13+
from . import _repr, session_info
14+
15+
Format = Literal["text", "markdown", "html", "json"]
16+
17+
18+
class Args(Namespace):
19+
"""CLI arguments."""
20+
21+
packages: list[str]
22+
os: bool
23+
cpu: bool
24+
gpu: bool
25+
format: Format
26+
27+
@classmethod
28+
def parser(cls) -> ArgumentParser:
29+
"""Return argument parser."""
30+
parser = ArgumentParser()
31+
parser.add_argument("packages", nargs="*", help="packages to import")
32+
parser.add_argument(
33+
"--os", default=True, action=Ba, help="include OS name and version"
34+
)
35+
parser.add_argument(
36+
"--cpu", default=True, action=Ba, help="include number of CPU cores"
37+
)
38+
parser.add_argument(
39+
"--gpu",
40+
default=False,
41+
action=Ba,
42+
help="include information per supported GPU (disabled by default)",
43+
)
44+
parser.add_argument(
45+
"-f",
46+
"--format",
47+
default="text",
48+
choices=get_args(Format),
49+
help="output format",
50+
)
51+
return parser
52+
53+
@classmethod
54+
def parse(cls, args: list[str] | None = None) -> Args:
55+
"""Parse CLI arguments."""
56+
return cls.parser().parse_args(args, cls())
57+
58+
59+
def main(args_: list[str] | None = None, /) -> None:
60+
"""Run CLI."""
61+
args = Args.parse(args_)
62+
63+
modules = {name: __import__(name) for name in args.packages}
64+
65+
with patch.dict(sys.modules, __main__=type("__main__", (ModuleType,), modules)):
66+
si = session_info(cpu=True, dependencies=True)
67+
68+
match args.format:
69+
case "text":
70+
print(si)
71+
case "markdown":
72+
print(_repr.repr_markdown(si))
73+
case "html":
74+
print(_repr.repr_html(si))
75+
case "json":
76+
print(_repr.repr_json(si))
77+
case _:
78+
raise AssertionError

tests/test_cli.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# SPDX-License-Identifier: MPL-2.0
2+
"""Test the Command Line Interface."""
3+
4+
from __future__ import annotations
5+
6+
from typing import TYPE_CHECKING
7+
8+
from session_info2.cli import main
9+
10+
if TYPE_CHECKING:
11+
import pytest
12+
13+
14+
def test_cli(capsys: pytest.CaptureFixture[str]) -> None:
15+
main(["pytest"])
16+
17+
out, err = capsys.readouterr()
18+
19+
assert not err
20+
assert "pytest" in out
21+
assert "session-info2" in out
22+
assert out.index("pytest") < out.index("---") < out.index("session-info2")

0 commit comments

Comments
 (0)