gridparse 1.5.0__tar.gz → 1.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gridparse-1.5.0/gridparse.egg-info → gridparse-1.5.2}/PKG-INFO +1 -1
- {gridparse-1.5.0 → gridparse-1.5.2}/gridparse/grid_argument_parser.py +358 -20
- {gridparse-1.5.0 → gridparse-1.5.2/gridparse.egg-info}/PKG-INFO +1 -1
- {gridparse-1.5.0 → gridparse-1.5.2}/pyproject.toml +1 -2
- {gridparse-1.5.0 → gridparse-1.5.2}/setup.py +1 -1
- {gridparse-1.5.0 → gridparse-1.5.2}/LICENSE +0 -0
- {gridparse-1.5.0 → gridparse-1.5.2}/MANIFEST.in +0 -0
- {gridparse-1.5.0 → gridparse-1.5.2}/README.md +0 -0
- {gridparse-1.5.0 → gridparse-1.5.2}/gridparse/__init__.py +0 -0
- {gridparse-1.5.0 → gridparse-1.5.2}/gridparse/utils.py +0 -0
- {gridparse-1.5.0 → gridparse-1.5.2}/gridparse.egg-info/SOURCES.txt +0 -0
- {gridparse-1.5.0 → gridparse-1.5.2}/gridparse.egg-info/dependency_links.txt +0 -0
- {gridparse-1.5.0 → gridparse-1.5.2}/gridparse.egg-info/requires.txt +0 -0
- {gridparse-1.5.0 → gridparse-1.5.2}/gridparse.egg-info/top_level.txt +0 -0
- {gridparse-1.5.0 → gridparse-1.5.2}/setup.cfg +0 -0
| @@ -8,6 +8,328 @@ from omegaconf import OmegaConf | |
| 8 8 | 
             
            from gridparse.utils import list_as_dashed_str, strbool
         | 
| 9 9 |  | 
| 10 10 |  | 
| 11 | 
            +
            class AuxArgumentParser(argparse.ArgumentParser):
         | 
| 12 | 
            +
                """Overwritten only to collect the argument names that
         | 
| 13 | 
            +
                are specified in the command line."""
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def parse_known_args(
         | 
| 16 | 
            +
                    self, args=None, namespace=None
         | 
| 17 | 
            +
                ) -> Tuple[argparse.Namespace, List[str]]:
         | 
| 18 | 
            +
                    """Overwritten to collect the argument names that
         | 
| 19 | 
            +
                    are specified in the command line."""
         | 
| 20 | 
            +
                    if args is None:
         | 
| 21 | 
            +
                        # args default to the system args
         | 
| 22 | 
            +
                        args = argparse._sys.argv[1:]
         | 
| 23 | 
            +
                    else:
         | 
| 24 | 
            +
                        # make sure that args are mutable
         | 
| 25 | 
            +
                        args = list(args)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    # default Namespace built from parser defaults
         | 
| 28 | 
            +
                    if namespace is None:
         | 
| 29 | 
            +
                        namespace = argparse.Namespace()
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    if not hasattr(namespace, "___specified_args___"):
         | 
| 32 | 
            +
                        setattr(namespace, "___specified_args___", set())
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                    # add any action defaults that aren't present
         | 
| 35 | 
            +
                    for action in self._actions:
         | 
| 36 | 
            +
                        if action.dest is not argparse.SUPPRESS:
         | 
| 37 | 
            +
                            if not hasattr(namespace, action.dest):
         | 
| 38 | 
            +
                                if action.default is not argparse.SUPPRESS:
         | 
| 39 | 
            +
                                    setattr(namespace, action.dest, action.default)
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    # add any parser defaults that aren't present
         | 
| 42 | 
            +
                    for dest in self._defaults:
         | 
| 43 | 
            +
                        if not hasattr(namespace, dest):
         | 
| 44 | 
            +
                            setattr(namespace, dest, self._defaults[dest])
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    # parse the arguments and exit if there are any errors
         | 
| 47 | 
            +
                    if self.exit_on_error:
         | 
| 48 | 
            +
                        try:
         | 
| 49 | 
            +
                            namespace, args = self._parse_known_args(args, namespace)
         | 
