def _kwargs_to_str_args()

in parlai/core/params.py [0:0]


    def _kwargs_to_str_args(self, **kwargs):
        """
        Attempt to map from python-code kwargs into CLI args.

        e.g. model_file -> --model-file.

        Works with short options too, like t="convai2".
        """

        # we have to do this large block of repetitive code twice, the first
        # round is basically just to become aware of anything that would have
        # been added by add_extra_args
        kwname_to_action = {}
        for action in self._actions:
            if action.dest == 'help':
                # no help allowed
                continue
            for option_string in action.option_strings:
                kwname = option_string.lstrip('-').replace('-', '_')
                assert (kwname not in kwname_to_action) or (
                    kwname_to_action[kwname] is action
                ), f"No duplicate names! ({kwname}, {kwname_to_action[kwname]}, {action})"
                kwname_to_action[kwname] = action

        # since we can have options that depend on options, repeat until convergence
        string_args = []
        unparsed_args = set(kwargs.keys())
        while unparsed_args:
            string_args = []
            for kwname, value in kwargs.items():
                if kwname not in kwname_to_action:
                    # best guess, we need to delay it. hopefully this gets added
                    # during add_kw_Args
                    continue
                action = kwname_to_action[kwname]
                last_option_string = action.option_strings[-1]
                if isinstance(action, argparse._StoreTrueAction):
                    if bool(value):
                        string_args.append(last_option_string)
                elif isinstance(action, argparse._StoreAction) and action.nargs is None:
                    string_args.append(last_option_string)
                    string_args.append(self._value2argstr(value))
                elif isinstance(action, argparse._StoreAction) and action.nargs in '*+':
                    string_args.append(last_option_string)
                    string_args.extend([self._value2argstr(v) for v in value])
                else:
                    raise TypeError(f"Don't know what to do with {action}")

            # become aware of any extra args that might be specified if the user
            # provides something like model="transformer/generator".
            self.add_extra_args(string_args)

            # do it again, this time knowing about ALL args.
            kwname_to_action = {}
            for action in self._actions:
                if action.dest == 'help':
                    # no help allowed
                    continue
                for option_string in action.option_strings:
                    kwname = option_string.lstrip('-').replace('-', '_')
                    assert (kwname not in kwname_to_action) or (
                        kwname_to_action[kwname] is action
                    ), f"No duplicate names! ({kwname}, {kwname_to_action[kwname]}, {action})"
                    kwname_to_action[kwname] = action

            new_unparsed_args = set()
            string_args = []
            for kwname, value in kwargs.items():
                if kwname not in kwname_to_action:
                    new_unparsed_args.add(kwname)
                    continue

                action = kwname_to_action[kwname]
                last_option_string = action.option_strings[-1]
                if isinstance(action, argparse._StoreTrueAction):
                    if bool(value):
                        string_args.append(last_option_string)
                elif isinstance(action, argparse._StoreAction) and action.nargs is None:
                    string_args.append(last_option_string)
                    string_args.append(self._value2argstr(value))
                elif isinstance(action, argparse._StoreAction) and action.nargs in '*+':
                    string_args.append(last_option_string)
                    # Special case: Labels
                    string_args.extend([self._value2argstr(v) for v in value])
                else:
                    raise TypeError(f"Don't know what to do with {action}")

            if new_unparsed_args == unparsed_args:
                # if we have converged to a fixed point with no improvements, we
                # truly found some unreachable args
                raise KeyError(
                    f'Failed to parse one or more kwargs: {", ".join(new_unparsed_args)}'
                )
            else:
                # We've seen some improvements on the number of unparsed args,
                # iterate again
                unparsed_args = new_unparsed_args

        return string_args