We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Help incorrectly shows when flag isn't recognized
**Bug description**
```
$ parlai i -mf /checkpoint/parlai/zoo/
q_function/generative2.7B_bst_0331/model --display-fi 1
usage: parlai [-h] [--helpall] [--version] COMMAND ...

       _
      /")
     //)
  ==//'=== ParlAI
   /

optional arguments:
  -h, --help               show this help message and exit
  --helpall                List all commands, including advanced ones.
  --version                Prints version info and exit.

Commands:
  
  display_data (dd)        Display data from a task
  display_model (dm)       Display model predictions.
  eval_model (em, eval)    Evaluate a model
  train_model (tm, train)  Train a model
  interactive (i)          Interactive chat with a model on the command line
  safe_interactive         Like interactive, but adds a safety filter
  self_chat                Generate self-chats of a model

Parse Error: unrecognized arguments: --display-fi 1
```

Note that the parlai supercommand help shows, and not the interactive.


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

{"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@@ -126,6 +126,9 @@\n     \"\"\"\n \n     def __init__(self, *args, **kwargs):\n+        # used to target help messages more correctly, see GH #3182\n+        self._help_subparser = None\n+\n         from parlai.utils.strings import colorize\n \n         logo = \"\"\n@@ -147,6 +150,22 @@\n         for _, v in sa.choices.items():\n             v.add_extra_args(args)\n \n+    def parse_known_args(self, args=None, namespace=None, nohelp=False):\n+        known, unused = super().parse_known_args(args, namespace, nohelp)\n+        if hasattr(known, '_subparser'):\n+            # keep this around to keep the print message more in tune\n+            self._help_subparser = known._subparser\n+        return known, unused\n+\n+    def print_help(self):\n+        \"\"\"\n+        Print help, possibly deferring to the appropriate subcommand.\n+        \"\"\"\n+        if self._help_subparser:\n+            self._help_subparser.print_help()\n+        else:\n+            return super().print_help()\n+\n     def add_subparsers(self, **kwargs):\n         return super().add_subparsers(**kwargs)\n", "issue": "Help incorrectly shows when flag isn't recognized\n**Bug description**\r\n```\r\n$ parlai i -mf /checkpoint/parlai/zoo/\r\nq_function/generative2.7B_bst_0331/model --display-fi 1\r\nusage: parlai [-h] [--helpall] [--version] COMMAND ...\r\n\r\n       _\r\n      /\")\r\n     //)\r\n  ==//'=== ParlAI\r\n   /\r\n\r\noptional arguments:\r\n  -h, --help               show this help message and exit\r\n  --helpall                List all commands, including advanced ones.\r\n  --version                Prints version info and exit.\r\n\r\nCommands:\r\n  \r\n  display_data (dd)        Display data from a task\r\n  display_model (dm)       Display model predictions.\r\n  eval_model (em, eval)    Evaluate a model\r\n  train_model (tm, train)  Train a model\r\n  interactive (i)          Interactive chat with a model on the command line\r\n  safe_interactive         Like interactive, but adds a safety filter\r\n  self_chat                Generate self-chats of a model\r\n\r\nParse Error: unrecognized arguments: --display-fi 1\r\n```\r\n\r\nNote that the parlai supercommand help shows, and not the interactive.\r\n\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\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"}], "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\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        # used to target help messages more correctly, see GH #3182\n        self._help_subparser = None\n\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 parse_known_args(self, args=None, namespace=None, nohelp=False):\n        known, unused = super().parse_known_args(args, namespace, nohelp)\n        if hasattr(known, '_subparser'):\n            # keep this around to keep the print message more in tune\n            self._help_subparser = known._subparser\n        return known, unused\n\n    def print_help(self):\n        \"\"\"\n        Print help, possibly deferring to the appropriate subcommand.\n        \"\"\"\n        if self._help_subparser:\n            self._help_subparser.print_help()\n        else:\n            return super().print_help()\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"}]}