| 50 | 
            +
                        except argparse.ArgumentError:
         | 
| 51 | 
            +
                            err = argparse._sys.exc_info()[1]
         | 
| 52 | 
            +
                            self.error(str(err))
         | 
| 53 | 
            +
                    else:
         | 
| 54 | 
            +
                        namespace, args = self._parse_known_args(args, namespace)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    if hasattr(namespace, argparse._UNRECOGNIZED_ARGS_ATTR):
         | 
| 57 | 
            +
                        args.extend(getattr(namespace, argparse._UNRECOGNIZED_ARGS_ATTR))
         | 
| 58 | 
            +
                        delattr(namespace, argparse._UNRECOGNIZED_ARGS_ATTR)
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                    return namespace, args
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def _parse_known_args(
         | 
| 63 | 
            +
                    self, arg_strings, namespace
         | 
| 64 | 
            +
                ) -> Tuple[List[argparse.Namespace], List[str]]:
         | 
| 65 | 
            +
                    """Overwritten to collect the argument names that
         | 
| 66 | 
            +
                    are specified in the command line."""
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    # replace arg strings that are file references
         | 
| 69 | 
            +
                    if self.fromfile_prefix_chars is not None:
         | 
| 70 | 
            +
                        arg_strings = self._read_args_from_files(arg_strings)
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    # map all mutually exclusive arguments to the other arguments
         | 
| 73 | 
            +
                    # they can't occur with
         | 
| 74 | 
            +
                    action_conflicts = {}
         | 
| 75 | 
            +
                    for mutex_group in self._mutually_exclusive_groups:
         | 
| 76 | 
            +
                        group_actions = mutex_group._group_actions
         | 
| 77 | 
            +
                        for i, mutex_action in enumerate(mutex_group._group_actions):
         | 
| 78 | 
            +
                            conflicts = action_conflicts.setdefault(mutex_action, [])
         | 
| 79 | 
            +
                            conflicts.extend(group_actions[:i])
         | 
| 80 | 
            +
                            conflicts.extend(group_actions[i + 1 :])
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    # find all option indices, and determine the arg_string_pattern
         | 
| 83 | 
            +
                    # which has an 'O' if there is an option at an index,
         | 
| 84 | 
            +
                    # an 'A' if there is an argument, or a '-' if there is a '--'
         | 
| 85 | 
            +
                    option_string_indices = {}
         | 
| 86 | 
            +
                    arg_string_pattern_parts = []
         | 
| 87 | 
            +
                    arg_strings_iter = iter(arg_strings)
         | 
| 88 | 
            +
                    for i, arg_string in enumerate(arg_strings_iter):
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                        # all args after -- are non-options
         | 
| 91 | 
            +
                        if arg_string == '--':
         | 
| 92 | 
            +
                            arg_string_pattern_parts.append('-')
         | 
| 93 | 
            +
                            for arg_string in arg_strings_iter:
         | 
| 94 | 
            +
                                arg_string_pattern_parts.append('A')
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                        # otherwise, add the arg to the arg strings
         | 
| 97 | 
            +
                        # and note the index if it was an option
         | 
| 98 | 
            +
                        else:
         | 
| 99 | 
            +
                            option_tuple = self._parse_optional(arg_string)
         | 
| 100 | 
            +
                            if option_tuple is None:
         | 
| 101 | 
            +
                                pattern = 'A'
         | 
| 102 | 
            +
                            else:
         | 
| 103 | 
            +
                                option_string_indices[i] = option_tuple
         | 
| 104 | 
            +
                                pattern = 'O'
         | 
| 105 | 
            +
                            arg_string_pattern_parts.append(pattern)
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                    # join the pieces together to form the pattern
         | 
| 108 | 
            +
                    arg_strings_pattern = ''.join(arg_string_pattern_parts)
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                    # converts arg strings to the appropriate and then takes the action
         | 
| 111 | 
            +
                    seen_actions = set()
         | 
| 112 | 
            +
                    seen_non_default_actions = set()
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                    def take_action(action, argument_strings, option_string=None):
         | 
| 115 | 
            +
                        seen_actions.add(action)
         | 
| 116 | 
            +
                        argument_values = self._get_values(action, argument_strings)
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                        # error if this argument is not allowed with other previously
         | 
