-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add argskwargs parser for makefile style cli args. Closes #284
- Loading branch information
Showing
2 changed files
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
"""Context parser that returns a list from input arguments. | ||
Takes input args (i.e separated by spaces on cli) and returns a list named | ||
argList. | ||
Where args are key=value pairs, returns a dictionary where each pair becomes a | ||
dictionary element. | ||
Don't have spaces in your values unless your really mean it. "k1=v1 ' k2'=v2" | ||
will result in a context key name of ' k2' not 'k2'. | ||
So cli input like this "ham eggs bacon drink=coffee", will yield context: | ||
{ 'argList': ['ham', 'eggs', 'bacon'], 'drink': 'coffee'} | ||
""" | ||
# can remove __future__ once py 3.10 the lowest supported version | ||
from __future__ import annotations | ||
from collections.abc import Mapping | ||
import logging | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
ARG_LIST_KEY = 'argList' | ||
|
||
|
||
def get_parsed_context(args: list[str] | None) -> Mapping: | ||
"""Create dict from combination of args & kwargs passed from cli. | ||
This supports the style of args that makefile does, i.e | ||
$ pypyr pipeline-name arg1 arg2 key1=value1 key2-"value 2" | ||
args go to context key `argList`. key=value pairs become context dictionary | ||
elements at root. | ||
Args: | ||
args: list of string. Passed from command-line invocation where: | ||
$ pypyr pipelinename this is the context_arg | ||
This would result in args == ['this', 'is', 'the', 'context_arg'] | ||
Returns: | ||
dict. This dict will initialize the context for the pipeline run. | ||
The dict will have key `argList` with empty list [] if no args | ||
passed. | ||
""" | ||
logger.debug("starting") | ||
if not args: | ||
logger.debug( | ||
"pipeline invoked without context arg set. For this\n" | ||
"argskwargs parser you're looking for something like:\n" | ||
"pypyr pipelinename arg1 arg2 k1=v1 k2=\"v 2\"" | ||
) | ||
return {ARG_LIST_KEY: []} | ||
arg_list = [] | ||
out: dict[str, str | list] = {} | ||
for a in args: | ||
# 1st = is separator, subsequent = just taken as part of the value | ||
key, sep, value = a.partition('=') | ||
if sep: | ||
out[key] = value | ||
else: | ||
arg_list.append(a) | ||
|
||
out[ARG_LIST_KEY] = arg_list | ||
|
||
return out |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
"""Unit tests for pypyr.parser.argskwargs.""" | ||
|
||
from pypyr.parser.argskwargs import get_parsed_context | ||
|
||
|
||
def test_argskwargs_empty_input(): | ||
"""Parse empty inputs.""" | ||
assert get_parsed_context([]) == {'argList': []} | ||
assert get_parsed_context(None) == {'argList': []} | ||
|
||
|
||
def test_argskwargs_args_only(): | ||
"""Parse when only args.""" | ||
assert get_parsed_context(['a']) == {'argList': ['a']} | ||
assert get_parsed_context(['a', 'b b', 'c']) == {'argList': | ||
['a', 'b b', 'c']} | ||
|
||
|
||
def test_argskwargs_kwargs_only(): | ||
"""Parse when only kwargs.""" | ||
assert get_parsed_context(['k1=value 1']) == {'argList': [], | ||
'k1': 'value 1'} | ||
assert get_parsed_context(['k1=value 1', 'k2=v2=3']) == {'argList': [], | ||
'k1': 'value 1', | ||
'k2': 'v2=3'} | ||
|
||
|
||
def test_argskwargs_args_and_kwargs(): | ||
"""Parse when args + kwargs.""" | ||
assert get_parsed_context(['a', 'b', 'c d', | ||
'k1="value 1"', 'k2=v2']) == { | ||
'argList': ['a', 'b', 'c d'], | ||
'k1': '"value 1"', | ||
'k2': 'v2'} |