Skip to content

Commit 130bb8b

Browse files
Added more features to the ArgumentParser and fixed issues with Argumentify.
+ Added `Sequence[T]` as a supported type to the ColorizingArgumentParser. + Bug fixes.
1 parent 596845e commit 130bb8b

6 files changed

Lines changed: 56 additions & 35 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ Help this project by [Donation](DONATE.md)
66
Changes
77
-------
88

9+
### 2.9.2
10+
11+
+ Added `Sequence[T]` as a supported type to the ColorizingArgumentParser.
12+
+ Bug fixes.
13+
914
### 2.9.1
1015

1116
+ Update `README.md`.

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ pip install git+https://github.com/MPCodeWriter21/log21
6161
Changes
6262
-------
6363

64-
### 2.9.1
64+
### 2.9.2
6565

66-
+ Update `README.md`.
66+
+ Added `Sequence[T]` as a supported type to the ColorizingArgumentParser.
67+
+ Bug fixes.
6768

6869
[Full CHANGELOG](https://github.com/MPCodeWriter21/log21/blob/master/CHANGELOG.md)
6970

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ dependencies = [
2626
"webcolors",
2727
"docstring-parser"
2828
]
29-
version = "2.9.1"
29+
version = "2.9.2"
3030

3131
[tool.setuptools.packages.find]
3232
where = ["src"]

src/log21/Argparse.py

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
import types as _types
99
import typing as _typing
1010
import argparse as _argparse
11+
import collections.abc
1112
from enum import Enum as _Enum
12-
from typing import (Tuple as _Tuple, Mapping as _Mapping, Optional as _Optional,
13-
Sequence as _Sequence)
13+
from typing import (Tuple as _Tuple, Mapping as _Mapping, NoReturn,
14+
Optional as _Optional, Sequence as _Sequence)
1415
from gettext import gettext as _gettext
1516
from textwrap import TextWrapper as _TextWrapper
1617
from collections import OrderedDict as _OrderedDict
@@ -78,7 +79,7 @@ def __init__(
7879
if key in self.colors:
7980
self.colors[key] = value
8081

81-
class _Section(object):
82+
class _Section:
8283

8384
def __init__(self, formatter, parent, heading=None):
8485
self.formatter = formatter
@@ -561,36 +562,43 @@ def _validate_func_type(self, action, func_type, kwargs, level: int = 0) -> _Tup
561562
and isinstance(func_type, _typing._LiteralGenericAlias)): # type: ignore
562563
func_type = Literal(func_type)
563564

565+
# Handle `Union` and `Optional` as a type (e.g. `Union[int, str]` and
566+
# `Optional[int]`)
567+
elif (hasattr(_typing, '_UnionGenericAlias')
568+
and isinstance(func_type, _typing._UnionGenericAlias)): # type: ignore
569+
# Optional[T] is just Union[T, NoneType]
570+
# Optional
571+
if (hasattr(_types, 'NoneType') and len(func_type.__args__) == 2
572+
and func_type.__args__[1] is _types.NoneType):
573+
action.required = False
574+
func_type = func_type.__args__[0]
575+
# Union
576+
else:
577+
func_type = func_type.__args__ # type: ignore
578+
564579
# Handle `List` as a type (e.g. `List[int]`)
565580
elif (hasattr(_typing, '_GenericAlias')
566581
and isinstance(func_type, _typing._GenericAlias) # type: ignore
567-
and func_type.__origin__ is list):
582+
and getattr(func_type, '__origin__') is list):
583+
func_type = func_type.__args__[0]
584+
if kwargs.get('nargs') is None:
585+
action.nargs = '+'
586+
587+
# Handle `Sequence` as a type (e.g. `Sequence[int]`)
588+
elif (hasattr(_typing, '_GenericAlias')
589+
and isinstance(func_type, _typing._GenericAlias) # type: ignore
590+
and getattr(func_type, '__origin__') is collections.abc.Sequence):
568591
func_type = func_type.__args__[0]
569592
if kwargs.get('nargs') is None:
570593
action.nargs = '+'
571594

572595
# Handle `Required` as a type (e.g. `Required[int]`)
573596
elif (hasattr(_typing, 'Required') and hasattr(_typing, '_GenericAlias')
574597
and isinstance(func_type, _typing._GenericAlias) # type: ignore
575-
and func_type.__origin__ is _typing.Required
576-
):
598+
and getattr(func_type, '__origin__') is _typing.Required):
577599
func_type = func_type.__args__[0]
578600
action.required = True
579601

