Skip to content

Commit

Permalink
Merge pull request #7 from NREL/pp/ignore_doc_params
Browse files Browse the repository at this point in the history
Option to explicitly ignore some parameters in the documentation
  • Loading branch information
ppinchuk authored May 18, 2023
2 parents 3a85931 + c8f0022 commit 558fb0a
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 17 deletions.
56 changes: 43 additions & 13 deletions gaps/cli/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,15 @@ def __init__(
add_collect=False,
split_keys=None,
config_preprocessor=None,
skip_doc_params=None,
):
self.name = name
self.add_collect = add_collect
self.split_keys = set() if split_keys is None else set(split_keys)
self.config_preprocessor = config_preprocessor or _passthrough
self.skip_doc_params = (
set() if skip_doc_params is None else set(skip_doc_params)
)
preprocessor_sig = signature(self.config_preprocessor)
self.preprocessor_args = preprocessor_sig.parameters.keys()
self.preprocessor_defaults = {
Expand Down Expand Up @@ -95,6 +99,7 @@ def __init__(
add_collect=False,
split_keys=None,
config_preprocessor=None,
skip_doc_params=None,
):
"""
Expand Down Expand Up @@ -156,9 +161,12 @@ def __init__(
it is expected that the ``config_preprocessor`` function
fills these arguments in programmatically before the
function is distributed across nodes. See the implementation
of :func:`gaps.cli.preprocessing.preprocess_collect_config`
and :func:`gaps.cli.collect.collect` for an example of this
pattern.
of :func:`gaps.cli.collect.collect` and
:func:`gaps.cli.preprocessing.preprocess_collect_config`
for an example of this pattern. You can use the
``skip_doc_params`` input below to achieve the same results
without the underscore syntax (helpful for public-facing
functions).
name : str, optional
Name of the command. This will be the name used to call the
command on the terminal. This name does not have to match
Expand Down Expand Up @@ -258,12 +266,21 @@ def __init__(
parameter, do not request it in the preprocessing function
docstring - extract it from the config dictionary instead).
By default, ``None``.
skip_doc_params : iterable of str, optional
Optional iterable of parameter names that should be excluded
from the documentation/template configuration files. This
can be useful if your pre-processing function automatically
sets some parameters based on other user input. This option
is an alternative to the "private" arguments discussed in
the ``function`` parameter documentation above. By default,
``None``.
"""
super().__init__(
name or function.__name__.strip("_").replace("_", "-"),
add_collect,
split_keys,
config_preprocessor,
skip_doc_params,
)
self.runner = function

Expand All @@ -273,7 +290,7 @@ def documentation(self):
return CommandDocumentation(
self.runner,
self.config_preprocessor,
skip_params=GAPS_SUPPLIED_ARGS,
skip_params=GAPS_SUPPLIED_ARGS | self.skip_doc_params,
is_split_spatially=self.is_split_spatially,
)

Expand Down Expand Up @@ -326,6 +343,7 @@ def __init__(
add_collect=False,
split_keys=None,
config_preprocessor=None,
skip_doc_params=None,
):
"""
Expand Down Expand Up @@ -379,22 +397,25 @@ def __init__(
Path to output directory - typically equivalent to
the project directory.
If your method is capable of multiprocessing, you should
also include ``max_workers`` in the method signature.
If your function is capable of multiprocessing, you should
also include ``max_workers`` in the function signature.
``gaps`` will pass an integer equal to the number of
processes the user wants to run on a single node for this
value. Note that the ``config`` parameter is not allowed as
a method signature item. Please request all the required
keys/inputs directly. This method can also request
a function signature item. Please request all the required
keys/inputs directly. This function can also request
"private" arguments by including a leading underscore in the
argument name. These arguments are NOT exposed to users in
the documentation or template configuration files. Instead,
it is expected that the ``config_preprocessor`` function
fills these arguments in programmatically before the
method is distributed across nodes. See the implementation
of :func:`gaps.cli.preprocessing.preprocess_collect_config`
and :func:`gaps.cli.collect.collect` for an example of this
pattern.
function is distributed across nodes. See the implementation
of :func:`gaps.cli.collect.collect` and
:func:`gaps.cli.preprocessing.preprocess_collect_config`
for an example of this pattern. You can use the
``skip_doc_params`` input below to achieve the same results
without the underscore syntax (helpful for public-facing
functions).
name : str, optional
Name of the command. This will be the name used to call the
command on the terminal. This name does not have to match
Expand Down Expand Up @@ -493,12 +514,21 @@ def __init__(
parameter, do not request it in the preprocessing function
docstring - extract it from the config dictionary instead).
By default, ``None``.
skip_doc_params : iterable of str, optional
Optional iterable of parameter names that should be excluded
from the documentation/template configuration files. This
can be useful if your pre-processing function automatically
sets some parameters based on other user input. This option
is an alternative to the "private" arguments discussed in
the ``function`` parameter documentation above. By default,
``None``.
"""
super().__init__(
name or method.strip("_").replace("_", "-"),
add_collect,
split_keys,
config_preprocessor,
skip_doc_params,
)
self.runner = init
self.run_method = method
Expand All @@ -515,7 +545,7 @@ def documentation(self):
self.runner,
getattr(self.runner, self.run_method),
self.config_preprocessor,
skip_params=GAPS_SUPPLIED_ARGS,
skip_params=GAPS_SUPPLIED_ARGS | self.skip_doc_params,
is_split_spatially=self.is_split_spatially,
)

