Skip to content

Commit

Permalink
Upgrade stdlib modules from CPython 3.11
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreQuentel committed Jun 19, 2023
1 parent 3144158 commit a153e95
Show file tree
Hide file tree
Showing 24 changed files with 4,162 additions and 1,246 deletions.
94 changes: 69 additions & 25 deletions www/src/Lib/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@
import re as _re
import sys as _sys

import warnings

from gettext import gettext as _, ngettext

SUPPRESS = '==SUPPRESS=='
Expand Down Expand Up @@ -151,6 +153,7 @@ def _copy_items(items):
# Formatting Help
# ===============


class HelpFormatter(object):
"""Formatter for generating usage messages and argument help strings.
Expand Down Expand Up @@ -392,6 +395,9 @@ def _format_actions_usage(self, actions, groups):
group_actions = set()
inserts = {}
for group in groups:
if not group._group_actions:
raise ValueError(f'empty group {group}')

try:
start = actions.index(group._group_actions[0])
except ValueError:
Expand Down Expand Up @@ -526,12 +532,13 @@ def _format_action(self, action):
parts = [action_header]

# if there was help for the action, add lines of help text
if action.help:
if action.help and action.help.strip():
help_text = self._expand_help(action)
help_lines = self._split_lines(help_text, help_width)
parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
for line in help_lines[1:]:
parts.append('%*s%s\n' % (help_position, '', line))
if help_text:
help_lines = self._split_lines(help_text, help_width)
parts.append('%*s%s\n' % (indent_first, '', help_lines[0]))
for line in help_lines[1:]:
parts.append('%*s%s\n' % (help_position, '', line))

# or add a newline if the description doesn't end with one
elif not action_header.endswith('\n'):
Expand Down Expand Up @@ -689,15 +696,27 @@ class ArgumentDefaultsHelpFormatter(HelpFormatter):
"""

def _get_help_string(self, action):
"""
Add the default value to the option help message.
ArgumentDefaultsHelpFormatter and BooleanOptionalAction when it isn't
already present. This code will do that, detecting cornercases to
prevent duplicates or cases where it wouldn't make sense to the end
user.
"""
help = action.help
if '%(default)' not in action.help:
if help is None:
help = ''

if '%(default)' not in help:
if action.default is not SUPPRESS:
defaulting_nargs = [OPTIONAL, ZERO_OR_MORE]
if action.option_strings or action.nargs in defaulting_nargs:
help += ' (default: %(default)s)'
return help



