Skip to content

Commit

Permalink
feat: --json --list-sessions (#665)
Browse files Browse the repository at this point in the history
Closes #658
  • Loading branch information
henryiii committed Mar 5, 2023
1 parent befe771 commit 119fd00
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 2 deletions.
5 changes: 5 additions & 0 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ To list all available sessions, including parametrized sessions:
nox --list
nox --list-sessions
If you'd like to use the output in later processing, you can add ``--json`` to
get json output for the selected session. Fields include ``session`` (pretty
name), ``name``, ``description``, ``python`` (null if not specified), ``tags``,
and ``call_spec`` (for parametrized sessions).


.. _session_execution_order:

Expand Down
7 changes: 7 additions & 0 deletions nox/_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,13 @@ def _session_completer(
action="store_true",
help="List all available sessions and exit.",
),
_option_set.Option(
"json",
"--json",
group=options.groups["sessions"],
action="store_true",
help="JSON output formatting. Requires list-sessions currently.",
),
_option_set.Option(
"sessions",
"-s",
Expand Down
30 changes: 28 additions & 2 deletions nox/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ def filter_manifest(manifest: Manifest, global_config: Namespace) -> Manifest |
logger.error("Error while collecting sessions.")
logger.error(exc.args[0])
return 3

if not manifest and not global_config.list_sessions:
print("No sessions selected. Please select a session with -s <session name>.\n")
_produce_listing(manifest, global_config)
Expand Down Expand Up @@ -264,6 +265,23 @@ def _produce_listing(manifest: Manifest, global_config: Namespace) -> None:
)


def _produce_json_listing(manifest: Manifest, global_config: Namespace) -> None:
report = []
for session, selected in manifest.list_all_sessions():
if selected:
report.append(
{
"session": session.friendly_name,
"name": session.name,
"description": session.description or "",
"python": session.func.python,
"tags": session.tags,
"call_spec": getattr(session.func, "call_spec", {}),
}
)
print(json.dumps(report))


def honor_list_request(manifest: Manifest, global_config: Namespace) -> Manifest | int:
"""If --list was passed, simply list the manifest and exit cleanly.
Expand All @@ -275,10 +293,18 @@ def honor_list_request(manifest: Manifest, global_config: Namespace) -> Manifest
Union[~.Manifest,int]: ``0`` if a listing is all that is requested,
the manifest otherwise (to be sent to the next task).
"""
if not global_config.list_sessions:
if not (global_config.list_sessions or global_config.json):
return manifest

_produce_listing(manifest, global_config)
# JSON output requires list sessions also be specified
if global_config.json and not global_config.list_sessions:
logger.error("Must specify --list-sessions with --json")
return 3

if global_config.json:
_produce_json_listing(manifest, global_config)
else:
_produce_listing(manifest, global_config)

return 0

Expand Down
58 changes: 58 additions & 0 deletions tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,64 @@ def test_honor_list_request_doesnt_print_docstring_if_not_present(capsys):
assert "Hello I'm a docstring" not in out


def test_honor_list_json_request(capsys):
config = _options.options.namespace(
list_sessions=True, noxfile="noxfile.py", json=True
)
manifest = mock.create_autospec(Manifest)
manifest.list_all_sessions.return_value = [
(
argparse.Namespace(
name="bar",
friendly_name="foo",
description="simple",
func=argparse.Namespace(python="123"),
tags=[],
),
True,
),
(
argparse.Namespace(),
False,
),
]
return_value = tasks.honor_list_request(manifest, global_config=config)
assert return_value == 0
assert json.loads(capsys.readouterr().out) == [
{
"session": "foo",
"name": "bar",
"description": "simple",
"python": "123",
"tags": [],
"call_spec": {},
}
]


def test_refuse_json_nolist_request(caplog):
config = _options.options.namespace(
list_sessions=False, noxfile="noxfile.py", json=True
)
manifest = mock.create_autospec(Manifest)
manifest.list_all_sessions.return_value = [
(
argparse.Namespace(
name="bar",
friendly_name="foo",
description="simple",
func=argparse.Namespace(python="123"),
tags=[],
),
True,
)
]
return_value = tasks.honor_list_request(manifest, global_config=config)
assert return_value == 3
(record,) = caplog.records
assert record.message == "Must specify --list-sessions with --json"


def test_empty_session_list_in_noxfile(capsys):
config = _options.options.namespace(noxfile="noxfile.py", sessions=(), posargs=[])
manifest = Manifest({"session": session_func}, config)
Expand Down

0 comments on commit 119fd00

Please sign in to comment.