We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Feature request: Show command line argument defaults
# 🚀 Feature request

When running with `--help`, show the default values for command line arguments.

## Motivation

There are dozens of command line arguments. When I'm trying to figure out how to run a script, I often want to know what value is being used when I don't specify it. But running with `--help` doesn't show the default values unless it's explicitly written in the description (which is only for three of them for the example script I'm using).

For example, `--evaluation_strategy`

```
  --evaluation_strategy {no,steps,epoch}
                        The evaluation strategy to use.
```

This ends up being a bit of a frustrating user experience. The two ways I currently use to find the value are:

1. Run the script again without `--help` and log all the arguments (done in the examples). This shows the assigned value, which will be the default if not passed. However, it doesn't show the description of what it does.

2. Go to the documentation. This will show the default value and a more thorough description, but requires opening a web browser and Googling to find the right page.

In other Python projects, I use the `argparse.ArgumentDefaultsHelpFormatter`, which automatically displays default values in the `--help` message along with their descriptions.

```python
parser = argparse.ArgumentParser(
    formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
```

I wonder whether the Huggingface arguments could support the same feature?

Many thanks for considering this!

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/transformers/hf_argparser.py`
Content:
```
1 # Copyright 2020 The HuggingFace Team. All rights reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import dataclasses
16 import json
17 import re
18 import sys
19 from argparse import ArgumentParser, ArgumentTypeError
20 from enum import Enum
21 from pathlib import Path
22 from typing import Any, Iterable, List, NewType, Optional, Tuple, Union
23 
24 
25 DataClass = NewType("DataClass", Any)
26 DataClassType = NewType("DataClassType", Any)
27 
28 
29 # From https://stackoverflow.com/questions/15008758/parsing-boolean-values-with-argparse
30 def string_to_bool(v):
31     if isinstance(v, bool):
32         return v
33     if v.lower() in ("yes", "true", "t", "y", "1"):
34         return True
35     elif v.lower() in ("no", "false", "f", "n", "0"):
36         return False
37     else:
38         raise ArgumentTypeError(
39             f"Truthy value expected: got {v} but expected one of yes/no, true/false, t/f, y/n, 1/0 (case insensitive)."
40         )
41 
42 
43 class HfArgumentParser(ArgumentParser):
44     """
45     This subclass of `argparse.ArgumentParser` uses type hints on dataclasses to generate arguments.
46 
47     The class is designed to play well with the native argparse. In particular, you can add more (non-dataclass backed)
48     arguments to the parser after initialization and you'll get the output back after parsing as an additional
49     namespace. Optional: To create sub argument groups use the `_argument_group_name` attribute in the dataclass.
50     """
51 
52     dataclass_types: Iterable[DataClassType]
53 
54     def __init__(self, dataclass_types: Union[DataClassType, Iterable[DataClassType]], **kwargs):
55         """
56         Args:
57             dataclass_types:
58                 Dataclass type, or list of dataclass types for which we will "fill" instances with the parsed args.
59             kwargs:
60                 (Optional) Passed to `argparse.ArgumentParser()` in the regular way.
61         """
62         super().__init__(**kwargs)
63         if dataclasses.is_dataclass(dataclass_types):
64             dataclass_types = [dataclass_types]
65         self.dataclass_types = dataclass_types
66         for dtype in self.dataclass_types:
67             self._add_dataclass_arguments(dtype)
68 
69     def _add_dataclass_arguments(self, dtype: DataClassType):
70         if hasattr(dtype, "_argument_group_name"):
71             parser = self.add_argument_group(dtype._argument_group_name)
72         else:
73             parser = self
74         for field in dataclasses.fields(dtype):
75             if not field.init:
76                 continue
77             field_name = f"--{field.name}"
78             kwargs = field.metadata.copy()
79             # field.metadata is not used at all by Data Classes,
80             # it is provided as a third-party extension mechanism.
81             if isinstance(field.type, str):
82                 raise ImportError(
83                     "This implementation is not compatible with Postponed Evaluation of Annotations (PEP 563),"
84                     "which can be opted in from Python 3.7 with `from __future__ import annotations`."
85                     "We will add compatibility when Python 3.9 is released."
86                 )
87             typestring = str(field.type)
88             for prim_type in (int, float, str):
89                 for collection in (List,):
90                     if (
91                         typestring == f"typing.Union[{collection[prim_type]}, NoneType]"
92                         or typestring == f"typing.Optional[{collection[prim_type]}]"
93                     ):
94                         field.type = collection[prim_type]
95                 if (
96                     typestring == f"typing.Union[{prim_type.__name__}, NoneType]"
97                     or typestring == f"typing.Optional[{prim_type.__name__}]"
98                 ):
99                     field.type = prim_type
100 
101             if isinstance(field.type, type) and issubclass(field.type, Enum):
102                 kwargs["choices"] = [x.value for x in field.type]
103                 kwargs["type"] = type(kwargs["choices"][0])
104                 if field.default is not dataclasses.MISSING:
105                     kwargs["default"] = field.default
106                 else:
107                     kwargs["required"] = True
108             elif field.type is bool or field.type == Optional[bool]:
109                 if field.default is True:
110                     parser.add_argument(f"--no_{field.name}", action="store_false", dest=field.name, **kwargs)
111 
112                 # Hack because type=bool in argparse does not behave as we want.
113                 kwargs["type"] = string_to_bool
114                 if field.type is bool or (field.default is not None and field.default is not dataclasses.MISSING):
115                     # Default value is False if we have no default when of type bool.
116                     default = False if field.default is dataclasses.MISSING else field.default
117                     # This is the value that will get picked if we don't include --field_name in any way
118                     kwargs["default"] = default
119                     # This tells argparse we accept 0 or 1 value after --field_name
120                     kwargs["nargs"] = "?"
121                     # This is the value that will get picked if we do --field_name (without value)
122                     kwargs["const"] = True
123             elif (
124                 hasattr(field.type, "__origin__") and re.search(r"^typing\.List\[(.*)\]$", str(field.type)) is not None
125             ):
126                 kwargs["nargs"] = "+"
127                 kwargs["type"] = field.type.__args__[0]
128                 assert all(
129                     x == kwargs["type"] for x in field.type.__args__
130                 ), f"{field.name} cannot be a List of mixed types"
131                 if field.default_factory is not dataclasses.MISSING:
132                     kwargs["default"] = field.default_factory()
133                 elif field.default is dataclasses.MISSING:
134                     kwargs["required"] = True
135             else:
136                 kwargs["type"] = field.type
137                 if field.default is not dataclasses.MISSING:
138                     kwargs["default"] = field.default
139                 elif field.default_factory is not dataclasses.MISSING:
140                     kwargs["default"] = field.default_factory()
141                 else:
142                     kwargs["required"] = True
143             parser.add_argument(field_name, **kwargs)
144 
145     def parse_args_into_dataclasses(
146         self, args=None, return_remaining_strings=False, look_for_args_file=True, args_filename=None
147     ) -> Tuple[DataClass, ...]:
148         """
149         Parse command-line args into instances of the specified dataclass types.
150 
151         This relies on argparse's `ArgumentParser.parse_known_args`. See the doc at:
152         docs.python.org/3.7/library/argparse.html#argparse.ArgumentParser.parse_args
153 
154         Args:
155             args:
156                 List of strings to parse. The default is taken from sys.argv. (same as argparse.ArgumentParser)
157             return_remaining_strings:
158                 If true, also return a list of remaining argument strings.
159             look_for_args_file:
160                 If true, will look for a ".args" file with the same base name as the entry point script for this
161                 process, and will append its potential content to the command line args.
162             args_filename:
163                 If not None, will uses this file instead of the ".args" file specified in the previous argument.
164 
165         Returns:
166             Tuple consisting of:
167 
168                 - the dataclass instances in the same order as they were passed to the initializer.abspath
169                 - if applicable, an additional namespace for more (non-dataclass backed) arguments added to the parser
170                   after initialization.
171                 - The potential list of remaining argument strings. (same as argparse.ArgumentParser.parse_known_args)
172         """
173         if args_filename or (look_for_args_file and len(sys.argv)):
174             if args_filename:
175                 args_file = Path(args_filename)
176             else:
177                 args_file = Path(sys.argv[0]).with_suffix(".args")
178 
179             if args_file.exists():
180                 fargs = args_file.read_text().split()
181                 args = fargs + args if args is not None else fargs + sys.argv[1:]
182                 # in case of duplicate arguments the first one has precedence
183                 # so we append rather than prepend.
184         namespace, remaining_args = self.parse_known_args(args=args)
185         outputs = []
186         for dtype in self.dataclass_types:
187             keys = {f.name for f in dataclasses.fields(dtype) if f.init}
188             inputs = {k: v for k, v in vars(namespace).items() if k in keys}
189             for k in keys:
190                 delattr(namespace, k)
191             obj = dtype(**inputs)
192             outputs.append(obj)
193         if len(namespace.__dict__) > 0:
194             # additional namespace.
195             outputs.append(namespace)
196         if return_remaining_strings:
197             return (*outputs, remaining_args)
198         else:
199             if remaining_args:
200                 raise ValueError(f"Some specified arguments are not used by the HfArgumentParser: {remaining_args}")
201 
202             return (*outputs,)
203 
204     def parse_json_file(self, json_file: str) -> Tuple[DataClass, ...]:
205         """
206         Alternative helper method that does not use `argparse` at all, instead loading a json file and populating the
207         dataclass types.
208         """
209         data = json.loads(Path(json_file).read_text())
210         outputs = []
211         for dtype in self.dataclass_types:
212             keys = {f.name for f in dataclasses.fields(dtype) if f.init}
213             inputs = {k: v for k, v in data.items() if k in keys}
214             obj = dtype(**inputs)
215             outputs.append(obj)
216         return (*outputs,)
217 
218     def parse_dict(self, args: dict) -> Tuple[DataClass, ...]:
219         """
220         Alternative helper method that does not use `argparse` at all, instead uses a dict and populating the dataclass
221         types.
222         """
223         outputs = []
224         for dtype in self.dataclass_types:
225             keys = {f.name for f in dataclasses.fields(dtype) if f.init}
226             inputs = {k: v for k, v in args.items() if k in keys}
227             obj = dtype(**inputs)
228             outputs.append(obj)
229         return (*outputs,)
230
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/transformers/hf_argparser.py b/src/transformers/hf_argparser.py
--- a/src/transformers/hf_argparser.py
+++ b/src/transformers/hf_argparser.py
@@ -16,7 +16,7 @@
 import json
 import re
 import sys
-from argparse import ArgumentParser, ArgumentTypeError
+from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser, ArgumentTypeError
 from enum import Enum
 from pathlib import Path
 from typing import Any, Iterable, List, NewType, Optional, Tuple, Union
@@ -59,6 +59,9 @@
             kwargs:
                 (Optional) Passed to `argparse.ArgumentParser()` in the regular way.
         """
+        # To make the default appear when using --help
+        if "formatter_class" not in kwargs:
+            kwargs["formatter_class"] = ArgumentDefaultsHelpFormatter
         super().__init__(**kwargs)
         if dataclasses.is_dataclass(dataclass_types):
             dataclass_types = [dataclass_types]

{"golden_diff": "diff --git a/src/transformers/hf_argparser.py b/src/transformers/hf_argparser.py\n--- a/src/transformers/hf_argparser.py\n+++ b/src/transformers/hf_argparser.py\n@@ -16,7 +16,7 @@\n import json\n import re\n import sys\n-from argparse import ArgumentParser, ArgumentTypeError\n+from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser, ArgumentTypeError\n from enum import Enum\n from pathlib import Path\n from typing import Any, Iterable, List, NewType, Optional, Tuple, Union\n@@ -59,6 +59,9 @@\n             kwargs:\n                 (Optional) Passed to `argparse.ArgumentParser()` in the regular way.\n         \"\"\"\n+        # To make the default appear when using --help\n+        if \"formatter_class\" not in kwargs:\n+            kwargs[\"formatter_class\"] = ArgumentDefaultsHelpFormatter\n         super().__init__(**kwargs)\n         if dataclasses.is_dataclass(dataclass_types):\n             dataclass_types = [dataclass_types]\n", "issue": "Feature request: Show command line argument defaults\n# \ud83d\ude80 Feature request\r\n\r\nWhen running with `--help`, show the default values for command line arguments.\r\n\r\n## Motivation\r\n\r\nThere are dozens of command line arguments. When I'm trying to figure out how to run a script, I often want to know what value is being used when I don't specify it. But running with `--help` doesn't show the default values unless it's explicitly written in the description (which is only for three of them for the example script I'm using).\r\n\r\nFor example, `--evaluation_strategy`\r\n\r\n```\r\n  --evaluation_strategy {no,steps,epoch}\r\n                        The evaluation strategy to use.\r\n```\r\n\r\nThis ends up being a bit of a frustrating user experience. The two ways I currently use to find the value are:\r\n\r\n1. Run the script again without `--help` and log all the arguments (done in the examples). This shows the assigned value, which will be the default if not passed. However, it doesn't show the description of what it does.\r\n\r\n2. Go to the documentation. This will show the default value and a more thorough description, but requires opening a web browser and Googling to find the right page.\r\n\r\nIn other Python projects, I use the `argparse.ArgumentDefaultsHelpFormatter`, which automatically displays default values in the `--help` message along with their descriptions.\r\n\r\n```python\r\nparser = argparse.ArgumentParser(\r\n    formatter_class=argparse.ArgumentDefaultsHelpFormatter\r\n)\r\n```\r\n\r\nI wonder whether the Huggingface arguments could support the same feature?\r\n\r\nMany thanks for considering this!\n", "before_files": [{"content": "# Copyright 2020 The HuggingFace Team. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport dataclasses\nimport json\nimport re\nimport sys\nfrom argparse import ArgumentParser, ArgumentTypeError\nfrom enum import Enum\nfrom pathlib import Path\nfrom typing import Any, Iterable, List, NewType, Optional, Tuple, Union\n\n\nDataClass = NewType(\"DataClass\", Any)\nDataClassType = NewType(\"DataClassType\", Any)\n\n\n# From https://stackoverflow.com/questions/15008758/parsing-boolean-values-with-argparse\ndef string_to_bool(v):\n    if isinstance(v, bool):\n        return v\n    if v.lower() in (\"yes\", \"true\", \"t\", \"y\", \"1\"):\n        return True\n    elif v.lower() in (\"no\", \"false\", \"f\", \"n\", \"0\"):\n        return False\n    else:\n        raise ArgumentTypeError(\n            f\"Truthy value expected: got {v} but expected one of yes/no, true/false, t/f, y/n, 1/0 (case insensitive).\"\n        )\n\n\nclass HfArgumentParser(ArgumentParser):\n    \"\"\"\n    This subclass of `argparse.ArgumentParser` uses type hints on dataclasses to generate arguments.\n\n    The class is designed to play well with the native argparse. In particular, you can add more (non-dataclass backed)\n    arguments to the parser after initialization and you'll get the output back after parsing as an additional\n    namespace. Optional: To create sub argument groups use the `_argument_group_name` attribute in the dataclass.\n    \"\"\"\n\n    dataclass_types: Iterable[DataClassType]\n\n    def __init__(self, dataclass_types: Union[DataClassType, Iterable[DataClassType]], **kwargs):\n        \"\"\"\n        Args:\n            dataclass_types:\n                Dataclass type, or list of dataclass types for which we will \"fill\" instances with the parsed args.\n            kwargs:\n                (Optional) Passed to `argparse.ArgumentParser()` in the regular way.\n        \"\"\"\n        super().__init__(**kwargs)\n        if dataclasses.is_dataclass(dataclass_types):\n            dataclass_types = [dataclass_types]\n        self.dataclass_types = dataclass_types\n        for dtype in self.dataclass_types:\n            self._add_dataclass_arguments(dtype)\n\n    def _add_dataclass_arguments(self, dtype: DataClassType):\n        if hasattr(dtype, \"_argument_group_name\"):\n            parser = self.add_argument_group(dtype._argument_group_name)\n        else:\n            parser = self\n        for field in dataclasses.fields(dtype):\n            if not field.init:\n                continue\n            field_name = f\"--{field.name}\"\n            kwargs = field.metadata.copy()\n            # field.metadata is not used at all by Data Classes,\n            # it is provided as a third-party extension mechanism.\n            if isinstance(field.type, str):\n                raise ImportError(\n                    \"This implementation is not compatible with Postponed Evaluation of Annotations (PEP 563),\"\n                    \"which can be opted in from Python 3.7 with `from __future__ import annotations`.\"\n                    \"We will add compatibility when Python 3.9 is released.\"\n                )\n            typestring = str(field.type)\n            for prim_type in (int, float, str):\n                for collection in (List,):\n                    if (\n                        typestring == f\"typing.Union[{collection[prim_type]}, NoneType]\"\n                        or typestring == f\"typing.Optional[{collection[prim_type]}]\"\n                    ):\n                        field.type = collection[prim_type]\n                if (\n                    typestring == f\"typing.Union[{prim_type.__name__}, NoneType]\"\n                    or typestring == f\"typing.Optional[{prim_type.__name__}]\"\n                ):\n                    field.type = prim_type\n\n            if isinstance(field.type, type) and issubclass(field.type, Enum):\n                kwargs[\"choices\"] = [x.value for x in field.type]\n                kwargs[\"type\"] = type(kwargs[\"choices\"][0])\n                if field.default is not dataclasses.MISSING:\n                    kwargs[\"default\"] = field.default\n                else:\n                    kwargs[\"required\"] = True\n            elif field.type is bool or field.type == Optional[bool]:\n                if field.default is True:\n                    parser.add_argument(f\"--no_{field.name}\", action=\"store_false\", dest=field.name, **kwargs)\n\n                # Hack because type=bool in argparse does not behave as we want.\n                kwargs[\"type\"] = string_to_bool\n                if field.type is bool or (field.default is not None and field.default is not dataclasses.MISSING):\n                    # Default value is False if we have no default when of type bool.\n                    default = False if field.default is dataclasses.MISSING else field.default\n                    # This is the value that will get picked if we don't include --field_name in any way\n                    kwargs[\"default\"] = default\n                    # This tells argparse we accept 0 or 1 value after --field_name\n                    kwargs[\"nargs\"] = \"?\"\n                    # This is the value that will get picked if we do --field_name (without value)\n                    kwargs[\"const\"] = True\n            elif (\n                hasattr(field.type, \"__origin__\") and re.search(r\"^typing\\.List\\[(.*)\\]$\", str(field.type)) is not None\n            ):\n                kwargs[\"nargs\"] = \"+\"\n                kwargs[\"type\"] = field.type.__args__[0]\n                assert all(\n                    x == kwargs[\"type\"] for x in field.type.__args__\n                ), f\"{field.name} cannot be a List of mixed types\"\n                if field.default_factory is not dataclasses.MISSING:\n                    kwargs[\"default\"] = field.default_factory()\n                elif field.default is dataclasses.MISSING:\n                    kwargs[\"required\"] = True\n            else:\n                kwargs[\"type\"] = field.type\n                if field.default is not dataclasses.MISSING:\n                    kwargs[\"default\"] = field.default\n                elif field.default_factory is not dataclasses.MISSING:\n                    kwargs[\"default\"] = field.default_factory()\n                else:\n                    kwargs[\"required\"] = True\n            parser.add_argument(field_name, **kwargs)\n\n    def parse_args_into_dataclasses(\n        self, args=None, return_remaining_strings=False, look_for_args_file=True, args_filename=None\n    ) -> Tuple[DataClass, ...]:\n        \"\"\"\n        Parse command-line args into instances of the specified dataclass types.\n\n        This relies on argparse's `ArgumentParser.parse_known_args`. See the doc at:\n        docs.python.org/3.7/library/argparse.html#argparse.ArgumentParser.parse_args\n\n        Args:\n            args:\n                List of strings to parse. The default is taken from sys.argv. (same as argparse.ArgumentParser)\n            return_remaining_strings:\n                If true, also return a list of remaining argument strings.\n            look_for_args_file:\n                If true, will look for a \".args\" file with the same base name as the entry point script for this\n                process, and will append its potential content to the command line args.\n            args_filename:\n                If not None, will uses this file instead of the \".args\" file specified in the previous argument.\n\n        Returns:\n            Tuple consisting of:\n\n                - the dataclass instances in the same order as they were passed to the initializer.abspath\n                - if applicable, an additional namespace for more (non-dataclass backed) arguments added to the parser\n                  after initialization.\n                - The potential list of remaining argument strings. (same as argparse.ArgumentParser.parse_known_args)\n        \"\"\"\n        if args_filename or (look_for_args_file and len(sys.argv)):\n            if args_filename:\n                args_file = Path(args_filename)\n            else:\n                args_file = Path(sys.argv[0]).with_suffix(\".args\")\n\n            if args_file.exists():\n                fargs = args_file.read_text().split()\n                args = fargs + args if args is not None else fargs + sys.argv[1:]\n                # in case of duplicate arguments the first one has precedence\n                # so we append rather than prepend.\n        namespace, remaining_args = self.parse_known_args(args=args)\n        outputs = []\n        for dtype in self.dataclass_types:\n            keys = {f.name for f in dataclasses.fields(dtype) if f.init}\n            inputs = {k: v for k, v in vars(namespace).items() if k in keys}\n            for k in keys:\n                delattr(namespace, k)\n            obj = dtype(**inputs)\n            outputs.append(obj)\n        if len(namespace.__dict__) > 0:\n            # additional namespace.\n            outputs.append(namespace)\n        if return_remaining_strings:\n            return (*outputs, remaining_args)\n        else:\n            if remaining_args:\n                raise ValueError(f\"Some specified arguments are not used by the HfArgumentParser: {remaining_args}\")\n\n            return (*outputs,)\n\n    def parse_json_file(self, json_file: str) -> Tuple[DataClass, ...]:\n        \"\"\"\n        Alternative helper method that does not use `argparse` at all, instead loading a json file and populating the\n        dataclass types.\n        \"\"\"\n        data = json.loads(Path(json_file).read_text())\n        outputs = []\n        for dtype in self.dataclass_types:\n            keys = {f.name for f in dataclasses.fields(dtype) if f.init}\n            inputs = {k: v for k, v in data.items() if k in keys}\n            obj = dtype(**inputs)\n            outputs.append(obj)\n        return (*outputs,)\n\n    def parse_dict(self, args: dict) -> Tuple[DataClass, ...]:\n        \"\"\"\n        Alternative helper method that does not use `argparse` at all, instead uses a dict and populating the dataclass\n        types.\n        \"\"\"\n        outputs = []\n        for dtype in self.dataclass_types:\n            keys = {f.name for f in dataclasses.fields(dtype) if f.init}\n            inputs = {k: v for k, v in args.items() if k in keys}\n            obj = dtype(**inputs)\n            outputs.append(obj)\n        return (*outputs,)\n", "path": "src/transformers/hf_argparser.py"}], "after_files": [{"content": "# Copyright 2020 The HuggingFace Team. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport dataclasses\nimport json\nimport re\nimport sys\nfrom argparse import ArgumentDefaultsHelpFormatter, ArgumentParser, ArgumentTypeError\nfrom enum import Enum\nfrom pathlib import Path\nfrom typing import Any, Iterable, List, NewType, Optional, Tuple, Union\n\n\nDataClass = NewType(\"DataClass\", Any)\nDataClassType = NewType(\"DataClassType\", Any)\n\n\n# From https://stackoverflow.com/questions/15008758/parsing-boolean-values-with-argparse\ndef string_to_bool(v):\n    if isinstance(v, bool):\n        return v\n    if v.lower() in (\"yes\", \"true\", \"t\", \"y\", \"1\"):\n        return True\n    elif v.lower() in (\"no\", \"false\", \"f\", \"n\", \"0\"):\n        return False\n    else:\n        raise ArgumentTypeError(\n            f\"Truthy value expected: got {v} but expected one of yes/no, true/false, t/f, y/n, 1/0 (case insensitive).\"\n        )\n\n\nclass HfArgumentParser(ArgumentParser):\n    \"\"\"\n    This subclass of `argparse.ArgumentParser` uses type hints on dataclasses to generate arguments.\n\n    The class is designed to play well with the native argparse. In particular, you can add more (non-dataclass backed)\n    arguments to the parser after initialization and you'll get the output back after parsing as an additional\n    namespace. Optional: To create sub argument groups use the `_argument_group_name` attribute in the dataclass.\n    \"\"\"\n\n    dataclass_types: Iterable[DataClassType]\n\n    def __init__(self, dataclass_types: Union[DataClassType, Iterable[DataClassType]], **kwargs):\n        \"\"\"\n        Args:\n            dataclass_types:\n                Dataclass type, or list of dataclass types for which we will \"fill\" instances with the parsed args.\n            kwargs:\n                (Optional) Passed to `argparse.ArgumentParser()` in the regular way.\n        \"\"\"\n        # To make the default appear when using --help\n        if \"formatter_class\" not in kwargs:\n            kwargs[\"formatter_class\"] = ArgumentDefaultsHelpFormatter\n        super().__init__(**kwargs)\n        if dataclasses.is_dataclass(dataclass_types):\n            dataclass_types = [dataclass_types]\n        self.dataclass_types = dataclass_types\n        for dtype in self.dataclass_types:\n            self._add_dataclass_arguments(dtype)\n\n    def _add_dataclass_arguments(self, dtype: DataClassType):\n        if hasattr(dtype, \"_argument_group_name\"):\n            parser = self.add_argument_group(dtype._argument_group_name)\n        else:\n            parser = self\n        for field in dataclasses.fields(dtype):\n            if not field.init:\n                continue\n            field_name = f\"--{field.name}\"\n            kwargs = field.metadata.copy()\n            # field.metadata is not used at all by Data Classes,\n            # it is provided as a third-party extension mechanism.\n            if isinstance(field.type, str):\n                raise ImportError(\n                    \"This implementation is not compatible with Postponed Evaluation of Annotations (PEP 563),\"\n                    \"which can be opted in from Python 3.7 with `from __future__ import annotations`.\"\n                    \"We will add compatibility when Python 3.9 is released.\"\n                )\n            typestring = str(field.type)\n            for prim_type in (int, float, str):\n                for collection in (List,):\n                    if (\n                        typestring == f\"typing.Union[{collection[prim_type]}, NoneType]\"\n                        or typestring == f\"typing.Optional[{collection[prim_type]}]\"\n                    ):\n                        field.type = collection[prim_type]\n                if (\n                    typestring == f\"typing.Union[{prim_type.__name__}, NoneType]\"\n                    or typestring == f\"typing.Optional[{prim_type.__name__}]\"\n                ):\n                    field.type = prim_type\n\n            if isinstance(field.type, type) and issubclass(field.type, Enum):\n                kwargs[\"choices\"] = [x.value for x in field.type]\n                kwargs[\"type\"] = type(kwargs[\"choices\"][0])\n                if field.default is not dataclasses.MISSING:\n                    kwargs[\"default\"] = field.default\n                else:\n                    kwargs[\"required\"] = True\n            elif field.type is bool or field.type == Optional[bool]:\n                if field.default is True:\n                    parser.add_argument(f\"--no_{field.name}\", action=\"store_false\", dest=field.name, **kwargs)\n\n                # Hack because type=bool in argparse does not behave as we want.\n                kwargs[\"type\"] = string_to_bool\n                if field.type is bool or (field.default is not None and field.default is not dataclasses.MISSING):\n                    # Default value is False if we have no default when of type bool.\n                    default = False if field.default is dataclasses.MISSING else field.default\n                    # This is the value that will get picked if we don't include --field_name in any way\n                    kwargs[\"default\"] = default\n                    # This tells argparse we accept 0 or 1 value after --field_name\n                    kwargs[\"nargs\"] = \"?\"\n                    # This is the value that will get picked if we do --field_name (without value)\n                    kwargs[\"const\"] = True\n            elif (\n                hasattr(field.type, \"__origin__\") and re.search(r\"^typing\\.List\\[(.*)\\]$\", str(field.type)) is not None\n            ):\n                kwargs[\"nargs\"] = \"+\"\n                kwargs[\"type\"] = field.type.__args__[0]\n                assert all(\n                    x == kwargs[\"type\"] for x in field.type.__args__\n                ), f\"{field.name} cannot be a List of mixed types\"\n                if field.default_factory is not dataclasses.MISSING:\n                    kwargs[\"default\"] = field.default_factory()\n                elif field.default is dataclasses.MISSING:\n                    kwargs[\"required\"] = True\n            else:\n                kwargs[\"type\"] = field.type\n                if field.default is not dataclasses.MISSING:\n                    kwargs[\"default\"] = field.default\n                elif field.default_factory is not dataclasses.MISSING:\n                    kwargs[\"default\"] = field.default_factory()\n                else:\n                    kwargs[\"required\"] = True\n            parser.add_argument(field_name, **kwargs)\n\n    def parse_args_into_dataclasses(\n        self, args=None, return_remaining_strings=False, look_for_args_file=True, args_filename=None\n    ) -> Tuple[DataClass, ...]:\n        \"\"\"\n        Parse command-line args into instances of the specified dataclass types.\n\n        This relies on argparse's `ArgumentParser.parse_known_args`. See the doc at:\n        docs.python.org/3.7/library/argparse.html#argparse.ArgumentParser.parse_args\n\n        Args:\n            args:\n                List of strings to parse. The default is taken from sys.argv. (same as argparse.ArgumentParser)\n            return_remaining_strings:\n                If true, also return a list of remaining argument strings.\n            look_for_args_file:\n                If true, will look for a \".args\" file with the same base name as the entry point script for this\n                process, and will append its potential content to the command line args.\n            args_filename:\n                If not None, will uses this file instead of the \".args\" file specified in the previous argument.\n\n        Returns:\n            Tuple consisting of:\n\n                - the dataclass instances in the same order as they were passed to the initializer.abspath\n                - if applicable, an additional namespace for more (non-dataclass backed) arguments added to the parser\n                  after initialization.\n                - The potential list of remaining argument strings. (same as argparse.ArgumentParser.parse_known_args)\n        \"\"\"\n        if args_filename or (look_for_args_file and len(sys.argv)):\n            if args_filename:\n                args_file = Path(args_filename)\n            else:\n                args_file = Path(sys.argv[0]).with_suffix(\".args\")\n\n            if args_file.exists():\n                fargs = args_file.read_text().split()\n                args = fargs + args if args is not None else fargs + sys.argv[1:]\n                # in case of duplicate arguments the first one has precedence\n                # so we append rather than prepend.\n        namespace, remaining_args = self.parse_known_args(args=args)\n        outputs = []\n        for dtype in self.dataclass_types:\n            keys = {f.name for f in dataclasses.fields(dtype) if f.init}\n            inputs = {k: v for k, v in vars(namespace).items() if k in keys}\n            for k in keys:\n                delattr(namespace, k)\n            obj = dtype(**inputs)\n            outputs.append(obj)\n        if len(namespace.__dict__) > 0:\n            # additional namespace.\n            outputs.append(namespace)\n        if return_remaining_strings:\n            return (*outputs, remaining_args)\n        else:\n            if remaining_args:\n                raise ValueError(f\"Some specified arguments are not used by the HfArgumentParser: {remaining_args}\")\n\n            return (*outputs,)\n\n    def parse_json_file(self, json_file: str) -> Tuple[DataClass, ...]:\n        \"\"\"\n        Alternative helper method that does not use `argparse` at all, instead loading a json file and populating the\n        dataclass types.\n        \"\"\"\n        data = json.loads(Path(json_file).read_text())\n        outputs = []\n        for dtype in self.dataclass_types:\n            keys = {f.name for f in dataclasses.fields(dtype) if f.init}\n            inputs = {k: v for k, v in data.items() if k in keys}\n            obj = dtype(**inputs)\n            outputs.append(obj)\n        return (*outputs,)\n\n    def parse_dict(self, args: dict) -> Tuple[DataClass, ...]:\n        \"\"\"\n        Alternative helper method that does not use `argparse` at all, instead uses a dict and populating the dataclass\n        types.\n        \"\"\"\n        outputs = []\n        for dtype in self.dataclass_types:\n            keys = {f.name for f in dataclasses.fields(dtype) if f.init}\n            inputs = {k: v for k, v in args.items() if k in keys}\n            obj = dtype(**inputs)\n            outputs.append(obj)\n        return (*outputs,)\n", "path": "src/transformers/hf_argparser.py"}]}