We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Add --version flag to parlai command
**Is your feature request related to a problem? Please describe.**
Make parlai "super command" conform the unix idiom of a --version flag.

Usecase: A user switching between virtual environments or reading about the release of a new feature should be able to easily identify which version they have on their path.

**Describe the solution you'd like**
```bash
$ parlai --version
parlai version X.X.X
# Optionally any relevant install info (not probably not any)
# Optionally copyright/license info (up to the maintainers whether you want this here or not)
```

**Describe alternatives you've considered**
```bash
$ python -c "import parlai; print(parlai.__version__)"
0.9.2
```
A little less natural

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `parlai/core/script.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 # Copyright (c) Facebook, Inc. and its affiliates.
4 # This source code is licensed under the MIT license found in the
5 # LICENSE file in the root directory of this source tree.
6 
7 
8 """
9 The general ParlAI Script interface.
10 
11 An abstract class to help standardize the call to ParlAI scripts, enabling them to be
12 completed easily.
13 
14 Also contains helper classes for loading scripts, etc.
15 """
16 
17 import io
18 import argparse
19 from typing import List, Optional, Dict, Any
20 from parlai.core.opt import Opt
21 from parlai.core.params import ParlaiParser, CustomHelpFormatter
22 from abc import abstractmethod
23 import importlib
24 import pkgutil
25 import parlai.scripts
26 import parlai.utils.logging as logging
27 from parlai.core.loader import register_script, SCRIPT_REGISTRY  # noqa: F401
28 
29 
30 def setup_script_registry():
31     """
32     Loads the scripts so that @register_script is hit for all.
33     """
34     for module in pkgutil.iter_modules(parlai.scripts.__path__, 'parlai.scripts.'):
35         importlib.import_module(module.name)
36 
37 
38 class ParlaiScript(object):
39     """
40     A ParlAI script is a standardized form of access.
41     """
42 
43     parser: ParlaiParser
44 
45     @classmethod
46     @abstractmethod
47     def setup_args(cls) -> ParlaiParser:
48         """
49         Create the parser with args.
50         """
51         # we want to later deprecate this for add_cmdline_args
52         pass
53 
54     def __init__(self, opt: Opt):
55         self.opt = opt
56 
57     @abstractmethod
58     def run(self):
59         """
60         The main method.
61 
62         Must be implemented by the script writer.
63         """
64         raise NotImplementedError()
65 
66     @classmethod
67     def _run_kwargs(cls, kwargs: Dict[str, Any]):
68         """
69         Construct and run the script using kwargs, pseudo-parsing them.
70         """
71         parser = cls.setup_args()
72         opt = parser.parse_kwargs(**kwargs)
73         return cls._run_from_parser_and_opt(opt, parser)
74 
75     @classmethod
76     def _run_args(cls, args: Optional[List[str]] = None):
77         """
78         Construct and run the script using args, defaulting to getting from CLI.
79         """
80         parser = cls.setup_args()
81         opt = parser.parse_args(args=args)
82         return cls._run_from_parser_and_opt(opt, parser)
83 
84     @classmethod
85     def _run_from_parser_and_opt(cls, opt: Opt, parser: ParlaiParser):
86         script = cls(opt)
87         script.parser = parser
88         return script.run()
89 
90     @classmethod
91     def main(cls, *args, **kwargs):
92         """
93         Run the program, possibly with some given args.
94 
95         You may provide command line args in the form of strings, or
96         options. For example:
97 
98         >>> MyScript.main(['--task', 'convai2'])
99         >>> MyScript.main(task='convai2')
100 
101         You may not combine both args and kwargs.
102         """
103         assert not (bool(args) and bool(kwargs))
104         if args:
105             return cls._run_args(args)
106         elif kwargs:
107             return cls._run_kwargs(kwargs)
108         else:
109             return cls._run_args(None)
110 
111     @classmethod
112     def help(cls, **kwargs):
113         f = io.StringIO()
114         parser = cls.setup_args()
115         parser.prog = cls.__name__
116         parser.add_extra_args(parser._kwargs_to_str_args(**kwargs))
117         parser.print_help(f)
118         return f.getvalue()
119 
120 
121 class _SupercommandParser(ParlaiParser):
122     """
123     Specialty ParlAI parser used for the supercommand.
124 
125     Contains some special behavior.
126     """
127 
128     def __init__(self, *args, **kwargs):
129         from parlai.utils.strings import colorize
130 
131         logo = ""
132         logo += colorize('       _', 'red') + "\n"
133         logo += colorize('      /', 'red') + colorize('"', 'brightblack')
134         logo += colorize(")", "yellow") + "\n"
135         logo += colorize('     //', 'red') + colorize(')', 'yellow') + '\n'
136         logo += colorize('  ==', 'green')
137         logo += colorize("/", 'blue') + colorize('/', 'red') + colorize("'", 'yellow')
138         logo += colorize("===", 'green') + " ParlAI\n"
139         logo += colorize("   /", 'blue')
140         kwargs['description'] = logo
141         return super().__init__(*args, **kwargs)
142 
143     def add_extra_args(self, args):
144         sa = [a for a in self._actions if isinstance(a, argparse._SubParsersAction)]
145         assert len(sa) == 1
146         sa = sa[0]
147         for _, v in sa.choices.items():
148             v.add_extra_args(args)
149 
150     def add_subparsers(self, **kwargs):
151         return super().add_subparsers(**kwargs)
152 
153     def _unsuppress_hidden(self):
154         """
155         Restore the help messages of hidden commands.
156         """
157 
158         spa = [a for a in self._actions if isinstance(a, argparse._SubParsersAction)]
159         assert len(spa) == 1
160         spa = spa[0]
161         for choices_action in spa._choices_actions:
162             dest = choices_action.dest
163             if choices_action.help == argparse.SUPPRESS:
164                 choices_action.help = spa.choices[dest].description
165 
166     def print_helpall(self):
167         self._unsuppress_hidden()
168         self.print_help()
169 
170 
171 class _SubcommandParser(ParlaiParser):
172     """
173     ParlaiParser which always sets add_parlai_args and add_model_args to False.
174 
175     Used in the superscript to initialize just the args for that command.
176     """
177 
178     def __init__(self, **kwargs):
179         kwargs['add_parlai_args'] = False
180         kwargs['add_model_args'] = False
181         assert 'description' in kwargs, 'Must supply description'
182         return super().__init__(**kwargs)
183 
184     def parse_known_args(self, args=None, namespace=None, nohelp=False):
185         if not nohelp:
186             self.add_extra_args(args)
187         return super().parse_known_args(args, namespace, nohelp)
188 
189 
190 def _SuperscriptHelpFormatter(**kwargs):
191     kwargs['width'] = 100
192     kwargs['max_help_position'] = 9999
193 
194     return CustomHelpFormatter(**kwargs)
195 
196 
197 def superscript_main(args=None):
198     """
199     Superscript is a loader for all the other scripts.
200     """
201     setup_script_registry()
202 
203     parser = _SupercommandParser(
204         False, False, formatter_class=_SuperscriptHelpFormatter
205     )
206     parser.add_argument(
207         '--helpall',
208         action='helpall',
209         help='show all commands, including advanced ones.',
210     )
211     parser.set_defaults(super_command=None)
212     subparsers = parser.add_subparsers(
213         parser_class=_SubcommandParser, title="Commands", metavar="COMMAND"
214     )
215     hparser = subparsers.add_parser(
216         'help',
217         aliases=['h'],
218         help=argparse.SUPPRESS,
219         description="List the main commands",
220     )
221     hparser.set_defaults(super_command='help')
222     hparser = subparsers.add_parser(
223         'helpall',
224         help=argparse.SUPPRESS,
225         description="List all commands, including advanced ones.",
226     )
227     hparser.set_defaults(super_command='helpall')
228 
229     # build the supercommand
230     for script_name, registration in SCRIPT_REGISTRY.items():
231         logging.verbose(f"Discovered command {script_name}")
232         script_parser = registration.klass.setup_args()
233         if script_parser is None:
234             # user didn't bother defining command line args. let's just fill
235             # in for them
236             script_parser = ParlaiParser(False, False)
237         help_ = argparse.SUPPRESS if registration.hidden else script_parser.description
238         subparser = subparsers.add_parser(
239             script_name,
240             aliases=registration.aliases,
241             help=help_,
242             description=script_parser.description,
243             formatter_class=CustomHelpFormatter,
244         )
245         subparser.set_defaults(
246             # carries the name of the full command so we know what to execute
247             super_command=script_name,
248             # used in ParlAI parser to find CLI options set by user
249             _subparser=subparser,
250         )
251         subparser.set_defaults(**script_parser._defaults)
252         for action in script_parser._actions:
253             subparser._add_action(action)
254         for action_group in script_parser._action_groups:
255             subparser._action_groups.append(action_group)
256 
257     try:
258         import argcomplete
259 
260         argcomplete.autocomplete(parser)
261     except ModuleNotFoundError:
262         pass
263 
264     opt = parser.parse_args(args)
265     cmd = opt.pop('super_command')
266     if cmd == 'helpall':
267         parser.print_helpall()
268     elif cmd == 'help' or cmd is None:
269         parser.print_help()
270     elif cmd is not None:
271         return SCRIPT_REGISTRY[cmd].klass._run_from_parser_and_opt(opt, parser)
272
```
--- 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/parlai/core/script.py b/parlai/core/script.py
--- a/parlai/core/script.py
+++ b/parlai/core/script.py
@@ -17,6 +17,7 @@
 import io
 import argparse
 from typing import List, Optional, Dict, Any
