-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Argparse "Overlay" Module #12873
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Argparse "Overlay" Module #12873
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
fd0ccf0
Implemented a wrapper module around the standard argparse package, ex…
Rostepher af96b10
Fixed imports in build_swift/argparse/__init__.py to make flake8 happy.
Rostepher ae6dfac
More re-formmating to meet the exacting standards of the python_lint …
Rostepher fa89a5d
Added doc-strings to all the modules in the build_swift argparse over…
Rostepher 40f30ff
Implemented a new BoolType for the argparse module which handles bool…
Rostepher 6894c6a
Fixed the mess of imports in the tests sub-package to favor relative …
Rostepher 2594ca7
Updated the add_positional method on the ArgumentParser builder class…
Rostepher 27fdc6e
Cleaned up the set_defaults method.
Rostepher 779eb6d
Added validation test to run the build_swift unit-tests.
Rostepher f53a214
Updated validation-test for the build_swift unit-test suite to use %u…
Rostepher 3b0dd5d
Fixed hard-coded default values in the expected_options module used f…
Rostepher 9926a62
Updated the comment in the Python validation test to run the build_sw…
Rostepher File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,53 @@ | ||
# This source file is part of the Swift.org open source project | ||
# | ||
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors | ||
# Licensed under Apache License v2.0 with Runtime Library Exception | ||
# | ||
# See https://swift.org/LICENSE.txt for license information | ||
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
|
||
|
||
""" | ||
Wrapper module around the standard argparse that extends the default | ||
functionality with support for multi-destination actions, an expressive DSL for | ||
constructing parsers and more argument types. This module exposes a strict | ||
super-set of the argparse API and is meant to be used as a drop-in replacement. | ||
""" | ||
|
||
|
||
from argparse import (ArgumentDefaultsHelpFormatter, ArgumentError, | ||
ArgumentTypeError, FileType, HelpFormatter, | ||
Namespace, RawDescriptionHelpFormatter, | ||
RawTextHelpFormatter) | ||
from argparse import ONE_OR_MORE, OPTIONAL, SUPPRESS, ZERO_OR_MORE | ||
|
||
from .actions import Action, Nargs | ||
from .parser import ArgumentParser | ||
from .types import (BoolType, ClangVersionType, PathType, RegexType, | ||
SwiftVersionType) | ||
|
||
|
||
__all__ = [ | ||
'Action', | ||
'ArgumentDefaultsHelpFormatter', | ||
'ArgumentError', | ||
'ArgumentParser', | ||
'ArgumentTypeError', | ||
'HelpFormatter', | ||
'Namespace', | ||
'Nargs', | ||
'RawDescriptionHelpFormatter', | ||
'RawTextHelpFormatter', | ||
|
||
'BoolType', | ||
'FileType', | ||
'PathType', | ||
'RegexType', | ||
'ClangVersionType', | ||
'SwiftVersionType', | ||
|
||
'SUPPRESS', | ||
'OPTIONAL', | ||
'ZERO_OR_MORE', | ||
'ONE_OR_MORE', | ||
] |
This file contains hidden or 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,337 @@ | ||
# This source file is part of the Swift.org open source project | ||
# | ||
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors | ||
# Licensed under Apache License v2.0 with Runtime Library Exception | ||
# | ||
# See https://swift.org/LICENSE.txt for license information | ||
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. docstring here as well. |
||
""" | ||
Hierarchy of action classes which support multiple destinations, similar to the | ||
default actions provided by the standard argparse. | ||
""" | ||
|
||
|
||
import argparse | ||
import copy | ||
|
||
from .types import BoolType, PathType | ||
|
||
|
||
__all__ = [ | ||
'Action', | ||
'Nargs', | ||
|
||
'AppendAction', | ||
'CustomCallAction', | ||
'StoreAction', | ||
'StoreIntAction', | ||
'StoreTrueAction', | ||
'StoreFalseAction', | ||
'StorePathAction', | ||
'ToggleTrueAction', | ||
'ToggleFalseAction', | ||
'UnsupportedAction', | ||
] | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
|
||
class Nargs(object): | ||
"""Container class holding valid values for the number of arguments | ||
actions can accept. Other possible values include integer literals. | ||
""" | ||
|
||
ZERO = 0 | ||
SINGLE = None | ||
OPTIONAL = argparse.OPTIONAL | ||
ZERO_OR_MORE = argparse.ZERO_OR_MORE | ||
ONE_OR_MORE = argparse.ONE_OR_MORE | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
|
||
class Action(argparse.Action): | ||
"""Slightly modified version of the Action class from argparse which has | ||
support for multiple destinations available rather than just a single one. | ||
""" | ||
|
||
def __init__(self, | ||
option_strings, | ||
dests=None, | ||
nargs=Nargs.SINGLE, | ||
const=None, | ||
default=None, | ||
type=None, | ||
choices=None, | ||
required=False, | ||
help=None, | ||
metavar=None, | ||
dest=None): # exists for compatibility purposes | ||
|
||
if dests is None and dest is None: | ||
raise TypeError('action must supply either dests or dest') | ||
|
||
dests = dests or dest | ||
if dests == argparse.SUPPRESS: | ||
dests = [] | ||
elif isinstance(dests, str): | ||
dests = [dests] | ||
|
||
super(Action, self).__init__( | ||
option_strings=option_strings, | ||
dest=argparse.SUPPRESS, | ||
nargs=nargs, | ||
const=const, | ||
default=default, | ||
type=type, | ||
choices=choices, | ||
required=required, | ||
help=help, | ||
metavar=metavar) | ||
|
||
self.dests = dests | ||
|
||
def _get_kwargs(self): | ||
"""Unofficial method used for pretty-printing out actions. | ||
""" | ||
|
||
names = [ | ||
'option_strings', | ||
'dests', | ||
'nargs', | ||
'const', | ||
'default', | ||
'type', | ||
'choices', | ||
'required', | ||
'help', | ||
'metavar', | ||
] | ||
|
||
return [(name, getattr(self, name)) for name in names] | ||
|
||
def __call__(self, parser, namespace, values, option_string=None): | ||
raise NotImplementedError('__call__ not defined') | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
|
||
class AppendAction(Action): | ||
"""Action that appends | ||
""" | ||
|
||
def __init__(self, option_strings, join=None, **kwargs): | ||
|
||
kwargs['nargs'] = Nargs.SINGLE | ||
kwargs.setdefault('default', []) | ||
|
||
super(AppendAction, self).__init__( | ||
option_strings=option_strings, | ||
**kwargs) | ||
|
||
def __call__(self, parser, namespace, values, option_string=None): | ||
if isinstance(values, str): | ||
values = [values] | ||
|
||
for dest in self.dests: | ||
if getattr(namespace, dest) is None: | ||
setattr(namespace, dest, []) | ||
|
||
items = copy.copy(getattr(namespace, dest)) | ||
items += values | ||
|
||
setattr(namespace, dest, items) | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
|
||
class CustomCallAction(Action): | ||
"""Action that allows for instances to implement custom call functionality. | ||
The call_func must follow the same calling convention as implementing the | ||
__call__ method for an Action. | ||
""" | ||
|
||
def __init__(self, option_strings, call_func, **kwargs): | ||
|
||
if not callable(call_func): | ||
raise TypeError('call_func must be callable') | ||
|
||
super(CustomCallAction, self).__init__( | ||
option_strings=option_strings, | ||
**kwargs) | ||
|
||
self.call_func = call_func | ||
|
||
def __call__(self, parser, namespace, values, option_string=None): | ||
self.call_func(self, parser, namespace, values, option_string) | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
|
||
class StoreAction(Action): | ||
"""Action that stores a string. | ||
""" | ||
|
||
def __init__(self, option_strings, **kwargs): | ||
|
||
if 'choices' in kwargs: | ||
kwargs['nargs'] = Nargs.OPTIONAL | ||
if 'const' in kwargs: | ||
kwargs['nargs'] = Nargs.ZERO | ||
|
||
super(StoreAction, self).__init__( | ||
option_strings=option_strings, | ||
**kwargs) | ||
|
||
def __call__(self, parser, namespace, values, option_string=None): | ||
for dest in self.dests: | ||
if self.nargs == Nargs.ZERO and self.const is not None: | ||
values = self.const | ||
|
||
setattr(namespace, dest, values) | ||
|
||
|
||
class StoreIntAction(StoreAction): | ||
"""Action that stores an int. | ||
""" | ||
|
||
def __init__(self, option_strings, **kwargs): | ||
kwargs['nargs'] = Nargs.SINGLE | ||
kwargs['type'] = int | ||
kwargs.setdefault('metavar', 'N') | ||
|
||
super(StoreAction, self).__init__( | ||
option_strings=option_strings, | ||
**kwargs) | ||
|
||
|
||
class StoreTrueAction(StoreAction): | ||
"""Action that stores True when called and False by default. | ||
""" | ||
|
||
def __init__(self, option_strings, **kwargs): | ||
kwargs['nargs'] = Nargs.ZERO | ||
kwargs['const'] = True | ||
kwargs['default'] = False | ||
|
||
super(StoreTrueAction, self).__init__( | ||
option_strings=option_strings, | ||
**kwargs) | ||
|
||
|
||
class StoreFalseAction(StoreAction): | ||
"""Action that stores False when called and True by default. | ||
""" | ||
|
||
def __init__(self, option_strings, **kwargs): | ||
kwargs['nargs'] = Nargs.ZERO | ||
kwargs['const'] = False | ||
kwargs['default'] = True | ||
|
||
super(StoreFalseAction, self).__init__( | ||
option_strings=option_strings, | ||
**kwargs) | ||
|
||
|
||
class StorePathAction(StoreAction): | ||
"""Action that stores a path, which it will attempt to expand. | ||
""" | ||
|
||
def __init__(self, option_strings, **kwargs): | ||
kwargs['nargs'] = Nargs.SINGLE | ||
kwargs['type'] = PathType() | ||
|
||
super(StorePathAction, self).__init__( | ||
option_strings=option_strings, | ||
**kwargs) | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
|
||
class _ToggleAction(Action): | ||
"""Action that can be toggled on or off, either implicitly when called or | ||
explicitly when an optional boolean value is parsed. | ||
""" | ||
|
||
def __init__(self, option_strings, on_value, off_value, **kwargs): | ||
kwargs['nargs'] = Nargs.OPTIONAL | ||
kwargs['type'] = BoolType() | ||
kwargs.setdefault('default', off_value) | ||
kwargs.setdefault('metavar', 'BOOL') | ||
|
||
super(_ToggleAction, self).__init__( | ||
option_strings=option_strings, | ||
**kwargs) | ||
|
||
self.on_value = on_value | ||
self.off_value = off_value | ||
|
||
def __call__(self, parser, namespace, values, option_string=None): | ||
if values is None: | ||
values = self.on_value | ||
elif values is True: | ||
values = self.on_value | ||
elif values is False: | ||
values = self.off_value | ||
else: | ||
raise argparse.ArgumentTypeError( | ||
'{} is not a boolean value'.format(values)) | ||
|
||
for dest in self.dests: | ||
setattr(namespace, dest, values) | ||
|
||
|
||
class ToggleTrueAction(_ToggleAction): | ||
"""Action that toggles True when called or False otherwise, with the | ||
option to explicitly override the value. | ||
""" | ||
|
||
def __init__(self, option_strings, **kwargs): | ||
|
||
super(ToggleTrueAction, self).__init__( | ||
option_strings=option_strings, | ||
on_value=True, | ||
off_value=False, | ||
**kwargs) | ||
|
||
|
||
class ToggleFalseAction(_ToggleAction): | ||
"""Action that toggles False when called or True otherwise, with the | ||
option to explicitly override the value. | ||
""" | ||
|
||
def __init__(self, option_strings, **kwargs): | ||
|
||
super(ToggleFalseAction, self).__init__( | ||
option_strings=option_strings, | ||
on_value=False, | ||
off_value=True, | ||
**kwargs) | ||
|
||
|
||
# ----------------------------------------------------------------------------- | ||
|
||
class UnsupportedAction(Action): | ||
"""Action that denotes an unsupported argument or opiton and subsequently | ||
raises an ArgumentError. | ||
""" | ||
|
||
def __init__(self, option_strings, message=None, **kwargs): | ||
kwargs['nargs'] = Nargs.ZERO | ||
kwargs['default'] = argparse.SUPPRESS | ||
|
||
super(UnsupportedAction, self).__init__( | ||
option_strings=option_strings, | ||
dests=argparse.SUPPRESS, | ||
**kwargs) | ||
|
||
self.message = message | ||
|
||
def __call__(self, parser, namespace, values, option_string=None): | ||
if self.message is not None: | ||
parser.error(self.message) | ||
|
||
arg = option_string or str(values) | ||
parser.error('unsupported argument: {}'.format(arg)) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a docstring explaining what this module is intended to do so it is used appropriately in the future :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No problem, I'll add those in a bit.