Expand Down
2 changes: 1 addition & 1 deletion gaps/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""GAPs Version Number. """

__version__ = "0.3.1"
__version__ = "0.3.2"
79 changes: 76 additions & 3 deletions tests/cli/test_cli_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,27 @@ def _testing_function(
_input2=None,
_z_0=None,
):
"""Test function to make CLI around."""
"""Test function to make CLI around.
Parameters
----------
project_points : path-like
Path to project points.
input1 : int
Input 1.
input3 : str
Input 3.
out_dir : path-like
Path to out dir.
tag : str
Internal GAPs tag.
max_workers : int
Max workers.
_input2 : float, optional
Secret input 2. By default, ``None``.
_z_0 : str, optional
Secret str. By default, ``None``.
"""
is_pp = isinstance(project_points, ProjectPoints)
out_fp = Path(out_dir) / f"out{tag}.json"
out_vals = {
Expand All @@ -62,13 +82,37 @@ class TestCommand:
"""Test command class."""

def __init__(self, input1, input3, _input2=None):
"""Test function to make CLI around."""
"""est function to make CLI around.
Parameters
----------
input1 : int
Input 1.
input3 : str
Input 3.
_input2 : float, optional
Secret input 2. By default, ``None``.
"""
self._input1 = input1
self._input2 = _input2
self._input3 = input3

def run(self, project_points, out_dir, tag, max_workers, _z_0=None):
"""Test run function for CLI around."""
"""Test run function for CLI around.
Parameters
----------
project_points : path-like
Path to project points.
out_dir : path-like
Path to out dir.
tag : str
Internal GAPs tag.
max_workers : int
Max workers.
_z_0 : str, optional
Secret str. By default, ``None``.
"""
is_pp = isinstance(project_points, ProjectPoints)
out_fp = Path(out_dir) / f"out{tag}.json"
out_vals = {
Expand Down Expand Up @@ -511,6 +555,35 @@ def test_run_local_multiple_out_files(test_ctx, runnable_script, test_class):
assert "_j" in job_name


@pytest.mark.parametrize("test_class", [False, True])
def test_command_skip_doc_params(test_class):
"""Test the `command` class with skip params."""

if test_class:
command_config = CLICommandFromClass(
TestCommand,
"run",
split_keys={"input3"},
skip_doc_params={"input1"},
)
else:
command_config = CLICommandFromFunction(
_testing_function,
name="run",
split_keys={"input3"},
skip_doc_params={"input1"},
)

assert "input1" not in command_config.documentation.parameter_help
assert "input1" not in command_config.documentation.template_config

assert "_input2" not in command_config.documentation.parameter_help
assert "_input2" not in command_config.documentation.template_config

assert "input3" in command_config.documentation.parameter_help
assert "input3" in command_config.documentation.template_config


def test_validate_config():
"""Test the `_validate_config` function."""

Expand Down

0 comments on commit 558fb0a

Please sign in to comment.