| 119 | 
            +
                        # seen arguments, assuming that actions that use the default
         | 
| 120 | 
            +
                        # value don't really count as "present"
         | 
| 121 | 
            +
                        if argument_values is not action.default:
         | 
| 122 | 
            +
                            seen_non_default_actions.add(action)
         | 
| 123 | 
            +
                            for conflict_action in action_conflicts.get(action, []):
         | 
| 124 | 
            +
                                if conflict_action in seen_non_default_actions:
         | 
| 125 | 
            +
                                    msg = argparse._('not allowed with argument %s')
         | 
| 126 | 
            +
                                    action_name = argparse._get_action_name(conflict_action)
         | 
| 127 | 
            +
                                    raise argparse.ArgumentError(action, msg % action_name)
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                        # take the action if we didn't receive a SUPPRESS value
         | 
| 130 | 
            +
                        # (e.g. from a default)
         | 
| 131 | 
            +
                        if argument_values is not argparse.SUPPRESS:
         | 
| 132 | 
            +
                            action(self, namespace, argument_values, option_string)
         | 
| 133 | 
            +
                            namespace.___specified_args___.add(action.dest)
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                    # function to convert arg_strings into an optional action
         | 
| 136 | 
            +
                    def consume_optional(start_index):
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                        # get the optional identified at this index
         | 
| 139 | 
            +
                        option_tuple = option_string_indices[start_index]
         | 
| 140 | 
            +
                        action, option_string, explicit_arg = option_tuple
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                        # identify additional optionals in the same arg string
         | 
| 143 | 
            +
                        # (e.g. -xyz is the same as -x -y -z if no args are required)
         | 
| 144 | 
            +
                        match_argument = self._match_argument
         | 
| 145 | 
            +
                        action_tuples = []
         | 
| 146 | 
            +
                        while True:
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                            # if we found no optional action, skip it
         | 
| 149 | 
            +
                            if action is None:
         | 
| 150 | 
            +
                                extras.append(arg_strings[start_index])
         | 
| 151 | 
            +
                                return start_index + 1
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                            # if there is an explicit argument, try to match the
         | 
| 154 | 
            +
                            # optional's string arguments to only this
         | 
| 155 | 
            +
                            if explicit_arg is not None:
         | 
| 156 | 
            +
                                arg_count = match_argument(action, 'A')
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                                # if the action is a single-dash option and takes no
         | 
| 159 | 
            +
                                # arguments, try to parse more single-dash options out
         | 
| 160 | 
            +
                                # of the tail of the option string
         | 
| 161 | 
            +
                                chars = self.prefix_chars
         | 
| 162 | 
            +
                                if (
         | 
| 163 | 
            +
                                    arg_count == 0
         | 
| 164 | 
            +
                                    and option_string[1] not in chars
         | 
| 165 | 
            +
                                    and explicit_arg != ''
         | 
| 166 | 
            +
                                ):
         | 
| 167 | 
            +
                                    action_tuples.append((action, [], option_string))
         | 
| 168 | 
            +
                                    char = option_string[0]
         | 
| 169 | 
            +
                                    option_string = char + explicit_arg[0]
         | 
| 170 | 
            +
                                    new_explicit_arg = explicit_arg[1:] or None
         | 
| 171 | 
            +
                                    optionals_map = self._option_string_actions
         | 
| 172 | 
            +
                                    if option_string in optionals_map:
         | 
| 173 | 
            +
                                        action = optionals_map[option_string]
         | 
| 174 | 
            +
                                        explicit_arg = new_explicit_arg
         | 
| 175 | 
            +
                                    else:
         | 
| 176 | 
            +
                                        msg = argparse._('ignored explicit argument %r')
         | 
| 177 | 
            +
                                        raise argparse.ArgumentError(
         | 
| 178 | 
            +
                                            action, msg % explicit_arg
         | 
| 179 | 
            +
                                        )
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                                # if the action expect exactly one argument, we've
         | 
| 182 | 
            +
                                # successfully matched the option; exit the loop
         | 
| 183 | 
            +
                                elif arg_count == 1:
         | 
| 184 | 
            +
                                    stop = start_index + 1
         | 
