-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: use Option for populating arguments
- Loading branch information
1 parent
b8a45d1
commit aef46e7
Showing
7 changed files
with
172 additions
and
193 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
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,101 @@ | ||
import argparse | ||
from enum import Enum | ||
from inspect import isclass | ||
from typing import Any, List, Optional, Tuple | ||
|
||
from ..types import UNDEFINED | ||
from ..typing_utils import match_types | ||
|
||
|
||
def get_action( | ||
_type, default=None, | ||
): | ||
if default is False: | ||
return "store_true" | ||
if default is True: | ||
return "store_false" | ||
if (_type is not UNDEFINED) and match_types(_type, (List, Tuple)): # type: ignore | ||
return "append" | ||
return "store" | ||
|
||
|
||
class Option: | ||
def __init__( | ||
self, | ||
flags: Tuple[str, ...] = (), | ||
type_: Any = UNDEFINED, | ||
default: Any = UNDEFINED, | ||
help_: str = "", | ||
metavar: Optional[str] = None, | ||
required=False, | ||
**kwargs, | ||
): | ||
"""Represent optional arguments to the command. | ||
Tries to be compatible to `ArgumentParser.add_argument | ||
https://docs.python.org/3/library/argparse.html#argparse.ArgumentParser.add_argument`_. | ||
:param flags: Either a name or a list of option strings, e.g. -f, --foo. | ||
:param default: The value produced if the argument is absent from the command line. | ||
* The default value assigned to a keyword argument helps determine | ||
the type of option and action. | ||
* The default value is assigned directly to the parser's default for that option. | ||
* In addition, it determines the ArgumentParser action | ||
* a default value of False implies store_true, while True implies store_false. | ||
* If the default value is a list, the action is append | ||
(multiple instances of that option are permitted). | ||
* Strings or None imply a store action. | ||
:param type_: The type to which the command-line argument should be converted. | ||
:param help_: A brief description of what the argument does. | ||
:param metavar: A name for the argument in usage messages. | ||
:param required: Whether or not the command-line option may be omitted (optionals only). | ||
:param kwargs: will be passed onto parser.add_argument | ||
""" | ||
|
||
# :param nargs: The number of command-line arguments that should be consumed. | ||
# nargs: to be generated from the type | ||
|
||
# action: Union[str, Type[argparse.Action]] | ||
# :param action: The basic type of action to be taken when this argument is encountered at the command line. | ||
|
||
# :param dest: The name of the attribute to be added to the object returned by parse_args(). | ||
|
||
# :param const: A constant value required by some action and nargs selections. | ||
# will be covered by type-hint and default value given | ||
|
||
# :param choices: A container of the allowable values for the argument. | ||
# will covered by enum type | ||
|
||
self.flags = flags | ||
|
||
if default is not UNDEFINED: | ||
kwargs["default"] = default | ||
|
||
if type_ is UNDEFINED and default is not None: | ||
type_ = type(default) | ||
|
||
kwargs.setdefault('action', get_action(type_, default)) | ||
|
||
if isclass(type_) and issubclass(type_, Enum): | ||
kwargs.setdefault("choices", [e.value for e in type_]) | ||
elif (type_ is not UNDEFINED) and type_ != bool: | ||
kwargs.setdefault("type", type_) | ||
|
||
kwargs.setdefault('help', help_) | ||
kwargs.setdefault('metavar', metavar) | ||
kwargs.setdefault('required', required) | ||
self.kwargs = kwargs | ||
|
||
def add(self, parser: argparse.ArgumentParser): | ||
return parser.add_argument(*self.flags, **self.kwargs) | ||
|
||
|
||
class Argument(Option): | ||
"""Represent positional argument that are required.""" | ||
|
||
def __init__( | ||
self, **kwargs, | ||
): | ||
"""See Option.__init__'s doc for more info.""" | ||
super().__init__(required=True, **kwargs) |
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
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,35 @@ | ||
from typing import Set | ||
|
||
|
||
def generate_options(): | ||
"""Coroutine to identify short options that haven't been used yet. | ||
Yields lists of short option (if available) and long option for | ||
the given name, keeping track of which short options have been previously | ||
used. | ||
If you aren't familiar with coroutines, use similar to a generator: | ||
x = generate_options() | ||
next(x) # advance coroutine past its initialization code | ||
params = x.send(param_name) | ||
""" | ||
used_short_options: Set[str] = set() | ||
param_name = yield | ||
while True: | ||
names = ["--" + param_name] | ||
for letter in param_name: | ||
if letter not in used_short_options: | ||
used_short_options.add(letter) | ||
names.insert(0, "-" + letter) | ||
break | ||
param_name = yield names | ||
|
||
|
||
def generate_flags( | ||
param, param_doc, option_generator, | ||
): | ||
names = [] | ||
|
||
while param_doc and param_doc[0].startswith("-"): | ||
names.append(param_doc.pop(0)) | ||
|
||
return names if names else option_generator.send(param) |
Oops, something went wrong.