Skip to content

Commit

Permalink
Add header from noxfile.py docstring #454 (#459)
Browse files Browse the repository at this point in the history
* Add header from noxfile.py docstring #454

This commit adds the functionality for using the `noxfile.py` module
docstring as a header description for the `nox -l` option.

The module docstring is now an attribute in `Manifest` which is
now populated in `discover_manifest` which is in-turn passed
to `honor_list_request` which will print the docstring if it is
present, and do nothing if it is not present.

I've also added two tests which cover these conditions (existent and
non-existent module docstring) and added to an existing
parametrized test.

* Standardise printed docstring whitespace

Co-authored-by: Claudio Jolowicz <mail@claudiojolowicz.com>
  • Loading branch information
FollowTheProcess and cjolowicz authored Jul 4, 2021
1 parent 5ac156f commit 0d4764e
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 5 deletions.
8 changes: 7 additions & 1 deletion nox/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,21 @@ class Manifest:
session_functions (Mapping[str, function]): The registry of discovered
session functions.
global_config (.nox.main.GlobalConfig): The global configuration.
module_docstring (Optional[str]): The user noxfile.py docstring.
Defaults to `None`.
"""

def __init__(
self, session_functions: Mapping[str, "Func"], global_config: argparse.Namespace
self,
session_functions: Mapping[str, "Func"],
global_config: argparse.Namespace,
module_docstring: Optional[str] = None,
) -> None:
self._all_sessions = [] # type: List[SessionRunner]
self._queue = [] # type: List[SessionRunner]
self._consumed = [] # type: List[SessionRunner]
self._config = global_config # type: argparse.Namespace
self.module_docstring = module_docstring # type: Optional[str]

# Create the sessions based on the provided session functions.
for name, func in session_functions.items():
Expand Down
9 changes: 7 additions & 2 deletions nox/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,11 @@ def discover_manifest(
# sorted by decorator call time.
functions = registry.get()

# Get the docstring from the noxfile
module_docstring = module.__doc__

# Return the final dictionary of session functions.
return Manifest(functions, global_config)
return Manifest(functions, global_config, module_docstring)


def filter_manifest(
Expand Down Expand Up @@ -166,7 +169,9 @@ def honor_list_request(
return manifest

# If the user just asked for a list of sessions, print that
# and be done.
# and any docstring specified in noxfile.py and be done.
if manifest.module_docstring:
print(manifest.module_docstring.strip(), end="\n\n")

print("Sessions defined in {noxfile}:\n".format(noxfile=global_config.noxfile))

Expand Down
1 change: 1 addition & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.


import functools
import os
import platform
Expand Down
52 changes: 50 additions & 2 deletions tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,21 @@ def test_honor_list_request_noop():
assert return_value is manifest


@pytest.mark.parametrize("description", [None, "bar"])
def test_honor_list_request(description):
@pytest.mark.parametrize(
"description, module_docstring",
[
(None, None),
(None, "hello docstring"),
("Bar", None),
("Bar", "hello docstring"),
],
)
def test_honor_list_request(description, module_docstring):
config = _options.options.namespace(
list_sessions=True, noxfile="noxfile.py", color=False
)
manifest = mock.create_autospec(Manifest)
manifest.module_docstring = module_docstring
manifest.list_all_sessions.return_value = [
(argparse.Namespace(friendly_name="foo", description=description), True)
]
Expand All @@ -218,6 +227,7 @@ def test_honor_list_request_skip_and_selected(capsys):
list_sessions=True, noxfile="noxfile.py", color=False
)
manifest = mock.create_autospec(Manifest)
manifest.module_docstring = None
manifest.list_all_sessions.return_value = [
(argparse.Namespace(friendly_name="foo", description=None), True),
(argparse.Namespace(friendly_name="bar", description=None), False),
Expand All @@ -231,6 +241,44 @@ def test_honor_list_request_skip_and_selected(capsys):
assert "- bar" in out


def test_honor_list_request_prints_docstring_if_present(capsys):
config = _options.options.namespace(
list_sessions=True, noxfile="noxfile.py", color=False
)
manifest = mock.create_autospec(Manifest)
manifest.module_docstring = "Hello I'm a docstring"
manifest.list_all_sessions.return_value = [
(argparse.Namespace(friendly_name="foo", description=None), True),
(argparse.Namespace(friendly_name="bar", description=None), False),
]

return_value = tasks.honor_list_request(manifest, global_config=config)
assert return_value == 0

out = capsys.readouterr().out

assert "Hello I'm a docstring" in out


def test_honor_list_request_doesnt_print_docstring_if_not_present(capsys):
config = _options.options.namespace(
list_sessions=True, noxfile="noxfile.py", color=False
)
manifest = mock.create_autospec(Manifest)
manifest.module_docstring = None
manifest.list_all_sessions.return_value = [
(argparse.Namespace(friendly_name="foo", description=None), True),
(argparse.Namespace(friendly_name="bar", description=None), False),
]

return_value = tasks.honor_list_request(manifest, global_config=config)
assert return_value == 0

out = capsys.readouterr().out

assert "Hello I'm a docstring" not in out


def test_verify_manifest_empty():
config = _options.options.namespace(sessions=(), keywords=())
manifest = Manifest({}, config)
Expand Down

0 comments on commit 0d4764e

Please sign in to comment.