| 185 | 
            +
                                    args = [explicit_arg]
         | 
| 186 | 
            +
                                    action_tuples.append((action, args, option_string))
         | 
| 187 | 
            +
                                    break
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                                # error if a double-dash option did not use the
         | 
| 190 | 
            +
                                # explicit argument
         | 
| 191 | 
            +
                                else:
         | 
| 192 | 
            +
                                    msg = argparse._('ignored explicit argument %r')
         | 
| 193 | 
            +
                                    raise argparse.ArgumentError(action, msg % explicit_arg)
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                            # if there is no explicit argument, try to match the
         | 
| 196 | 
            +
                            # optional's string arguments with the following strings
         | 
| 197 | 
            +
                            # if successful, exit the loop
         | 
| 198 | 
            +
                            else:
         | 
| 199 | 
            +
                                start = start_index + 1
         | 
| 200 | 
            +
                                selected_patterns = arg_strings_pattern[start:]
         | 
| 201 | 
            +
                                arg_count = match_argument(action, selected_patterns)
         | 
| 202 | 
            +
                                stop = start + arg_count
         | 
| 203 | 
            +
                                args = arg_strings[start:stop]
         | 
| 204 | 
            +
                                action_tuples.append((action, args, option_string))
         | 
| 205 | 
            +
                                break
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                        # add the Optional to the list and return the index at which
         | 
| 208 | 
            +
                        # the Optional's string args stopped
         | 
| 209 | 
            +
                        assert action_tuples
         | 
| 210 | 
            +
                        for action, args, option_string in action_tuples:
         | 
| 211 | 
            +
                            take_action(action, args, option_string)
         | 
| 212 | 
            +
                        return stop
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                    # the list of Positionals left to be parsed; this is modified
         | 
| 215 | 
            +
                    # by consume_positionals()
         | 
| 216 | 
            +
                    positionals = self._get_positional_actions()
         | 
| 217 | 
            +
             | 
| 218 | 
            +
                    # function to convert arg_strings into positional actions
         | 
| 219 | 
            +
                    def consume_positionals(start_index):
         | 
| 220 | 
            +
                        # match as many Positionals as possible
         | 
| 221 | 
            +
                        match_partial = self._match_arguments_partial
         | 
| 222 | 
            +
                        selected_pattern = arg_strings_pattern[start_index:]
         | 
| 223 | 
            +
                        arg_counts = match_partial(positionals, selected_pattern)
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                        # slice off the appropriate arg strings for each Positional
         | 
| 226 | 
            +
                        # and add the Positional and its args to the list
         | 
| 227 | 
            +
                        for action, arg_count in zip(positionals, arg_counts):
         | 
| 228 | 
            +
                            args = arg_strings[start_index : start_index + arg_count]
         | 
| 229 | 
            +
                            start_index += arg_count
         | 
| 230 | 
            +
                            take_action(action, args)
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                        # slice off the Positionals that we just parsed and return the
         | 
| 233 | 
            +
                        # index at which the Positionals' string args stopped
         | 
| 234 | 
            +
                        positionals[:] = positionals[len(arg_counts) :]
         | 
| 235 | 
            +
                        return start_index
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                    # consume Positionals and Optionals alternately, until we have
         | 
| 238 | 
            +
                    # passed the last option string
         | 
| 239 | 
            +
                    extras = []
         | 
| 240 | 
            +
                    start_index = 0
         | 
| 241 | 
            +
                    if option_string_indices:
         | 
| 242 | 
            +
                        max_option_string_index = max(option_string_indices)
         | 
| 243 | 
            +
                    else:
         | 
| 244 | 
            +
                        max_option_string_index = -1
         | 
| 245 | 
            +
                    while start_index <= max_option_string_index:
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                        # consume any Positionals preceding the next option
         | 
| 248 | 
            +
                        next_option_string_index = min(
         | 
| 249 | 
            +
                            [
         | 
| 250 | 
            +
                                index
         | 
| 251 | 
            +
                                for index in option_string_indices
         | 
| 252 | 
            +
                                if index >= start_index
         | 
| 253 | 
            +
                            ]
         | 
| 254 | 
            +
                        )
         | 
