This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author rive-n
Recipients lys.nikolaou, rive-n
Date 2022-03-22.08:42:29
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1647938550.12.0.081893810281.issue47043@roundup.psfhosted.org>
In-reply-to
Content
Long time no updates here. Another fix. In past version more than 1 argument could not be parsed. Fix (finally with unittests):

```python3
    def __call__(self, parser, namespace, values, option_string=None, arg_strings_pattern:list =None):
        o_amount = arg_strings_pattern.count("O")
        if not o_amount:
            raise ValueError("No Os found")
        o_start, o_stop, indexes = arg_strings_pattern.index('O'), len(arg_strings_pattern), []
        print(parser)
        try:
            while arg_strings_pattern.index('O', o_start, o_stop):
                indexes.append(arg_strings_pattern.index('O', o_start, o_stop))
                o_start = arg_strings_pattern.index('O', o_start + 1, o_stop)
        except ValueError:
            pass

        used_indexes = []
        known_args = {}
        for i, index in enumerate(indexes):
            parser_name = values[index - 1]
            if not known_args.get(parser_name):
                known_args[parser_name] = []
                known_args[parser_name] += values[index: indexes[i + 1] - 1] if i + 1 < len(indexes) else values[index:]
            if index not in used_indexes:
                for s, subindex in enumerate(indexes[1:]):
                    subparser_name = values[subindex - 1]
                    if parser_name == subparser_name:
                        used_indexes.append(index)
                        used_indexes.append(subindex)
                        subparser_args = values[subindex: indexes[s + 2] - 1] if s + 2 < len(indexes) else values[subindex:]
                        known_args[parser_name] += subparser_args

        for parser_name, args in known_args.items():
            self._create_parser(namespace, parser_name, args)

    def _create_parser(self, namespace, parser_name, arg_strings):

        # set the parser name if requested
        if self.dest is not SUPPRESS:
            setattr(namespace, self.dest, parser_name)

        # select the parser
        try:
            parser = self._name_parser_map[parser_name]
        except KeyError:
            args = {'parser_name': parser_name,
                    'choices': ', '.join(self._name_parser_map)}
            msg = _('unknown parser %(parser_name)r (choices: %(choices)s)') % args
            raise ArgumentError(self, msg)

        # parse all the remaining options into the namespace
        # store any unrecognized options on the object, so that the top
        # level parser can decide what to do with them

        # In case this subparser defines new defaults, we parse them
        # in a new namespace object and then update the original
        # namespace for the relevant parts.
        subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
        for key, value in vars(subnamespace).items():
            setattr(namespace, key, value)

        if arg_strings:
            vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
            getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)

```

Unittests:
```python3
import unittest
import argfork as argparse
from argfork import Namespace


class argparseTest(unittest.TestCase):

    def setUp(self) -> None:
        self.parser = argparse.ArgumentParser(prog='PROG')
        subparsers = self.parser.add_subparsers(help='sub-command help')

        # create the parser for the "a" command
        parser_a = subparsers.add_parser('a', help='a help')
        parser_a.add_argument('-a', help='bar help')

        # create the parser for the "b" command
        parser_b = subparsers.add_parser('b', help='b help')
        parser_b.add_argument('-b', help='baz help')
        parser_b.add_argument('-q', help='baz help')

        # create the parser for the "c" command
        parser_b = subparsers.add_parser('c', help='b help')
        parser_b.add_argument('-c', help='baz help')
        parser_b.add_argument('-k', help='baz help')

        # create the parser for the "c" command
        parser_b = subparsers.add_parser('d', help='b help')
        parser_b.add_argument('-d', help='baz help')
        parser_b.add_argument('-D', help='baz help')
        parser_b.add_argument('-R', help='baz help')

    def testSimple(self):
        case = ['a', '-a', 'test']
        res_obj = Namespace(a='test').__dict__
        rest_obj = self.parser.parse_known_args(case)[0].__dict__

        res_k, res_v = res_obj.keys(), list(res_obj.values())
        test_k, test_v = rest_obj.keys(), list(rest_obj.values())

        self.assertEqual(res_v, test_v)
        self.assertEqual(res_k, test_k)

    def testMany(self):
        case = ['d', '-d', '1234', 'd', '-D', '12345', 'd', '-R', '1', 'c', '-c', '123', 'c', '-k', '555', 'b', '-q', 'test']
        res_obj = Namespace(d='1234', D='12345', R='1', c='123', k='555', b=None, q='test').__dict__
        rest_obj = self.parser.parse_known_args(case)[0].__dict__

        res_k, res_v = res_obj.keys(), list(res_obj.values())
        test_k, test_v = rest_obj.keys(), list(rest_obj.values())

        self.assertEqual(res_v, test_v)
        self.assertEqual(res_k, test_k)

    def testZero(self):
        case = []
        res_obj = Namespace().__dict__
        rest_obj = self.parser.parse_known_args(case)[0].__dict__

        res_k, res_v = res_obj.keys(), list(res_obj.values())
        test_k, test_v = rest_obj.keys(), list(rest_obj.values())

        self.assertEqual(res_v, test_v)
        self.assertEqual(res_k, test_k)

if __name__ == '__main__':
    unittest.main()
```
History
Date User Action Args
2022-03-22 08:42:30rive-nsetrecipients: + rive-n, lys.nikolaou
2022-03-22 08:42:30rive-nsetmessageid: <1647938550.12.0.081893810281.issue47043@roundup.psfhosted.org>
2022-03-22 08:42:30rive-nlinkissue47043 messages
2022-03-22 08:42:29rive-ncreate