This subclass of `argparse.ArgumentParser` uses type hints on dataclasses to generate arguments. The class is designed to play well with the native argparse. In particular, you can add more (non-dataclass backed) arguments to the parser after initialization and you'll get the output ba
| 109 | |
| 110 | |
| 111 | class HfArgumentParser(ArgumentParser): |
| 112 | """ |
| 113 | This subclass of `argparse.ArgumentParser` uses type hints on dataclasses to generate arguments. |
| 114 | |
| 115 | The class is designed to play well with the native argparse. In particular, you can add more (non-dataclass backed) |
| 116 | arguments to the parser after initialization and you'll get the output back after parsing as an additional |
| 117 | namespace. Optional: To create sub argument groups use the `_argument_group_name` attribute in the dataclass. |
| 118 | |
| 119 | Args: |
| 120 | dataclass_types (`DataClassType` or `Iterable[DataClassType]`, *optional*): |
| 121 | Dataclass type, or list of dataclass types for which we will "fill" instances with the parsed args. |
| 122 | kwargs (`dict[str, Any]`, *optional*): |
| 123 | Passed to `argparse.ArgumentParser()` in the regular way. |
| 124 | """ |
| 125 | |
| 126 | dataclass_types: Iterable[DataClassType] |
| 127 | |
| 128 | def __init__(self, dataclass_types: DataClassType | Iterable[DataClassType] | None = None, **kwargs): |
| 129 | # Make sure dataclass_types is an iterable |
| 130 | if dataclass_types is None: |
| 131 | dataclass_types = [] |
| 132 | elif not isinstance(dataclass_types, Iterable): |
| 133 | dataclass_types = [dataclass_types] |
| 134 | |
| 135 | # To make the default appear when using --help |
| 136 | if "formatter_class" not in kwargs: |
| 137 | kwargs["formatter_class"] = ArgumentDefaultsHelpFormatter |
| 138 | super().__init__(**kwargs) |
| 139 | if dataclasses.is_dataclass(dataclass_types): |
| 140 | dataclass_types = [dataclass_types] |
| 141 | self.dataclass_types = list(dataclass_types) |
| 142 | for dtype in self.dataclass_types: |
| 143 | self._add_dataclass_arguments(dtype) |
| 144 | |
| 145 | @staticmethod |
| 146 | def _parse_dataclass_field(parser: ArgumentParser, field: dataclasses.Field): |
| 147 | # Long-option strings are conventionlly separated by hyphens rather |
| 148 | # than underscores, e.g., "--long-format" rather than "--long_format". |
| 149 | # Argparse converts hyphens to underscores so that the destination |
| 150 | # string is a valid attribute name. Hf_argparser should do the same. |
| 151 | long_options = [f"--{field.name}"] |
| 152 | if "_" in field.name: |
| 153 | long_options.append(f"--{field.name.replace('_', '-')}") |
| 154 | |
| 155 | kwargs = field.metadata.copy() |
| 156 | # field.metadata is not used at all by Data Classes, |
| 157 | # it is provided as a third-party extension mechanism. |
| 158 | if isinstance(field.type, str): |
| 159 | raise RuntimeError( |
| 160 | "Unresolved type detected, which should have been done with the help of " |
| 161 | "`typing.get_type_hints` method by default" |
| 162 | ) |
| 163 | |
| 164 | aliases = kwargs.pop("aliases", []) |
| 165 | if isinstance(aliases, str): |
| 166 | aliases = [aliases] |
| 167 | |
| 168 | origin_type = getattr(field.type, "__origin__", field.type) |
no outgoing calls