diff options
| author | shadchin <[email protected]> | 2022-02-10 16:44:30 +0300 | 
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:44:30 +0300 | 
| commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
| tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/python/pytest/py3/_pytest/config/argparsing.py | |
| parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/config/argparsing.py')
| -rw-r--r-- | contrib/python/pytest/py3/_pytest/config/argparsing.py | 528 | 
1 files changed, 264 insertions, 264 deletions
diff --git a/contrib/python/pytest/py3/_pytest/config/argparsing.py b/contrib/python/pytest/py3/_pytest/config/argparsing.py index 9a481965526..24188312492 100644 --- a/contrib/python/pytest/py3/_pytest/config/argparsing.py +++ b/contrib/python/pytest/py3/_pytest/config/argparsing.py @@ -1,72 +1,72 @@  import argparse -import sys +import sys   import warnings -from gettext import gettext -from typing import Any -from typing import Callable -from typing import cast -from typing import Dict -from typing import List -from typing import Mapping -from typing import Optional -from typing import Sequence -from typing import Tuple -from typing import TYPE_CHECKING -from typing import Union +from gettext import gettext  +from typing import Any  +from typing import Callable  +from typing import cast  +from typing import Dict  +from typing import List  +from typing import Mapping  +from typing import Optional  +from typing import Sequence  +from typing import Tuple  +from typing import TYPE_CHECKING  +from typing import Union   import py -import _pytest._io -from _pytest.compat import final -from _pytest.config.exceptions import UsageError - -if TYPE_CHECKING: -    from typing import NoReturn -    from typing_extensions import Literal +import _pytest._io  +from _pytest.compat import final  +from _pytest.config.exceptions import UsageError  +if TYPE_CHECKING:  +    from typing import NoReturn  +    from typing_extensions import Literal  +   FILE_OR_DIR = "file_or_dir" -@final -class Parser: -    """Parser for command line arguments and ini-file values. +@final  +class Parser:  +    """Parser for command line arguments and ini-file values.  -    :ivar extra_info: Dict of generic param -> value to display in case +    :ivar extra_info: Dict of generic param -> value to display in case           there's an error processing the command line arguments.      """ -    prog: Optional[str] = None - -    def __init__( -        self, -        usage: Optional[str] = None, -        processopt: Optional[Callable[["Argument"], None]] = None, -    ) -> None: +    prog: Optional[str] = None  +  +    def __init__(  +        self,  +        usage: Optional[str] = None,  +        processopt: Optional[Callable[["Argument"], None]] = None,  +    ) -> None:           self._anonymous = OptionGroup("custom options", parser=self) -        self._groups: List[OptionGroup] = [] +        self._groups: List[OptionGroup] = []           self._processopt = processopt          self._usage = usage -        self._inidict: Dict[str, Tuple[str, Optional[str], Any]] = {} -        self._ininames: List[str] = [] -        self.extra_info: Dict[str, Any] = {} +        self._inidict: Dict[str, Tuple[str, Optional[str], Any]] = {}  +        self._ininames: List[str] = []  +        self.extra_info: Dict[str, Any] = {}  -    def processoption(self, option: "Argument") -> None: +    def processoption(self, option: "Argument") -> None:           if self._processopt:              if option.dest:                  self._processopt(option) -    def getgroup( -        self, name: str, description: str = "", after: Optional[str] = None -    ) -> "OptionGroup": -        """Get (or create) a named option Group. +    def getgroup(  +        self, name: str, description: str = "", after: Optional[str] = None  +    ) -> "OptionGroup":  +        """Get (or create) a named option Group.  -        :name: Name of the option group. -        :description: Long description for --help output. -        :after: Name of another group, used for ordering --help output. +        :name: Name of the option group.  +        :description: Long description for --help output.  +        :after: Name of another group, used for ordering --help output.           The returned group object has an ``addoption`` method with the same          signature as :py:func:`parser.addoption -        <_pytest.config.argparsing.Parser.addoption>` but will be shown in the +        <_pytest.config.argparsing.Parser.addoption>` but will be shown in the           respective group in the output of ``pytest. --help``.          """          for group in self._groups: @@ -80,37 +80,37 @@ class Parser:          self._groups.insert(i + 1, group)          return group -    def addoption(self, *opts: str, **attrs: Any) -> None: -        """Register a command line option. +    def addoption(self, *opts: str, **attrs: Any) -> None:  +        """Register a command line option.  -        :opts: Option names, can be short or long options. -        :attrs: Same attributes which the ``add_argument()`` function of the -           `argparse library <https://docs.python.org/library/argparse.html>`_ +        :opts: Option names, can be short or long options.  +        :attrs: Same attributes which the ``add_argument()`` function of the  +           `argparse library <https://docs.python.org/library/argparse.html>`_              accepts. -        After command line parsing, options are available on the pytest config +        After command line parsing, options are available on the pytest config           object via ``config.option.NAME`` where ``NAME`` is usually set          by passing a ``dest`` attribute, for example          ``addoption("--long", dest="NAME", ...)``.          """          self._anonymous.addoption(*opts, **attrs) -    def parse( -        self, -        args: Sequence[Union[str, py.path.local]], -        namespace: Optional[argparse.Namespace] = None, -    ) -> argparse.Namespace: +    def parse(  +        self,  +        args: Sequence[Union[str, py.path.local]],  +        namespace: Optional[argparse.Namespace] = None,  +    ) -> argparse.Namespace:           from _pytest._argcomplete import try_argcomplete          self.optparser = self._getparser()          try_argcomplete(self.optparser) -        strargs = [str(x) if isinstance(x, py.path.local) else x for x in args] -        return self.optparser.parse_args(strargs, namespace=namespace) +        strargs = [str(x) if isinstance(x, py.path.local) else x for x in args]  +        return self.optparser.parse_args(strargs, namespace=namespace)  -    def _getparser(self) -> "MyOptionParser": +    def _getparser(self) -> "MyOptionParser":           from _pytest._argcomplete import filescompleter -        optparser = MyOptionParser(self, self.extra_info, prog=self.prog) +        optparser = MyOptionParser(self, self.extra_info, prog=self.prog)           groups = self._groups + [self._anonymous]          for group in groups:              if group.options: @@ -120,98 +120,98 @@ class Parser:                      n = option.names()                      a = option.attrs()                      arggroup.add_argument(*n, **a) -        file_or_dir_arg = optparser.add_argument(FILE_OR_DIR, nargs="*") +        file_or_dir_arg = optparser.add_argument(FILE_OR_DIR, nargs="*")           # bash like autocompletion for dirs (appending '/') -        # Type ignored because typeshed doesn't know about argcomplete. -        file_or_dir_arg.completer = filescompleter  # type: ignore +        # Type ignored because typeshed doesn't know about argcomplete.  +        file_or_dir_arg.completer = filescompleter  # type: ignore           return optparser -    def parse_setoption( -        self, -        args: Sequence[Union[str, py.path.local]], -        option: argparse.Namespace, -        namespace: Optional[argparse.Namespace] = None, -    ) -> List[str]: +    def parse_setoption(  +        self,  +        args: Sequence[Union[str, py.path.local]],  +        option: argparse.Namespace,  +        namespace: Optional[argparse.Namespace] = None,  +    ) -> List[str]:           parsedoption = self.parse(args, namespace=namespace)          for name, value in parsedoption.__dict__.items():              setattr(option, name, value) -        return cast(List[str], getattr(parsedoption, FILE_OR_DIR)) - -    def parse_known_args( -        self, -        args: Sequence[Union[str, py.path.local]], -        namespace: Optional[argparse.Namespace] = None, -    ) -> argparse.Namespace: -        """Parse and return a namespace object with known arguments at this point.""" +        return cast(List[str], getattr(parsedoption, FILE_OR_DIR))  + +    def parse_known_args(  +        self,  +        args: Sequence[Union[str, py.path.local]],  +        namespace: Optional[argparse.Namespace] = None,  +    ) -> argparse.Namespace:  +        """Parse and return a namespace object with known arguments at this point."""           return self.parse_known_and_unknown_args(args, namespace=namespace)[0] -    def parse_known_and_unknown_args( -        self, -        args: Sequence[Union[str, py.path.local]], -        namespace: Optional[argparse.Namespace] = None, -    ) -> Tuple[argparse.Namespace, List[str]]: -        """Parse and return a namespace object with known arguments, and -        the remaining arguments unknown at this point.""" +    def parse_known_and_unknown_args(  +        self,  +        args: Sequence[Union[str, py.path.local]],  +        namespace: Optional[argparse.Namespace] = None,  +    ) -> Tuple[argparse.Namespace, List[str]]:  +        """Parse and return a namespace object with known arguments, and  +        the remaining arguments unknown at this point."""           optparser = self._getparser() -        strargs = [str(x) if isinstance(x, py.path.local) else x for x in args] -        return optparser.parse_known_args(strargs, namespace=namespace) - -    def addini( -        self, -        name: str, -        help: str, -        type: Optional[ -            "Literal['string', 'pathlist', 'args', 'linelist', 'bool']" -        ] = None, -        default=None, -    ) -> None: -        """Register an ini-file option. - -        :name: Name of the ini-variable. -        :type: Type of the variable, can be ``string``, ``pathlist``, ``args``, -               ``linelist`` or ``bool``.  Defaults to ``string`` if ``None`` or -               not passed. -        :default: Default value if no ini-file option exists but is queried. +        strargs = [str(x) if isinstance(x, py.path.local) else x for x in args]  +        return optparser.parse_known_args(strargs, namespace=namespace)  + +    def addini(  +        self,  +        name: str,  +        help: str,  +        type: Optional[  +            "Literal['string', 'pathlist', 'args', 'linelist', 'bool']"  +        ] = None,  +        default=None,  +    ) -> None:  +        """Register an ini-file option.  + +        :name: Name of the ini-variable.  +        :type: Type of the variable, can be ``string``, ``pathlist``, ``args``,  +               ``linelist`` or ``bool``.  Defaults to ``string`` if ``None`` or  +               not passed.  +        :default: Default value if no ini-file option exists but is queried.           The value of ini-variables can be retrieved via a call to          :py:func:`config.getini(name) <_pytest.config.Config.getini>`.          """ -        assert type in (None, "string", "pathlist", "args", "linelist", "bool") +        assert type in (None, "string", "pathlist", "args", "linelist", "bool")           self._inidict[name] = (help, type, default)          self._ininames.append(name)  class ArgumentError(Exception): -    """Raised if an Argument instance is created with invalid or -    inconsistent arguments.""" +    """Raised if an Argument instance is created with invalid or  +    inconsistent arguments."""  -    def __init__(self, msg: str, option: Union["Argument", str]) -> None: +    def __init__(self, msg: str, option: Union["Argument", str]) -> None:           self.msg = msg          self.option_id = str(option) -    def __str__(self) -> str: +    def __str__(self) -> str:           if self.option_id: -            return f"option {self.option_id}: {self.msg}" +            return f"option {self.option_id}: {self.msg}"           else:              return self.msg -class Argument: -    """Class that mimics the necessary behaviour of optparse.Option. - -    It's currently a least effort implementation and ignoring choices -    and integer prefixes. +class Argument:  +    """Class that mimics the necessary behaviour of optparse.Option.  +    It's currently a least effort implementation and ignoring choices  +    and integer prefixes.  +       https://docs.python.org/3/library/optparse.html#optparse-standard-option-types      """      _typ_map = {"int": int, "string": str, "float": float, "complex": complex} -    def __init__(self, *names: str, **attrs: Any) -> None: -        """Store parms in private vars for use in add_argument.""" +    def __init__(self, *names: str, **attrs: Any) -> None:  +        """Store parms in private vars for use in add_argument."""           self._attrs = attrs -        self._short_opts: List[str] = [] -        self._long_opts: List[str] = [] +        self._short_opts: List[str] = []  +        self._long_opts: List[str] = []           if "%default" in (attrs.get("help") or ""):              warnings.warn(                  'pytest now uses argparse. "%default" should be' @@ -224,8 +224,8 @@ class Argument:          except KeyError:              pass          else: -            # This might raise a keyerror as well, don't want to catch that. -            if isinstance(typ, str): +            # This might raise a keyerror as well, don't want to catch that.  +            if isinstance(typ, str):                   if typ == "choice":                      warnings.warn(                          "`type` argument to addoption() is the string %r." @@ -247,35 +247,35 @@ class Argument:                          stacklevel=4,                      )                      attrs["type"] = Argument._typ_map[typ] -                # Used in test_parseopt -> test_parse_defaultgetter. +                # Used in test_parseopt -> test_parse_defaultgetter.                   self.type = attrs["type"]              else:                  self.type = typ          try: -            # Attribute existence is tested in Config._processopt. +            # Attribute existence is tested in Config._processopt.               self.default = attrs["default"]          except KeyError:              pass          self._set_opt_strings(names) -        dest: Optional[str] = attrs.get("dest") -        if dest: -            self.dest = dest -        elif self._long_opts: -            self.dest = self._long_opts[0][2:].replace("-", "_") -        else: -            try: -                self.dest = self._short_opts[0][1:] -            except IndexError as e: -                self.dest = "???"  # Needed for the error repr. -                raise ArgumentError("need a long or short option", self) from e - -    def names(self) -> List[str]: +        dest: Optional[str] = attrs.get("dest")  +        if dest:  +            self.dest = dest  +        elif self._long_opts:  +            self.dest = self._long_opts[0][2:].replace("-", "_")  +        else:  +            try:  +                self.dest = self._short_opts[0][1:]  +            except IndexError as e:  +                self.dest = "???"  # Needed for the error repr.  +                raise ArgumentError("need a long or short option", self) from e  + +    def names(self) -> List[str]:           return self._short_opts + self._long_opts -    def attrs(self) -> Mapping[str, Any]: -        # Update any attributes set by processopt. +    def attrs(self) -> Mapping[str, Any]:  +        # Update any attributes set by processopt.           attrs = "default dest help".split() -        attrs.append(self.dest) +        attrs.append(self.dest)           for attr in attrs:              try:                  self._attrs[attr] = getattr(self, attr) @@ -288,11 +288,11 @@ class Argument:              self._attrs["help"] = a          return self._attrs -    def _set_opt_strings(self, opts: Sequence[str]) -> None: -        """Directly from optparse. +    def _set_opt_strings(self, opts: Sequence[str]) -> None:  +        """Directly from optparse.  -        Might not be necessary as this is passed to argparse later on. -        """ +        Might not be necessary as this is passed to argparse later on.  +        """           for opt in opts:              if len(opt) < 2:                  raise ArgumentError( @@ -317,8 +317,8 @@ class Argument:                      )                  self._long_opts.append(opt) -    def __repr__(self) -> str: -        args: List[str] = [] +    def __repr__(self) -> str:  +        args: List[str] = []           if self._short_opts:              args += ["_short_opts: " + repr(self._short_opts)]          if self._long_opts: @@ -331,22 +331,22 @@ class Argument:          return "Argument({})".format(", ".join(args)) -class OptionGroup: -    def __init__( -        self, name: str, description: str = "", parser: Optional[Parser] = None -    ) -> None: +class OptionGroup:  +    def __init__(  +        self, name: str, description: str = "", parser: Optional[Parser] = None  +    ) -> None:           self.name = name          self.description = description -        self.options: List[Argument] = [] +        self.options: List[Argument] = []           self.parser = parser -    def addoption(self, *optnames: str, **attrs: Any) -> None: -        """Add an option to this group. +    def addoption(self, *optnames: str, **attrs: Any) -> None:  +        """Add an option to this group.  -        If a shortened version of a long option is specified, it will +        If a shortened version of a long option is specified, it will           be suppressed in the help. addoption('--twowords', '--two-words')          results in help showing '--two-words' only, but --twowords gets -        accepted **and** the automatic destination is in args.twowords. +        accepted **and** the automatic destination is in args.twowords.           """          conflict = set(optnames).intersection(              name for opt in self.options for name in opt.names() @@ -356,11 +356,11 @@ class OptionGroup:          option = Argument(*optnames, **attrs)          self._addoption_instance(option, shortupper=False) -    def _addoption(self, *optnames: str, **attrs: Any) -> None: +    def _addoption(self, *optnames: str, **attrs: Any) -> None:           option = Argument(*optnames, **attrs)          self._addoption_instance(option, shortupper=True) -    def _addoption_instance(self, option: "Argument", shortupper: bool = False) -> None: +    def _addoption_instance(self, option: "Argument", shortupper: bool = False) -> None:           if not shortupper:              for opt in option._short_opts:                  if opt[0] == "-" and opt[1].islower(): @@ -371,133 +371,133 @@ class OptionGroup:  class MyOptionParser(argparse.ArgumentParser): -    def __init__( -        self, -        parser: Parser, -        extra_info: Optional[Dict[str, Any]] = None, -        prog: Optional[str] = None, -    ) -> None: +    def __init__(  +        self,  +        parser: Parser,  +        extra_info: Optional[Dict[str, Any]] = None,  +        prog: Optional[str] = None,  +    ) -> None:           self._parser = parser          argparse.ArgumentParser.__init__(              self, -            prog=prog, +            prog=prog,               usage=parser._usage,              add_help=False,              formatter_class=DropShorterLongHelpFormatter, -            allow_abbrev=False, +            allow_abbrev=False,           )          # extra_info is a dict of (param -> value) to display if there's -        # an usage error to provide more contextual information to the user. -        self.extra_info = extra_info if extra_info else {} - -    def error(self, message: str) -> "NoReturn": -        """Transform argparse error message into UsageError.""" -        msg = f"{self.prog}: error: {message}" - -        if hasattr(self._parser, "_config_source_hint"): -            # Type ignored because the attribute is set dynamically. -            msg = f"{msg} ({self._parser._config_source_hint})"  # type: ignore - -        raise UsageError(self.format_usage() + msg) - -    # Type ignored because typeshed has a very complex type in the superclass. -    def parse_args(  # type: ignore -        self, -        args: Optional[Sequence[str]] = None, -        namespace: Optional[argparse.Namespace] = None, -    ) -> argparse.Namespace: -        """Allow splitting of positional arguments.""" -        parsed, unrecognized = self.parse_known_args(args, namespace) -        if unrecognized: -            for arg in unrecognized: +        # an usage error to provide more contextual information to the user.  +        self.extra_info = extra_info if extra_info else {}  + +    def error(self, message: str) -> "NoReturn":  +        """Transform argparse error message into UsageError."""  +        msg = f"{self.prog}: error: {message}"  + +        if hasattr(self._parser, "_config_source_hint"):  +            # Type ignored because the attribute is set dynamically.  +            msg = f"{msg} ({self._parser._config_source_hint})"  # type: ignore  + +        raise UsageError(self.format_usage() + msg)  +  +    # Type ignored because typeshed has a very complex type in the superclass.  +    def parse_args(  # type: ignore  +        self,  +        args: Optional[Sequence[str]] = None,  +        namespace: Optional[argparse.Namespace] = None,  +    ) -> argparse.Namespace:  +        """Allow splitting of positional arguments."""  +        parsed, unrecognized = self.parse_known_args(args, namespace)  +        if unrecognized:  +            for arg in unrecognized:                   if arg and arg[0] == "-": -                    lines = ["unrecognized arguments: %s" % (" ".join(unrecognized))] +                    lines = ["unrecognized arguments: %s" % (" ".join(unrecognized))]                       for k, v in sorted(self.extra_info.items()): -                        lines.append(f"  {k}: {v}") +                        lines.append(f"  {k}: {v}")                       self.error("\n".join(lines)) -            getattr(parsed, FILE_OR_DIR).extend(unrecognized) -        return parsed - -    if sys.version_info[:2] < (3, 9):  # pragma: no cover -        # Backport of https://github.com/python/cpython/pull/14316 so we can -        # disable long --argument abbreviations without breaking short flags. -        def _parse_optional( -            self, arg_string: str -        ) -> Optional[Tuple[Optional[argparse.Action], str, Optional[str]]]: -            if not arg_string: -                return None -            if not arg_string[0] in self.prefix_chars: -                return None -            if arg_string in self._option_string_actions: -                action = self._option_string_actions[arg_string] -                return action, arg_string, None -            if len(arg_string) == 1: -                return None -            if "=" in arg_string: -                option_string, explicit_arg = arg_string.split("=", 1) -                if option_string in self._option_string_actions: -                    action = self._option_string_actions[option_string] -                    return action, option_string, explicit_arg -            if self.allow_abbrev or not arg_string.startswith("--"): -                option_tuples = self._get_option_tuples(arg_string) -                if len(option_tuples) > 1: -                    msg = gettext( -                        "ambiguous option: %(option)s could match %(matches)s" -                    ) -                    options = ", ".join(option for _, option, _ in option_tuples) -                    self.error(msg % {"option": arg_string, "matches": options}) -                elif len(option_tuples) == 1: -                    (option_tuple,) = option_tuples -                    return option_tuple -            if self._negative_number_matcher.match(arg_string): -                if not self._has_negative_number_optionals: -                    return None -            if " " in arg_string: -                return None -            return None, arg_string, None - - +            getattr(parsed, FILE_OR_DIR).extend(unrecognized)  +        return parsed  + +    if sys.version_info[:2] < (3, 9):  # pragma: no cover  +        # Backport of https://github.com/python/cpython/pull/14316 so we can  +        # disable long --argument abbreviations without breaking short flags.  +        def _parse_optional(  +            self, arg_string: str  +        ) -> Optional[Tuple[Optional[argparse.Action], str, Optional[str]]]:  +            if not arg_string:  +                return None  +            if not arg_string[0] in self.prefix_chars:  +                return None  +            if arg_string in self._option_string_actions:  +                action = self._option_string_actions[arg_string]  +                return action, arg_string, None  +            if len(arg_string) == 1:  +                return None  +            if "=" in arg_string:  +                option_string, explicit_arg = arg_string.split("=", 1)  +                if option_string in self._option_string_actions:  +                    action = self._option_string_actions[option_string]  +                    return action, option_string, explicit_arg  +            if self.allow_abbrev or not arg_string.startswith("--"):  +                option_tuples = self._get_option_tuples(arg_string)  +                if len(option_tuples) > 1:  +                    msg = gettext(  +                        "ambiguous option: %(option)s could match %(matches)s"  +                    )  +                    options = ", ".join(option for _, option, _ in option_tuples)  +                    self.error(msg % {"option": arg_string, "matches": options})  +                elif len(option_tuples) == 1:  +                    (option_tuple,) = option_tuples  +                    return option_tuple  +            if self._negative_number_matcher.match(arg_string):  +                if not self._has_negative_number_optionals:  +                    return None  +            if " " in arg_string:  +                return None  +            return None, arg_string, None  + +   class DropShorterLongHelpFormatter(argparse.HelpFormatter): -    """Shorten help for long options that differ only in extra hyphens. +    """Shorten help for long options that differ only in extra hyphens.  -    - Collapse **long** options that are the same except for extra hyphens. -    - Shortcut if there are only two options and one of them is a short one. -    - Cache result on the action object as this is called at least 2 times. +    - Collapse **long** options that are the same except for extra hyphens.  +    - Shortcut if there are only two options and one of them is a short one.  +    - Cache result on the action object as this is called at least 2 times.       """ -    def __init__(self, *args: Any, **kwargs: Any) -> None: -        # Use more accurate terminal width. -        if "width" not in kwargs: -            kwargs["width"] = _pytest._io.get_terminal_width() -        super().__init__(*args, **kwargs) - -    def _format_action_invocation(self, action: argparse.Action) -> str: +    def __init__(self, *args: Any, **kwargs: Any) -> None:  +        # Use more accurate terminal width.  +        if "width" not in kwargs:  +            kwargs["width"] = _pytest._io.get_terminal_width()  +        super().__init__(*args, **kwargs)  +  +    def _format_action_invocation(self, action: argparse.Action) -> str:           orgstr = argparse.HelpFormatter._format_action_invocation(self, action)          if orgstr and orgstr[0] != "-":  # only optional arguments              return orgstr -        res: Optional[str] = getattr(action, "_formatted_action_invocation", None) +        res: Optional[str] = getattr(action, "_formatted_action_invocation", None)           if res:              return res          options = orgstr.split(", ")          if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2):              # a shortcut for '-h, --help' or '--abc', '-a' -            action._formatted_action_invocation = orgstr  # type: ignore +            action._formatted_action_invocation = orgstr  # type: ignore               return orgstr          return_list = [] -        short_long: Dict[str, str] = {} +        short_long: Dict[str, str] = {}           for option in options:              if len(option) == 2 or option[2] == " ":                  continue              if not option.startswith("--"):                  raise ArgumentError( -                    'long optional argument without "--": [%s]' % (option), option +                    'long optional argument without "--": [%s]' % (option), option                   )              xxoption = option[2:] -            shortened = xxoption.replace("-", "") -            if shortened not in short_long or len(short_long[shortened]) < len( -                xxoption -            ): -                short_long[shortened] = xxoption +            shortened = xxoption.replace("-", "")  +            if shortened not in short_long or len(short_long[shortened]) < len(  +                xxoption  +            ):  +                short_long[shortened] = xxoption           # now short_long has been filled out to the longest with dashes          # **and** we keep the right option ordering from add_argument          for option in options: @@ -505,18 +505,18 @@ class DropShorterLongHelpFormatter(argparse.HelpFormatter):                  return_list.append(option)              if option[2:] == short_long.get(option.replace("-", "")):                  return_list.append(option.replace(" ", "=", 1)) -        formatted_action_invocation = ", ".join(return_list) -        action._formatted_action_invocation = formatted_action_invocation  # type: ignore -        return formatted_action_invocation - -    def _split_lines(self, text, width): -        """Wrap lines after splitting on original newlines. - -        This allows to have explicit line breaks in the help text. -        """ -        import textwrap - -        lines = [] -        for line in text.splitlines(): -            lines.extend(textwrap.wrap(line.strip(), width)) -        return lines +        formatted_action_invocation = ", ".join(return_list)  +        action._formatted_action_invocation = formatted_action_invocation  # type: ignore  +        return formatted_action_invocation  +  +    def _split_lines(self, text, width):  +        """Wrap lines after splitting on original newlines.  +  +        This allows to have explicit line breaks in the help text.  +        """  +        import textwrap  +  +        lines = []  +        for line in text.splitlines():  +            lines.extend(textwrap.wrap(line.strip(), width))  +        return lines   | 