class MetavarTypeHelpFormatter(HelpFormatter):
"""Help message formatter which uses the argument 'type' as the default
metavar value (instead of the argument 'dest')
Expand All @@ -713,7 +732,6 @@ def _get_default_metavar_for_positional(self, action):
return action.type.__name__



# =====================
# Options and Arguments
# =====================
Expand All @@ -722,7 +740,7 @@ def _get_action_name(argument):
if argument is None:
return None
elif argument.option_strings:
return '/'.join(argument.option_strings)
return '/'.join(argument.option_strings)
elif argument.metavar not in (None, SUPPRESS):
return argument.metavar
elif argument.dest not in (None, SUPPRESS):
Expand All @@ -748,7 +766,7 @@ def __str__(self):
if self.argument_name is None:
format = '%(message)s'
else:
format = 'argument %(argument_name)s: %(message)s'
format = _('argument %(argument_name)s: %(message)s')
return format % dict(message=self.message,
argument_name=self.argument_name)

Expand Down Expand Up @@ -844,6 +862,7 @@ def _get_kwargs(self):
'default',
'type',
'choices',
'required',
'help',
'metavar',
]
Expand All @@ -855,6 +874,7 @@ def format_usage(self):
def __call__(self, parser, namespace, values, option_string=None):
raise NotImplementedError(_('.__call__() not defined'))


class BooleanOptionalAction(Action):
def __init__(self,
option_strings,
Expand All @@ -874,9 +894,6 @@ def __init__(self,
option_string = '--no-' + option_string[2:]
_option_strings.append(option_string)

if help is not None and default is not None:
help += f" (default: {default})"

super().__init__(
option_strings=_option_strings,
dest=dest,
Expand All @@ -888,6 +905,7 @@ def __init__(self,
help=help,
metavar=metavar)


def __call__(self, parser, namespace, values, option_string=None):
if option_string in self.option_strings:
setattr(namespace, self.dest, not option_string.startswith('--no-'))
Expand Down Expand Up @@ -936,7 +954,7 @@ class _StoreConstAction(Action):
def __init__(self,
option_strings,
dest,
const,
const=None,
default=None,
required=False,
help=None,
Expand Down Expand Up @@ -1031,7 +1049,7 @@ class _AppendConstAction(Action):
def __init__(self,
option_strings,
dest,
const,
const=None,
default=None,
required=False,
help=None,
Expand Down Expand Up @@ -1163,6 +1181,13 @@ def add_parser(self, name, **kwargs):

aliases = kwargs.pop('aliases', ())

if name in self._name_parser_map:
raise ArgumentError(self, _('conflicting subparser: %s') % name)
for alias in aliases:
if alias in self._name_parser_map:
raise ArgumentError(
self, _('conflicting subparser alias: %s') % alias)

# create a pseudo-action to hold the choice help
if 'help' in kwargs:
help = kwargs.pop('help')
Expand Down Expand Up @@ -1252,9 +1277,9 @@ def __call__(self, string):
# the special argument "-" means sys.std{in,out}
if string == '-':
if 'r' in self._mode:
return _sys.stdin
elif 'w' in self._mode:
return _sys.stdout
return _sys.stdin.buffer if 'b' in self._mode else _sys.stdin
elif any(c in self._mode for c in 'wax'):
return _sys.stdout.buffer if 'b' in self._mode else _sys.stdout
else:
msg = _('argument "-" with mode %r') % self._mode
raise ValueError(msg)
Expand Down Expand Up @@ -1643,6 +1668,14 @@ def _remove_action(self, action):
super(_ArgumentGroup, self)._remove_action(action)
self._group_actions.remove(action)

def add_argument_group(self, *args, **kwargs):
warnings.warn(
"Nesting argument groups is deprecated.",
category=DeprecationWarning,
stacklevel=2
)
return super().add_argument_group(*args, **kwargs)


class _MutuallyExclusiveGroup(_ArgumentGroup):

Expand All @@ -1663,12 +1696,21 @@ def _remove_action(self, action):
self._container._remove_action(action)
self._group_actions.remove(action)

def add_mutually_exclusive_group(self, *args, **kwargs):
warnings.warn(
"Nesting mutually exclusive groups is deprecated.",
category=DeprecationWarning,
stacklevel=2
)
return super().add_mutually_exclusive_group(*args, **kwargs)


class ArgumentParser(_AttributeHolder, _ActionsContainer):
"""Object for parsing command line strings into Python objects.
Keyword Arguments:
- prog -- The name of the program (default: sys.argv[0])
- prog -- The name of the program (default:
``os.path.basename(sys.argv[0])``)
- usage -- A usage message (default: auto-generated from arguments)
- description -- A description of what the program does
- epilog -- Text following the argument descriptions
Expand Down Expand Up @@ -1851,8 +1893,7 @@ def parse_known_args(self, args=None, namespace=None):
if self.exit_on_error:
try:
namespace, args = self._parse_known_args(args, namespace)
except ArgumentError:
err = _sys.exc_info()[1]
except ArgumentError as err:
self.error(str(err))
else:
namespace, args = self._parse_known_args(args, namespace)
Expand Down Expand Up @@ -1956,7 +1997,11 @@ def consume_optional(start_index):
# arguments, try to parse more single-dash options out
# of the tail of the option string
chars = self.prefix_chars
if arg_count == 0 and option_string[1] not in chars:
if (
arg_count == 0
and option_string[1] not in chars
and explicit_arg != ''
):
action_tuples.append((action, [], option_string))
char = option_string[0]
option_string = char + explicit_arg[0]
Expand Down Expand Up @@ -2127,8 +2172,7 @@ def _read_args_from_files(self, arg_strings):
arg_strings.append(arg)
arg_strings = self._read_args_from_files(arg_strings)
new_arg_strings.extend(arg_strings)
except OSError:
err = _sys.exc_info()[1]
except OSError as err:
self.error(str(err))

# return the modified argument list
Expand Down Expand Up @@ -2478,9 +2522,9 @@ def _get_value(self, action, arg_string):
result = type_func(arg_string)

# ArgumentTypeErrors indicate errors
except ArgumentTypeError:
except ArgumentTypeError as err:
name = getattr(action.type, '__name__', repr(action.type))
msg = str(_sys.exc_info()[1])
msg = str(err)
raise ArgumentError(action, msg)

# TypeErrors or ValueErrors also indicate errors
Expand Down
10 changes: 9 additions & 1 deletion www/src/Lib/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ def parse(source, filename='<unknown>', mode='exec', *,

def literal_eval(node_or_string):
"""
Safely evaluate an expression node or a string containing a Python
Evaluate an expression node or a string containing only a Python
expression. The string or node provided may only consist of the following
Python literal structures: strings, bytes, numbers, tuples, lists, dicts,
sets, booleans, and None.
Caution: A complex expression can overflow the C stack and cause a crash.
"""
if isinstance(node_or_string, str):
node_or_string = parse(node_or_string.lstrip(" \t"), mode='eval')
Expand Down Expand Up @@ -234,6 +236,12 @@ def increment_lineno(node, n=1):
location in a file.
"""
for child in walk(node):
# TypeIgnore is a special case where lineno is not an attribute
# but rather a field of the node itself.
if isinstance(child, TypeIgnore):
child.lineno = getattr(child, 'lineno', 0) + n
continue

if 'lineno' in child._attributes:
child.lineno = getattr(child, 'lineno', 0) + n
if (
Expand Down
2 changes: 0 additions & 2 deletions www/src/Lib/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,5 +399,3 @@ def columnize(self, list, displaywidth=80):
for col in range(len(texts)):
texts[col] = texts[col].ljust(colwidths[col])
self.stdout.write("%s\n"%str(" ".join(texts)))


3 changes: 2 additions & 1 deletion www/src/Lib/codecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,8 @@ def open(filename, mode='r', encoding=None, errors='strict', buffering=-1):
codecs. Output is also codec dependent and will usually be
Unicode as well.
Underlying encoded files are always opened in binary mode.
If encoding is not None, then the
underlying encoded files are always opened in binary mode.
The default file mode is 'r', meaning to open the file in read mode.
encoding specifies the encoding which is to be used for the
Expand Down
26 changes: 13 additions & 13 deletions www/src/Lib/codeop.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,22 @@ def _maybe_compile(compiler, source, filename, symbol):
if symbol != "eval":
source = "pass" # Replace it with a 'pass' statement

try:
return compiler(source, filename, symbol)
except SyntaxError: # Let other compile() errors propagate.
pass

# Catch syntax warnings after the first compile
# to emit warnings (SyntaxWarning, DeprecationWarning) at most once.
# Disable compiler warnings when checking for incomplete input.
with warnings.catch_warnings():
warnings.simplefilter("error")

warnings.simplefilter("ignore", (SyntaxWarning, DeprecationWarning))
try:
compiler(source + "\n", filename, symbol)
except SyntaxError as e:
if "incomplete input" in str(e):
compiler(source, filename, symbol)
except SyntaxError: # Let other compile() errors propagate.
try:
compiler(source + "\n", filename, symbol)
return None
raise
except SyntaxError as e:
if "incomplete input" in str(e):
return None
# fallthrough

return compiler(source, filename, symbol)


def _is_syntax_error(err1, err2):
rep1 = repr(err1)
Expand Down
Loading

0 comments on commit a153e95

Please sign in to comment.