+import parlai
 from parlai.core.opt import Opt
 from parlai.core.params import ParlaiParser, CustomHelpFormatter
 from abc import abstractmethod
@@ -206,7 +207,13 @@
     parser.add_argument(
         '--helpall',
         action='helpall',
-        help='show all commands, including advanced ones.',
+        help='List all commands, including advanced ones.',
+    )
+    parser.add_argument(
+        '--version',
+        action='version',
+        version=get_version_string(),
+        help='Prints version info and exit.',
     )
     parser.set_defaults(super_command=None)
     subparsers = parser.add_subparsers(
@@ -216,13 +223,13 @@
         'help',
         aliases=['h'],
         help=argparse.SUPPRESS,
-        description="List the main commands",
+        description='List the main commands.',
     )
     hparser.set_defaults(super_command='help')
     hparser = subparsers.add_parser(
         'helpall',
         help=argparse.SUPPRESS,
-        description="List all commands, including advanced ones.",
+        description='List all commands, including advanced ones.',
     )
     hparser.set_defaults(super_command='helpall')
 
@@ -265,7 +272,13 @@
     cmd = opt.pop('super_command')
     if cmd == 'helpall':
         parser.print_helpall()
+    elif cmd == 'versioninfo':
+        exit(0)
     elif cmd == 'help' or cmd is None:
         parser.print_help()
     elif cmd is not None:
         return SCRIPT_REGISTRY[cmd].klass._run_from_parser_and_opt(opt, parser)