| 255 | 
            +
                        if start_index != next_option_string_index:
         | 
| 256 | 
            +
                            positionals_end_index = consume_positionals(start_index)
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                            # only try to parse the next optional if we didn't consume
         | 
| 259 | 
            +
                            # the option string during the positionals parsing
         | 
| 260 | 
            +
                            if positionals_end_index > start_index:
         | 
| 261 | 
            +
                                start_index = positionals_end_index
         | 
| 262 | 
            +
                                continue
         | 
| 263 | 
            +
                            else:
         | 
| 264 | 
            +
                                start_index = positionals_end_index
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                        # if we consumed all the positionals we could and we're not
         | 
| 267 | 
            +
                        # at the index of an option string, there were extra arguments
         | 
| 268 | 
            +
                        if start_index not in option_string_indices:
         | 
| 269 | 
            +
                            strings = arg_strings[start_index:next_option_string_index]
         | 
| 270 | 
            +
                            extras.extend(strings)
         | 
| 271 | 
            +
                            start_index = next_option_string_index
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                        # consume the next optional and any arguments for it
         | 
| 274 | 
            +
                        start_index = consume_optional(start_index)
         | 
| 275 | 
            +
             | 
| 276 | 
            +
                    # consume any positionals following the last Optional
         | 
| 277 | 
            +
                    stop_index = consume_positionals(start_index)
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                    # if we didn't consume all the argument strings, there were extras
         | 
| 280 | 
            +
                    extras.extend(arg_strings[stop_index:])
         | 
| 281 | 
            +
             | 
| 282 | 
            +
                    # make sure all required actions were present and also convert
         | 
| 283 | 
            +
                    # action defaults which were not given as arguments
         | 
| 284 | 
            +
                    required_actions = []
         | 
| 285 | 
            +
                    for action in self._actions:
         | 
| 286 | 
            +
                        if action not in seen_actions:
         | 
| 287 | 
            +
                            if action.required:
         | 
| 288 | 
            +
                                required_actions.append(argparse._get_action_name(action))
         | 
| 289 | 
            +
                            else:
         | 
| 290 | 
            +
                                # Convert action default now instead of doing it before
         | 
| 291 | 
            +
                                # parsing arguments to avoid calling convert functions
         | 
| 292 | 
            +
                                # twice (which may fail) if the argument was given, but
         | 
| 293 | 
            +
                                # only if it was defined already in the namespace
         | 
| 294 | 
            +
                                if (
         | 
| 295 | 
            +
                                    action.default is not None
         | 
| 296 | 
            +
                                    and isinstance(action.default, str)
         | 
| 297 | 
            +
                                    and hasattr(namespace, action.dest)
         | 
| 298 | 
            +
                                    and action.default is getattr(namespace, action.dest)
         | 
| 299 | 
            +
                                ):
         | 
| 300 | 
            +
                                    setattr(
         | 
| 301 | 
            +
                                        namespace,
         | 
| 302 | 
            +
                                        action.dest,
         | 
| 303 | 
            +
                                        self._get_value(action, action.default),
         | 
| 304 | 
            +
                                    )
         | 
| 305 | 
            +
             | 
| 306 | 
            +
                    if required_actions:
         | 
| 307 | 
            +
                        self.error(
         | 
| 308 | 
            +
                            argparse._('the following arguments are required: %s')
         | 
| 309 | 
            +
                            % ', '.join(required_actions)
         | 
| 310 | 
            +
                        )
         | 
| 311 | 
            +
             | 
| 312 | 
            +
                    # make sure all required groups had one option present
         | 
| 313 | 
            +
                    for group in self._mutually_exclusive_groups:
         | 
| 314 | 
            +
                        if group.required:
         | 
| 315 | 
            +
                            for action in group._group_actions:
         | 
| 316 | 
            +
                                if action in seen_non_default_actions:
         | 
| 317 | 
            +
                                    break
         | 
| 318 | 
            +
             | 
| 319 | 
            +
                            # if no actions were used, report the error
         | 
| 320 | 
            +
                            else:
         | 
| 321 | 
            +
                                names = [
         | 
| 322 | 
            +
                                    argparse._get_action_name(action)
         | 
| 323 | 
            +
                                    for action in group._group_actions
         | 
| 324 | 
            +
                                    if action.help is not argparse.SUPPRESS
         | 
| 325 | 
            +
                                ]
         | 
