Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions snaparg/snaparg.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

class SnapArgumentParser(argparse.ArgumentParser):
def __init__(self, *args, **kwargs):
"""
Initializes the SnapArgumentParser with enhanced defaults.

Sets a custom help formatter with increased help position width and, for Python 3.12+, enables exit on error by default.
"""
if sys.version_info > (3, 11):
kwargs.setdefault("exit_on_error", True)
kwargs.setdefault(
Expand All @@ -24,6 +29,11 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def add_argument(self, *args, **kwargs):
"""
Adds a command-line argument, with enhanced support for enum types.

If the argument type is an enum.Enum subclass, sets the metavar to display valid enum member names and ensures input values are parsed as enum members, raising an error for invalid values.
"""
arg_type = kwargs.get("type")
if isinstance(arg_type, type) and issubclass(arg_type, enum.Enum):
kwargs.setdefault("metavar", "[" + "|".join(e.name for e in arg_type) + "]")
Expand All @@ -41,10 +51,25 @@ def parse_enum(s):
return super().add_argument(*args, **kwargs)

def get_registered_actions(self):
"""
Returns a list of argument actions that have associated option strings.

Only actions representing options (i.e., those with flags like '--foo') are included.
"""
return [a for a in self._actions if a.option_strings]


def _autofix_arguments(self, suggestions, raw_args):
"""
Replaces mistyped arguments in the input list with their suggested corrections.

Args:
suggestions: A list of (wrong, right) argument string pairs indicating corrections.
raw_args: The original list of command-line argument strings.

Returns:
A new list of arguments with mistyped entries replaced by their suggested corrections.
"""
fixed_args = []
for arg in raw_args:
for wrong, right in suggestions:
Expand All @@ -56,6 +81,11 @@ def _autofix_arguments(self, suggestions, raw_args):
return fixed_args

def parse_args(self, args=None, namespace=None):
"""
Parses command-line arguments and checks for missing required options.

If any required option arguments are missing after parsing, raises an error listing them.
"""
parsed_args = super().parse_args(args, namespace)
# Check for missing required arguments
missing = []
Expand All @@ -69,6 +99,11 @@ def parse_args(self, args=None, namespace=None):
return parsed_args

def error(self, message):
"""
Handles command-line parsing errors with enhanced, colorized messages and suggestions.

If a required argument value is missing, displays the expected type and usage tips. For mistyped flags, suggests corrections or automatically fixes them if '--autofix' is present, then exits the program.
"""
valid_options = []
for action in self.get_registered_actions():
if action.option_strings:
Expand Down
4 changes: 2 additions & 2 deletions snaparg/snaparg_interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

def interactive_parse(parser: SnapArgumentParser):
"""
Parses command-line arguments, interactively prompting for missing required arguments.
Parses command-line arguments, interactively prompting for any missing required values.

If required arguments are missing, prompts the user to enter values for them, validates the input, and then returns the fully parsed arguments.
If required arguments are missing from the command line, prompts the user to input them, validates and converts the input as needed, and returns the parsed arguments.
"""
try:
return parser.parse_args()
Expand Down