+
+
+def get_version_string() -> str:
+    return f"ParlAI version {parlai.__version__}"

{"golden_diff": "diff --git a/parlai/core/script.py b/parlai/core/script.py\n--- a/parlai/core/script.py\n+++ b/parlai/core/script.py\n@@ -17,6 +17,7 @@\n import io\n import argparse\n from typing import List, Optional, Dict, Any\n+import parlai\n from parlai.core.opt import Opt\n from parlai.core.params import ParlaiParser, CustomHelpFormatter\n from abc import abstractmethod\n@@ -206,7 +207,13 @@\n     parser.add_argument(\n         '--helpall',\n         action='helpall',\n-        help='show all commands, including advanced ones.',\n+        help='List all commands, including advanced ones.',\n+    )\n+    parser.add_argument(\n+        '--version',\n+        action='version',\n+        version=get_version_string(),\n+        help='Prints version info and exit.',\n     )\n     parser.set_defaults(super_command=None)\n     subparsers = parser.add_subparsers(\n@@ -216,13 +223,13 @@\n         'help',\n         aliases=['h'],\n         help=argparse.SUPPRESS,\n-        description=\"List the main commands\",\n+        description='List the main commands.',\n     )\n     hparser.set_defaults(super_command='help')\n     hparser = subparsers.add_parser(\n         'helpall',\n         help=argparse.SUPPRESS,\n-        description=\"List all commands, including advanced ones.\",\n+        description='List all commands, including advanced ones.',\n     )\n     hparser.set_defaults(super_command='helpall')\n \n@@ -265,7 +272,13 @@\n     cmd = opt.pop('super_command')\n     if cmd == 'helpall':\n         parser.print_helpall()\n+    elif cmd == 'versioninfo':\n+        exit(0)\n     elif cmd == 'help' or cmd is None:\n         parser.print_help()\n     elif cmd is not None:\n         return SCRIPT_REGISTRY[cmd].klass._run_from_parser_and_opt(opt, parser)\n+\n+\n+def get_version_string() -> str:\n+    return f\"ParlAI version {parlai.__version__}\"\n", "issue": "Add --version flag to parlai command\n**Is your feature request related to a problem? Please describe.**\r\nMake parlai \"super command\" conform the unix idiom of a --version flag.\r\n\r\nUsecase: A user switching between virtual environments or reading about the release of a new feature should be able to easily identify which version they have on their path.\r\n\r\n**Describe the solution you'd like**\r\n```bash\r\n$ parlai --version\r\nparlai version X.X.X\r\n# Optionally any relevant install info (not probably not any)\r\n# Optionally copyright/license info (up to the maintainers whether you want this here or not)\r\n```\r\n\r\n**Describe alternatives you've considered**\r\n```bash\r\n$ python -c \"import parlai; print(parlai.__version__)\"\r\n0.9.2\r\n```\r\nA little less natural\n", "before_files": [{"content": "#!/usr/bin/env python3\n\n# Copyright (c) Facebook, Inc. and its affiliates.\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\n\"\"\"\nThe general ParlAI Script interface.\n\nAn abstract class to help standardize the call to ParlAI scripts, enabling them to be\ncompleted easily.\n\nAlso contains helper classes for loading scripts, etc.\n\"\"\"\n\nimport io\nimport argparse\nfrom typing import List, Optional, Dict, Any\nfrom parlai.core.opt import Opt\nfrom parlai.core.params import ParlaiParser, CustomHelpFormatter\nfrom abc import abstractmethod\nimport importlib\nimport pkgutil\nimport parlai.scripts\nimport parlai.utils.logging as logging\nfrom parlai.core.loader import register_script, SCRIPT_REGISTRY  # noqa: F401\n\n\ndef setup_script_registry():\n    \"\"\"\n    Loads the scripts so that @register_script is hit for all.\n    \"\"\"\n    for module in pkgutil.iter_modules(parlai.scripts.__path__, 'parlai.scripts.'):\n        importlib.import_module(module.name)\n\n\nclass ParlaiScript(object):\n    \"\"\"\n    A ParlAI script is a standardized form of access.\n    \"\"\"\n\n    parser: ParlaiParser\n\n    @classmethod\n    @abstractmethod\n    def setup_args(cls) -> ParlaiParser:\n        \"\"\"\n        Create the parser with args.\n        \"\"\"\n        # we want to later deprecate this for add_cmdline_args\n        pass\n\n    def __init__(self, opt: Opt):\n        self.opt = opt\n\n    @abstractmethod\n    def run(self):\n        \"\"\"\n        The main method.\n\n        Must be implemented by the script writer.\n        \"\"\"\n        raise NotImplementedError()\n\n    @classmethod\n    def _run_kwargs(cls, kwargs: Dict[str, Any]):\n        \"\"\"\n        Construct and run the script using kwargs, pseudo-parsing them.\n        \"\"\"\n        parser = cls.setup_args()\n        opt = parser.parse_kwargs(**kwargs)\n        return cls._run_from_parser_and_opt(opt, parser)\n\n    @classmethod\n    def _run_args(cls, args: Optional[List[str]] = None):\n        \"\"\"\n        Construct and run the script using args, defaulting to getting from CLI.\n        \"\"\"\n        parser = cls.setup_args()\n        opt = parser.parse_args(args=args)\n        return cls._run_from_parser_and_opt(opt, parser)\n\n    @classmethod\n    def _run_from_parser_and_opt(cls, opt: Opt, parser: ParlaiParser):\n        script = cls(opt)\n        script.parser = parser\n        return script.run()\n\n    @classmethod\n    def main(cls, *args, **kwargs):\n        \"\"\"\n        Run the program, possibly with some given args.\n\n        You may provide command line args in the form of strings, or\n        options. For example:\n\n        >>> MyScript.main(['--task', 'convai2'])\n        >>> MyScript.main(task='convai2')\n\n        You may not combine both args and kwargs.\n        \"\"\"\n        assert not (bool(args) and bool(kwargs))\n        if args:\n            return cls._run_args(args)\n        elif kwargs:\n            return cls._run_kwargs(kwargs)\n        else:\n            return cls._run_args(None)\n\n    @classmethod\n    def help(cls, **kwargs):\n        f = io.StringIO()\n        parser = cls.setup_args()\n        parser.prog = cls.__name__\n        parser.add_extra_args(parser._kwargs_to_str_args(**kwargs))\n        parser.print_help(f)\n        return f.getvalue()\n\n\nclass _SupercommandParser(ParlaiParser):\n    \"\"\"\n    Specialty ParlAI parser used for the supercommand.\n\n    Contains some special behavior.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        from parlai.utils.strings import colorize\n\n        logo = \"\"\n        logo += colorize('       _', 'red') + \"\\n\"\n        logo += colorize('      /', 'red') + colorize('\"', 'brightblack')\n        logo += colorize(\")\", \"yellow\") + \"\\n\"\n        logo += colorize('     //', 'red') + colorize(')', 'yellow') + '\\n'\n        logo += colorize('  ==', 'green')\n        logo += colorize(\"/\", 'blue') + colorize('/', 'red') + colorize(\"'\", 'yellow')\n        logo += colorize(\"===\", 'green') + \" ParlAI\\n\"\n        logo += colorize(\"   /\", 'blue')\n        kwargs['description'] = logo\n        return super().__init__(*args, **kwargs)\n\n    def add_extra_args(self, args):\n        sa = [a for a in self._actions if isinstance(a, argparse._SubParsersAction)]\n        assert len(sa) == 1\n        sa = sa[0]\n        for _, v in sa.choices.items():\n            v.add_extra_args(args)\n\n    def add_subparsers(self, **kwargs):\n        return super().add_subparsers(**kwargs)\n\n    def _unsuppress_hidden(self):\n        \"\"\"\n        Restore the help messages of hidden commands.\n        \"\"\"\n\n        spa = [a for a in self._actions if isinstance(a, argparse._SubParsersAction)]\n        assert len(spa) == 1\n        spa = spa[0]\n        for choices_action in spa._choices_actions:\n            dest = choices_action.dest\n            if choices_action.help == argparse.SUPPRESS:\n                choices_action.help = spa.choices[dest].description\n\n    def print_helpall(self):\n        self._unsuppress_hidden()\n        self.print_help()\n\n\nclass _SubcommandParser(ParlaiParser):\n    \"\"\"\n    ParlaiParser which always sets add_parlai_args and add_model_args to False.\n\n    Used in the superscript to initialize just the args for that command.\n    \"\"\"\n\n    def __init__(self, **kwargs):\n        kwargs['add_parlai_args'] = False\n        kwargs['add_model_args'] = False\n        assert 'description' in kwargs, 'Must supply description'\n        return super().__init__(**kwargs)\n\n    def parse_known_args(self, args=None, namespace=None, nohelp=False):\n        if not nohelp:\n            self.add_extra_args(args)\n        return super().parse_known_args(args, namespace, nohelp)\n\n\ndef _SuperscriptHelpFormatter(**kwargs):\n    kwargs['width'] = 100\n    kwargs['max_help_position'] = 9999\n\n    return CustomHelpFormatter(**kwargs)\n\n\ndef superscript_main(args=None):\n    \"\"\"\n    Superscript is a loader for all the other scripts.\n    \"\"\"\n    setup_script_registry()\n\n    parser = _SupercommandParser(\n        False, False, formatter_class=_SuperscriptHelpFormatter\n    )\n    parser.add_argument(\n        '--helpall',\n        action='helpall',\n        help='show all commands, including advanced ones.',\n    )\n    parser.set_defaults(super_command=None)\n    subparsers = parser.add_subparsers(\n        parser_class=_SubcommandParser, title=\"Commands\", metavar=\"COMMAND\"\n    )\n    hparser = subparsers.add_parser(\n        'help',\n        aliases=['h'],\n        help=argparse.SUPPRESS,\n        description=\"List the main commands\",\n    )\n    hparser.set_defaults(super_command='help')\n    hparser = subparsers.add_parser(\n        'helpall',\n        help=argparse.SUPPRESS,\n        description=\"List all commands, including advanced ones.\",\n    )\n    hparser.set_defaults(super_command='helpall')\n\n    # build the supercommand\n    for script_name, registration in SCRIPT_REGISTRY.items():\n        logging.verbose(f\"Discovered command {script_name}\")\n        script_parser = registration.klass.setup_args()\n        if script_parser is None:\n            # user didn't bother defining command line args. let's just fill\n            # in for them\n            script_parser = ParlaiParser(False, False)\n        help_ = argparse.SUPPRESS if registration.hidden else script_parser.description\n        subparser = subparsers.add_parser(\n            script_name,\n            aliases=registration.aliases,\n            help=help_,\n            description=script_parser.description,\n            formatter_class=CustomHelpFormatter,\n        )\n        subparser.set_defaults(\n            # carries the name of the full command so we know what to execute\n            super_command=script_name,\n            # used in ParlAI parser to find CLI options set by user\n            _subparser=subparser,\n        )\n        subparser.set_defaults(**script_parser._defaults)\n        for action in script_parser._actions:\n            subparser._add_action(action)\n        for action_group in script_parser._action_groups:\n            subparser._action_groups.append(action_group)\n\n    try:\n        import argcomplete\n\n        argcomplete.autocomplete(parser)\n    except ModuleNotFoundError:\n        pass\n\n    opt = parser.parse_args(args)\n    cmd = opt.pop('super_command')\n    if cmd == 'helpall':\n        parser.print_helpall()\n    elif cmd == 'help' or cmd is None:\n        parser.print_help()\n    elif cmd is not None:\n        return SCRIPT_REGISTRY[cmd].klass._run_from_parser_and_opt(opt, parser)\n", "path": "parlai/core/script.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\n# Copyright (c) Facebook, Inc. and its affiliates.\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\n\n\"\"\"\nThe general ParlAI Script interface.\n\nAn abstract class to help standardize the call to ParlAI scripts, enabling them to be\ncompleted easily.\n\nAlso contains helper classes for loading scripts, etc.\n\"\"\"\n\nimport io\nimport argparse\nfrom typing import List, Optional, Dict, Any\nimport parlai\nfrom parlai.core.opt import Opt\nfrom parlai.core.params import ParlaiParser, CustomHelpFormatter\nfrom abc import abstractmethod\nimport importlib\nimport pkgutil\nimport parlai.scripts\nimport parlai.utils.logging as logging\nfrom parlai.core.loader import register_script, SCRIPT_REGISTRY  # noqa: F401\n\n\ndef setup_script_registry():\n    \"\"\"\n    Loads the scripts so that @register_script is hit for all.\n    \"\"\"\n    for module in pkgutil.iter_modules(parlai.scripts.__path__, 'parlai.scripts.'):\n        importlib.import_module(module.name)\n\n\nclass ParlaiScript(object):\n    \"\"\"\n    A ParlAI script is a standardized form of access.\n    \"\"\"\n\n    parser: ParlaiParser\n\n    @classmethod\n    @abstractmethod\n    def setup_args(cls) -> ParlaiParser:\n        \"\"\"\n        Create the parser with args.\n        \"\"\"\n        # we want to later deprecate this for add_cmdline_args\n        pass\n\n    def __init__(self, opt: Opt):\n        self.opt = opt\n\n    @abstractmethod\n    def run(self):\n        \"\"\"\n        The main method.\n\n        Must be implemented by the script writer.\n        \"\"\"\n        raise NotImplementedError()\n\n    @classmethod\n    def _run_kwargs(cls, kwargs: Dict[str, Any]):\n        \"\"\"\n        Construct and run the script using kwargs, pseudo-parsing them.\n        \"\"\"\n        parser = cls.setup_args()\n        opt = parser.parse_kwargs(**kwargs)\n        return cls._run_from_parser_and_opt(opt, parser)\n\n    @classmethod\n    def _run_args(cls, args: Optional[List[str]] = None):\n        \"\"\"\n        Construct and run the script using args, defaulting to getting from CLI.\n        \"\"\"\n        parser = cls.setup_args()\n        opt = parser.parse_args(args=args)\n        return cls._run_from_parser_and_opt(opt, parser)\n\n    @classmethod\n    def _run_from_parser_and_opt(cls, opt: Opt, parser: ParlaiParser):\n        script = cls(opt)\n        script.parser = parser\n        return script.run()\n\n    @classmethod\n    def main(cls, *args, **kwargs):\n        \"\"\"\n        Run the program, possibly with some given args.\n\n        You may provide command line args in the form of strings, or\n        options. For example:\n\n        >>> MyScript.main(['--task', 'convai2'])\n        >>> MyScript.main(task='convai2')\n\n        You may not combine both args and kwargs.\n        \"\"\"\n        assert not (bool(args) and bool(kwargs))\n        if args:\n            return cls._run_args(args)\n        elif kwargs:\n            return cls._run_kwargs(kwargs)\n        else:\n            return cls._run_args(None)\n\n    @classmethod\n    def help(cls, **kwargs):\n        f = io.StringIO()\n        parser = cls.setup_args()\n        parser.prog = cls.__name__\n        parser.add_extra_args(parser._kwargs_to_str_args(**kwargs))\n        parser.print_help(f)\n        return f.getvalue()\n\n\nclass _SupercommandParser(ParlaiParser):\n    \"\"\"\n    Specialty ParlAI parser used for the supercommand.\n\n    Contains some special behavior.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        from parlai.utils.strings import colorize\n\n        logo = \"\"\n        logo += colorize('       _', 'red') + \"\\n\"\n        logo += colorize('      /', 'red') + colorize('\"', 'brightblack')\n        logo += colorize(\")\", \"yellow\") + \"\\n\"\n        logo += colorize('     //', 'red') + colorize(')', 'yellow') + '\\n'\n        logo += colorize('  ==', 'green')\n        logo += colorize(\"/\", 'blue') + colorize('/', 'red') + colorize(\"'\", 'yellow')\n        logo += colorize(\"===\", 'green') + \" ParlAI\\n\"\n        logo += colorize(\"   /\", 'blue')\n        kwargs['description'] = logo\n        return super().__init__(*args, **kwargs)\n\n    def add_extra_args(self, args):\n        sa = [a for a in self._actions if isinstance(a, argparse._SubParsersAction)]\n        assert len(sa) == 1\n        sa = sa[0]\n        for _, v in sa.choices.items():\n            v.add_extra_args(args)\n\n    def add_subparsers(self, **kwargs):\n        return super().add_subparsers(**kwargs)\n\n    def _unsuppress_hidden(self):\n        \"\"\"\n        Restore the help messages of hidden commands.\n        \"\"\"\n\n        spa = [a for a in self._actions if isinstance(a, argparse._SubParsersAction)]\n        assert len(spa) == 1\n        spa = spa[0]\n        for choices_action in spa._choices_actions:\n            dest = choices_action.dest\n            if choices_action.help == argparse.SUPPRESS:\n                choices_action.help = spa.choices[dest].description\n\n    def print_helpall(self):\n        self._unsuppress_hidden()\n        self.print_help()\n\n\nclass _SubcommandParser(ParlaiParser):\n    \"\"\"\n    ParlaiParser which always sets add_parlai_args and add_model_args to False.\n\n    Used in the superscript to initialize just the args for that command.\n    \"\"\"\n\n    def __init__(self, **kwargs):\n        kwargs['add_parlai_args'] = False\n        kwargs['add_model_args'] = False\n        assert 'description' in kwargs, 'Must supply description'\n        return super().__init__(**kwargs)\n\n    def parse_known_args(self, args=None, namespace=None, nohelp=False):\n        if not nohelp:\n            self.add_extra_args(args)\n        return super().parse_known_args(args, namespace, nohelp)\n\n\ndef _SuperscriptHelpFormatter(**kwargs):\n    kwargs['width'] = 100\n    kwargs['max_help_position'] = 9999\n\n    return CustomHelpFormatter(**kwargs)\n\n\ndef superscript_main(args=None):\n    \"\"\"\n    Superscript is a loader for all the other scripts.\n    \"\"\"\n    setup_script_registry()\n\n    parser = _SupercommandParser(\n        False, False, formatter_class=_SuperscriptHelpFormatter\n    )\n    parser.add_argument(\n        '--helpall',\n        action='helpall',\n        help='List all commands, including advanced ones.',\n    )\n    parser.add_argument(\n        '--version',\n        action='version',\n        version=get_version_string(),\n        help='Prints version info and exit.',\n    )\n    parser.set_defaults(super_command=None)\n    subparsers = parser.add_subparsers(\n        parser_class=_SubcommandParser, title=\"Commands\", metavar=\"COMMAND\"\n    )\n    hparser = subparsers.add_parser(\n        'help',\n        aliases=['h'],\n        help=argparse.SUPPRESS,\n        description='List the main commands.',\n    )\n    hparser.set_defaults(super_command='help')\n    hparser = subparsers.add_parser(\n        'helpall',\n        help=argparse.SUPPRESS,\n        description='List all commands, including advanced ones.',\n    )\n    hparser.set_defaults(super_command='helpall')\n\n    # build the supercommand\n    for script_name, registration in SCRIPT_REGISTRY.items():\n        logging.verbose(f\"Discovered command {script_name}\")\n        script_parser = registration.klass.setup_args()\n        if script_parser is None:\n            # user didn't bother defining command line args. let's just fill\n            # in for them\n            script_parser = ParlaiParser(False, False)\n        help_ = argparse.SUPPRESS if registration.hidden else script_parser.description\n        subparser = subparsers.add_parser(\n            script_name,\n            aliases=registration.aliases,\n            help=help_,\n            description=script_parser.description,\n            formatter_class=CustomHelpFormatter,\n        )\n        subparser.set_defaults(\n            # carries the name of the full command so we know what to execute\n            super_command=script_name,\n            # used in ParlAI parser to find CLI options set by user\n            _subparser=subparser,\n        )\n        subparser.set_defaults(**script_parser._defaults)\n        for action in script_parser._actions:\n            subparser._add_action(action)\n        for action_group in script_parser._action_groups:\n            subparser._action_groups.append(action_group)\n\n    try:\n        import argcomplete\n\n        argcomplete.autocomplete(parser)\n    except ModuleNotFoundError:\n        pass\n\n    opt = parser.parse_args(args)\n    cmd = opt.pop('super_command')\n    if cmd == 'helpall':\n        parser.print_helpall()\n    elif cmd == 'versioninfo':\n        exit(0)\n    elif cmd == 'help' or cmd is None:\n        parser.print_help()\n    elif cmd is not None:\n        return SCRIPT_REGISTRY[cmd].klass._run_from_parser_and_opt(opt, parser)\n\n\ndef get_version_string() -> str:\n    return f\"ParlAI version {parlai.__version__}\"\n", "path": "parlai/core/script.py"}]}