580-
# Handle `Union` and `Optional` as a type (e.g. `Union[int, str]` and
581-
# `Optional[int]`)
582-
elif (hasattr(_types, 'NoneType') and hasattr(_typing, '_UnionGenericAlias')
583-
and isinstance(func_type, _typing._UnionGenericAlias)): # type: ignore
584-
# Optional[T] is just Union[T, NoneType]
585-
# Optional
586-
if (len(func_type.__args__) == 2
587-
and func_type.__args__[1] is _types.NoneType):
588-
action.required = False
589-
func_type = func_type.__args__[0]
590-
# Union
591-
else:
592-
func_type = func_type.__args__ # type: ignore
593-
594602
# Handle Enum as a type
595603
elif callable(func_type) and isinstance(func_type, type) and issubclass(
596604
func_type, _Enum) and action.choices is None and level == 0:
@@ -747,16 +755,15 @@ def error(self, message):
747755
f'%(prog)s: {_gc("r")}error{_gc("lr")}:{_gc("rst")} %(message)s\n'
748756
) % args
749757
)
758+
return NoReturn
750759

751760
def _get_formatter(self):
752761
if hasattr(self.formatter_class, 'colors'):
753762
return self.formatter_class(prog=self.prog, colors=self.colors)
754-
else:
755-
return self.formatter_class(prog=self.prog)
763+
return self.formatter_class(prog=self.prog)
756764

757765
def _get_value(self, action, arg_string):
758-
"""Override _get_value to add support for types such as Union and
759-
Literal."""
766+
"""Override _get_value to add support for types such as Union and Literal."""
760767

761768
func_type = self._registry_get('type', action.type, action.type)
762769
if not callable(func_type) and not isinstance(func_type, tuple):
@@ -842,13 +849,14 @@ def _read_args_from_files(self, arg_strings):
842849
for arg_string in arg_strings:
843850

844851
# for regular arguments, just add them back into the list
845-
if not arg_string or arg_string[0] not in self.fromfile_prefix_chars:
852+
if not arg_string or arg_string[0] not in (self.fromfile_prefix_chars
853+
or ''):
846854
new_arg_strings.append(arg_string)
847855

848856
# replace arguments referencing files with the file content
849857
else:
850858
try:
851-
with open(arg_string[1:]) as args_file:
859+
with open(arg_string[1:], encoding='utf-8') as args_file:
852860
arg_strings = []
853861
for arg_line in args_file.read().splitlines():
854862
for arg in self.convert_arg_line_to_args(arg_line):
@@ -1110,7 +1118,11 @@ def consume_positionals(start_index):
11101118
if action.help is not _argparse.SUPPRESS
11111119
]
11121120
self.error(
1113-
_gettext(f'one of the arguments {" ".join(names)} is required')
1121+
_gettext(
1122+
'one of the arguments ' +
1123+
' '.join(name for name in names if name is not None) +
1124+
' is required'
1125+
)
11141126
)
11151127

11161128
for group in self._action_groups:
@@ -1127,7 +1139,11 @@ def consume_positionals(start_index):
11271139
if action.help is not _argparse.SUPPRESS
11281140
]
11291141
self.error(
1130-
_gettext(f'one of the arguments {" ".join(names)} is required')
1142+
_gettext(
1143+
'one of the arguments ' +
1144+
' '.join(name for name in names if name is not None) +
1145+
' is required'
1146+
)
11311147
)
11321148

11331149
# return the updated namespace and the extra arguments

src/log21/Argumentify.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,10 @@ def _add_arguments(
262262
'dest': argument.name,
263263
'help': argument.help
264264
}
265-
if isinstance(argument.annotation, type):
266-
config['type'] = argument.annotation
267265
if argument.annotation == bool:
268266
config['action'] = 'store_true'
269-
config.pop('type')
267+
elif argument.annotation:
268+
config['type'] = argument.annotation
270269
if argument.kind == _inspect._ParameterKind.POSITIONAL_ONLY:
271270
config['required'] = True
272271
if argument.kind == _inspect._ParameterKind.VAR_POSITIONAL:

src/log21/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from .StreamHandler import StreamHandler, ColorizingStreamHandler
2424

2525
__author__ = 'CodeWriter21 (Mehrad Pooryoussof)'
26-
__version__ = '2.9.1'
26+
__version__ = '2.9.2'
2727
__github__ = 'Https://GitHub.com/MPCodeWriter21/log21'
2828
__all__ = [
2929
'ColorizingStreamHandler', 'DecolorizingFileHandler', 'ColorizingFormatter',

0 commit comments

Comments
 (0)