| 326 | 
            +
                                msg = argparse._('one of the arguments %s is required')
         | 
| 327 | 
            +
                                self.error(msg % ' '.join(names))
         | 
| 328 | 
            +
             | 
| 329 | 
            +
                    # return the updated namespace, the extra arguments, and the epxlicitly specified args
         | 
| 330 | 
            +
                    return namespace, extras
         | 
| 331 | 
            +
             | 
| 332 | 
            +
             | 
| 11 333 | 
             
            # overwritten to fix issue in __call__
         | 
| 12 334 | 
             
            class _GridSubparsersAction(argparse._SubParsersAction):
         | 
| 13 335 | 
             
                def __call__(
         | 
| @@ -57,7 +379,13 @@ class _GridSubparsersAction(argparse._SubParsersAction): | |
| 57 379 | 
             
                    subnamespaces, arg_strings = parser.parse_known_args(arg_strings, None)
         | 
| 58 380 | 
             
                    for subnamespace in subnamespaces:
         | 
| 59 381 | 
             
                        new_namespace = deepcopy(namespace)
         | 
| 382 | 
            +
                        new_namespace.___specified_args___.update(
         | 
| 383 | 
            +
                            subnamespace.___specified_args___
         | 
| 384 | 
            +
                        )
         | 
| 385 | 
            +
             | 
| 60 386 | 
             
                        for key, value in vars(subnamespace).items():
         | 
| 387 | 
            +
                            if key == "___specified_args___":
         | 
| 388 | 
            +
                                continue
         | 
| 61 389 | 
             
                            setattr(new_namespace, key, value)
         | 
| 62 390 | 
             
                        namespaces.append(new_namespace)
         | 
| 63 391 |  | 
| @@ -81,7 +409,7 @@ class _GridActionsContainer(argparse._ActionsContainer): | |
| 81 409 | 
             
                    self.register("action", "parsers", _GridSubparsersAction)
         | 
| 82 410 |  | 
| 83 411 |  | 
| 84 | 
            -
            class GridArgumentParser(_GridActionsContainer,  | 
| 412 | 
            +
            class GridArgumentParser(_GridActionsContainer, AuxArgumentParser):
         | 
| 85 413 | 
             
                """ArgumentParser that supports grid search.
         | 
| 86 414 |  | 
| 87 415 | 
             
                It transforms the following arguments in the corresponding way:
         | 
| @@ -163,7 +491,7 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 163 491 |  | 
| 164 492 | 
             
                def __init__(self, retain_config_filename: bool = False, *args, **kwargs):
         | 
| 165 493 | 
             
                    """Initializes the GridArgumentParser.
         | 
| 166 | 
            -
             | 
| 494 | 
            +
             | 
| 167 495 | 
             
                    Args:
         | 
| 168 496 | 
             
                        retain_config_filename: whether to keep the `gridparse-config` argument
         | 
| 169 497 | 
             
                            in the namespace or not.
         | 
| @@ -180,9 +508,9 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 180 508 | 
             
                        "Values will be used if not provided in the command line.",
         | 
| 181 509 | 
             
                    )
         | 
| 182 510 |  | 
| 183 | 
            -
             | 
| 184 511 | 
             
                def parse_args(self, *args, **kwargs):
         | 
| 185 512 | 
             
                    vals = super().parse_args(*args, **kwargs)
         | 
| 513 | 
            +
             | 
| 186 514 | 
             
                    # hacky way to return namespaces in subparser
         | 
| 187 515 | 
             
                    if "___namespaces___" in vals[0]:
         | 
| 188 516 | 
             
                        vals = [ns for subps_ns in vals for ns in subps_ns.___namespaces___]
         | 
| @@ -220,21 +548,25 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 220 548 | 
             
                        cfg = {}
         | 
| 221 549 | 
             
                        if ns.gridparse_config is not None:
         | 
| 222 550 | 
             
                            # reverse for priority to originally first configs
         | 
| 223 | 
            -
                            for potential_fn in reversed( | 
| 551 | 
            +
                            for potential_fn in reversed(
         | 
| 552 | 
            +
                                getattr(ns, "gridparse_config", [])
         | 
| 553 | 
            +
                            ):
         | 
| 224 554 | 
             
                                if os.path.isfile(potential_fn):
         | 
| 225 555 | 
             
                                    cfg = OmegaConf.merge(cfg, OmegaConf.load(potential_fn))
         | 
| 226 556 |  | 
| 227 557 | 
             
                            for arg in cfg:
         | 
| 228 558 | 
             
                                if not hasattr(ns, arg):
         | 
| 229 559 | 
             
                                    continue
         | 
| 230 | 
            -
                                if  | 
| 231 | 
            -
                                    setattr(ns, arg,  | 
| 560 | 
            +
                                if arg not in ns.___specified_args___:
         | 
| 561 | 
            +
                                    setattr(ns, arg, cfg.get(arg))
         | 
| 232 562 |  | 
| 233 563 | 
             
                        if not self._retain_config_filename:
         | 
| 234 564 | 
             
                            delattr(ns, "gridparse_config")
         | 
| 235 565 |  | 
| 566 | 
            +
                        delattr(ns, "___specified_args___")
         | 
| 567 | 
            +
             | 
| 236 568 | 
             
                    return vals
         | 
| 237 | 
            -
             | 
| 569 | 
            +
             | 
| 238 570 | 
             
                def _check_value(self, action, value):
         | 
| 239 571 | 
             
                    """Overwrites `_check_value` to support grid search with `None`s."""
         | 
| 240 572 | 
             
                    # converted value must be one of the choices (if specified)
         | 
| @@ -243,7 +575,7 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 243 575 | 
             
                    ):  # allows value to be None without error
         | 
| 244 576 | 
             
                        args = {
         | 
| 245 577 | 
             
                            "value": value,
         | 
| 246 | 
            -
                            "choices": ", ".join(map(repr, action.choices))
         | 
| 578 | 
            +
                            "choices": ", ".join(map(repr, action.choices)),
         | 
| 247 579 | 
             
                        }
         | 
| 248 580 | 
             
                        msg = argparse._(
         | 
| 249 581 | 
             
                            "invalid choice: %(value)r (choose from %(choices)s)"
         | 
| @@ -263,12 +595,12 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 263 595 | 
             
                        default == arg_string or arg_string is None
         | 
| 264 596 | 
             
                    ):
         | 
| 265 597 | 
             
                        return default
         | 
| 266 | 
            -
             | 
| 598 | 
            +
             | 
| 267 599 | 
             
                    # if arg_string is "args.X" value,
         | 
| 268 600 | 
             
                    # then set up value so that X is grabbed from the same namespace later
         | 
| 269 601 | 
             
                    if arg_string.startswith("args."):
         | 
| 270 602 | 
             
                        return arg_string
         | 
| 271 | 
            -
             | 
| 603 | 
            +
             | 
| 272 604 | 
             
                    # if arg_string is "_None_", then return None
         | 
| 273 605 | 
             
                    if (
         | 
| 274 606 | 
             
                        arg_string == "_None_"
         | 
| @@ -304,16 +636,18 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 304 636 | 
             
                @staticmethod
         | 
| 305 637 | 
             
                def _add_split_in_arg(arg: str, split: str) -> str:
         | 
| 306 638 | 
             
                    """Adds the `split` to the name of the argument `arg`."""
         | 
| 307 | 
            -
             | 
| 639 | 
            +
             | 
| 308 640 | 
             
                    if "_" in arg:
         | 
| 309 | 
            -
             | 
| 641 | 
            +
                        # if the user uses "_" as a delimiter, we use that
         | 
| 310 642 | 
             
                        delim = "_"
         | 
| 311 643 | 
             
                    else:
         | 
| 312 | 
            -
             | 
| 644 | 
            +
                        # otherwise, we use "-" (no necessary to check for it, e.g., could be CamelCase)
         | 
| 313 645 | 
             
                        delim = "-"
         | 
| 314 646 | 
             
                    return split + delim + arg
         | 
| 315 647 |  | 
| 316 | 
            -
                def add_argument( | 
| 648 | 
            +
                def add_argument(
         | 
| 649 | 
            +
                    self, *args, **kwargs
         | 
| 650 | 
            +
                ) -> Union[argparse.Action, List[argparse.Action]]:
         | 
| 317 651 | 
             
                    """Augments `add_argument` to support grid search.
         | 
| 318 652 | 
             
                    For parameters that are searchable, provide specification
         | 
| 319 653 | 
             
                    for a single value, and set the new argument `searchable`
         | 
| @@ -346,10 +680,14 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 346 680 | 
             
                                while cp_args[0][i] in self.prefix_chars:
         | 
| 347 681 | 
             
                                    i += 1
         | 
| 348 682 |  | 
| 349 | 
            -
                                cp_args[0] = cp_args[0][:i] + self._add_split_in_arg( | 
| 683 | 
            +
                                cp_args[0] = cp_args[0][:i] + self._add_split_in_arg(
         | 
| 684 | 
            +
                                    cp_args[0][i:], split
         | 
| 685 | 
            +
                                )
         | 
| 350 686 |  | 
| 351 687 | 
             
                            else:
         | 
| 352 | 
            -
                                cp_kwargs["dest"] = self._add_split_in_arg( | 
| 688 | 
            +
                                cp_kwargs["dest"] = self._add_split_in_arg(
         | 
| 689 | 
            +
                                    cp_kwargs["dest"], split
         | 
| 690 | 
            +
                                )
         | 
| 353 691 |  | 
| 354 692 | 
             
                            actions.append(self.add_argument(*cp_args, **cp_kwargs))
         | 
| 355 693 |  | 
| @@ -388,7 +726,7 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 388 726 | 
             
                        self.subspaces = {}
         | 
| 389 727 | 
             
                        self.cnt = 0
         | 
| 390 728 | 
             
                        self.parent = parent
         | 
| 391 | 
            -
             | 
| 729 | 
            +
             | 
| 392 730 | 
             
                    def add_arg(self, arg: str):
         | 
| 393 731 | 
             
                        if arg == "{":
         | 
| 394 732 | 
             
                            new_subspace = GridArgumentParser.Subspace(self)
         | 
| @@ -401,7 +739,7 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 401 739 | 
             
                            self.args[self.cnt] = arg
         | 
| 402 740 | 
             
                            self.cnt += 1
         | 
| 403 741 | 
             
                            return self
         | 
| 404 | 
            -
             | 
| 742 | 
            +
             | 
| 405 743 | 
             
                    def parse_paths(self) -> List[List[str]]:
         | 
| 406 744 |  | 
| 407 745 | 
             
                        if not self.subspaces:
         | 
| @@ -419,9 +757,9 @@ class GridArgumentParser(_GridActionsContainer, argparse.ArgumentParser): | |
| 419 757 | 
             
                                this_subspace_args.append(self.args[i])
         | 
| 420 758 | 
             
                                for path in cumulative_args:
         | 
| 421 759 | 
             
                                    path.append(self.args[i])
         | 
| 422 | 
            -
             | 
| 760 | 
            +
             | 
| 423 761 | 
             
                        return cumulative_args
         | 
| 424 | 
            -
             | 
| 762 | 
            +
             | 
| 425 763 | 
             
                    def __repr__(self) -> str:
         | 
| 426 764 | 
             
                        repr = "Subspace("
         | 
| 427 765 | 
             
                        for i in range(self.cnt):
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            [project]
         | 
| 2 2 | 
             
            name = "gridparse"
         | 
| 3 | 
            -
            version = "1.5. | 
| 3 | 
            +
            version = "1.5.2"
         | 
| 4 4 | 
             
            description = "Grid search directly from argparse"
         | 
| 5 5 | 
             
            readme = "README.md"
         | 
| 6 6 | 
             
            requires-python = ">=3.7"
         | 
| @@ -31,7 +31,6 @@ classifiers = [ | |
| 31 31 | 
             
              "Programming Language :: Python :: 3 :: Only",
         | 
| 32 32 | 
             
            ]
         | 
| 33 33 |  | 
| 34 | 
            -
             | 
| 35 34 | 
             
            dependencies = [
         | 
| 36 35 | 
             
              "omegaconf",
         | 
| 37 36 | 
             
            ]
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |