We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
predict --channel-order not working
The `channel-order` option of `rastervision predict` does not work when the command is run as a stand-alone script.

```
root@122d4f0150f4:/opt/data/mar5# rastervision predict potsdam.zip example.jpg out.tif --channel-order "0 1 2"
Usage: python -m rastervision predict [OPTIONS] PREDICT_PACKAGE IMAGE_URI
                                      OUTPUT_URI
Try "python -m rastervision predict --help" for help.

Error: Got unexpected extra arguments (1 2)
```

However, when it is run as a python module, it works. 
```
root@122d4f0150f4:/opt/data/mar5# python -m rastervision.cli.main predict potsdam.zip example.jpg out.tif --channel-order "0 1 2"
/usr/local/lib/python3.5/dist-packages/pluginbase.py:439: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  fromlist, level)
2019-03-06 18:46:21.105826: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
/usr/local/lib/python3.5/dist-packages/rasterio/__init__.py:217: NotGeoreferencedWarning: Dataset has no geotransform set. The identity matrix may be returned.
  s = DatasetReader(path, driver=driver, **kwargs)
[0, 1, 2]
[0]
2019-03-06 18:46:21:rastervision.task.semantic_segmentation: INFO - Making predictions for scene
/usr/local/lib/python3.5/dist-packages/rasterio/__init__.py:226: NotGeoreferencedWarning: Dataset has no geotransform set. The identity matrix may be returned.
  **kwargs)
.........................
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `rastervision/cli/main.py`
Content:
```
1 """Raster Vision main program"""
2 import sys
3 import os
4 
5 import click
6 import logging
7 
8 import rastervision as rv
9 from rastervision.experiment import (ExperimentLoader, LoaderError)
10 from rastervision.runner import (ExperimentRunner)
11 from rastervision.rv_config import RVConfig
12 
13 log = logging.getLogger(__name__)
14 
15 
16 def print_error(msg):
17     click.echo(click.style(msg, fg='red'), err=True)
18 
19 
20 @click.group()
21 @click.option(
22     '--profile', '-p', help='Sets the configuration profile name to use.')
23 @click.option(
24     '-v', '--verbose', help='Sets the output to  be verbose.', count=True)
25 def main(profile, verbose):
26     # Make sure current directory is on PYTHON_PATH
27     # so that we can run against modules in current dir.
28     sys.path.append(os.curdir)
29 
30     # Initialize configuration
31     rv._registry.initialize_config(profile=profile, verbosity=verbose + 1)
32 
33 
34 @main.command(
35     'run', short_help='Run Raster Vision commands against Experiments.')
36 @click.argument('runner')
37 @click.argument('commands', nargs=-1)
38 @click.option(
39     '--experiment_module',
40     '-e',
41     help=('Name of an importable module to look for experiment sets '
42           'in. If not supplied, experiments will be loaded '
43           'from __main__'))
44 @click.option(
45     '--path',
46     '-p',
47     metavar='PATTERN',
48     help=('Path of file containing ExprimentSet to run.'))
49 @click.option(
50     '--dry-run',
51     '-n',
52     is_flag=True,
53     help=('Execute a dry run, which will print out information '
54           'about the commands to be run, but will not actually '
55           'run the commands'))
56 @click.option(
57     '--skip-file-check',
58     '-x',
59     is_flag=True,
60     help=('Skip the step that verifies that file exist.'))
61 @click.option(
62     '--arg',
63     '-a',
64     type=(str, str),
65     multiple=True,
66     metavar='KEY VALUE',
67     help=('Pass a parameter to the experiments if the method '
68           'parameter list takes in a parameter with that key. '
69           'Multiple args can be supplied'))
70 @click.option(
71     '--prefix',
72     metavar='PREFIX',
73     default='exp_',
74     help=('Prefix for methods containing experiments. (default: "exp_")'))
75 @click.option(
76     '--method',
77     '-m',
78     'methods',
79     multiple=True,
80     metavar='PATTERN',
81     help=('Pattern to match method names to run.'))
82 @click.option(
83     '--filter',
84     '-f',
85     'filters',
86     multiple=True,
87     metavar='PATTERN',
88     help=('Pattern to match experiment names to run.'))
89 @click.option(
90     '--rerun',
91     '-r',
92     is_flag=True,
93     default=False,
94     help=('Rerun commands, regardless if '
95           'their output files already exist.'))
96 @click.option('--tempdir', help=('Temporary directory to use for this run.'))
97 @click.option(
98     '--splits',
99     '-s',
100     default=1,
101     metavar='INTEGER',
102     help=('The number of processes to attempt to split each stage into.'))
103 def run(runner, commands, experiment_module, dry_run, skip_file_check, arg,
104         prefix, methods, path, filters, rerun, tempdir, splits):
105     """Run Raster Vision commands from experiments, using the
106     experiment runner named RUNNER."""
107 
108     if tempdir:
109         RVConfig.set_tmp_dir(tempdir)
110 
111     # Validate runner
112     valid_runners = list(
113         map(lambda x: x.lower(), rv.ExperimentRunner.list_runners()))
114     if runner not in valid_runners:
115         print_error('Invalid experiment runner: "{}". '
116                     'Must be one of: "{}"'.format(runner,
117                                                   '", "'.join(valid_runners)))
118         sys.exit(1)
119 
120     runner = ExperimentRunner.get_runner(runner)
121 
122     if experiment_module and path:
123         print_error('Must specify only one of experiment_module or path')
124         sys.exit(1)
125 
126     if not commands:
127         commands = rv.ALL_COMMANDS
128     else:
129         commands = list(map(lambda x: x.upper(), commands))
130 
131     experiment_args = {}
132     for k, v in arg:
133         experiment_args[k] = v
134 
135     loader = ExperimentLoader(
136         experiment_args=experiment_args,
137         experiment_method_prefix=prefix,
138         experiment_method_patterns=methods,
139         experiment_name_patterns=filters)
140     try:
141         if experiment_module:
142             experiments = loader.load_from_module(experiment_module)
143         elif path:
144             experiments = loader.load_from_file(path)
145         else:
146             experiments = loader.load_from_module('__main__')
147     except LoaderError as e:
148         print_error(str(e))
149         sys.exit(1)
150 
151     if not experiments:
152         if experiment_module:
153             print_error(
154                 'No experiments found in {}.'.format(experiment_module))
155         elif path:
156             print_error('No experiments found in {}.'.format(path))
157         else:
158             print_error('No experiments found.')
159 
160     runner.run(
161         experiments,
162         commands_to_run=commands,
163         rerun_commands=rerun,
164         skip_file_check=skip_file_check,
165         dry_run=dry_run,
166         splits=splits)
167 
168 
169 @main.command()
170 @click.option(
171     '--experiment-module',
172     '-e',
173     help=('Name of an importable module to look for experiment sets '
174           'in. If not supplied, experiments will be loaded '
175           'from __main__'))
176 @click.option(
177     '--arg',
178     '-a',
179     type=(str, str),
180     multiple=True,
181     metavar='KEY VALUE',
182     help=('Pass a parameter to the experiments if the method '
183           'parameter list takes in a parameter with that key. '
184           'Multiple args can be supplied'))
185 def ls(experiment_module, arg):
186     """Print out a list of Experiment IDs."""
187     if experiment_module:
188         module_to_load = experiment_module
189     else:
190         module_to_load = '__main__'
191 
192     experiment_args = {}
193     for k, v in arg:
194         experiment_args[k] = v
195 
196     loader = ExperimentLoader(experiment_args=experiment_args)
197     try:
198         experiments = loader.load_from_module(module_to_load)
199     except LoaderError as e:
200         print_error(str(e))
201         sys.exit(1)
202 
203     if not experiments:
204         if experiment_module:
205             print_error(
206                 'No experiments found in {}.'.format(experiment_module))
207         else:
208             print_error('No experiments found.')
209 
210     for e in experiments:
211         click.echo('{}'.format(e.id))
212 
213 
214 @main.command(
215     'predict', short_help='Make predictions using a predict package.')
216 @click.argument('predict_package')
217 @click.argument('image_uri')
218 @click.argument('output_uri')
219 @click.option(
220     '--update-stats',
221     '-a',
222     is_flag=True,
223     help=('Run an analysis on this individual image, as '
224           'opposed to using any analysis like statistics '
225           'that exist in the prediction package'))
226 @click.option(
227     '--channel-order',
228     help='String containing channel_order. Example: \"2 1 0\"')
229 @click.option(
230     '--export-config',
231     type=click.Path(exists=False),
232     help='Exports the configuration to the given output file.')
233 def predict(predict_package, image_uri, output_uri, update_stats,
234             channel_order, export_config):
235     """Make predictions on the image at IMAGE_URI
236     using PREDICT_PACKAGE and store the
237     prediciton output at OUTPUT_URI.
238     """
239     if channel_order is not None:
240         channel_order = [
241             int(channel_ind) for channel_ind in channel_order.split(' ')
242         ]
243 
244     with RVConfig.get_tmp_dir() as tmp_dir:
245         predictor = rv.Predictor(predict_package, tmp_dir, update_stats,
246                                  channel_order)
247         predictor.predict(image_uri, output_uri, export_config)
248 
249 
250 @main.command(
251     'run_command', short_help='Run a command from configuration file.')
252 @click.argument('command_config_uri')
253 @click.option('--tempdir')
254 def run_command(command_config_uri, tempdir):
255     """Run a command from a serialized command configuration
256     at COMMAND_CONFIG_URI.
257     """
258     if tempdir is not None:
259         RVConfig.set_tmp_dir(tempdir)
260     rv.runner.CommandRunner.run(command_config_uri)
261 
262 
263 if __name__ == '__main__':
264     main()
265
```
--- 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/rastervision/cli/main.py b/rastervision/cli/main.py
--- a/rastervision/cli/main.py
+++ b/rastervision/cli/main.py
@@ -211,6 +211,37 @@
         click.echo('{}'.format(e.id))
 
 
+# https://stackoverflow.com/questions/48391777/nargs-equivalent-for-options-in-click
+class OptionEatAll(click.Option):
+    def __init__(self, *args, **kwargs):
+        self.save_other_options = kwargs.pop('save_other_options', True)
+        nargs = kwargs.pop('nargs', -1)
+        assert nargs == -1, 'nargs, if set, must be -1 not {}'.format(nargs)
+        super(OptionEatAll, self).__init__(*args, **kwargs)
+        self._previous_parser_process = None
+        self._eat_all_parser = None
+
+    def add_to_parser(self, parser, ctx):
+        def parser_process(value, state):
+            value = str(value)
+            while state.rargs:
+                value = '{} {}'.format(value, state.rargs.pop(0))
+            self._previous_parser_process(value, state)
+
+        retval = super(OptionEatAll, self).add_to_parser(parser, ctx)
+
+        for name in self.opts:
+            our_parser = parser._long_opt.get(name) or parser._short_opt.get(
+                name)
+            if our_parser:
+                self._eat_all_parser = our_parser
+                self._previous_parser_process = our_parser.process
+                our_parser.process = parser_process
+                break
+
+        return retval
+
+
 @main.command(
     'predict', short_help='Make predictions using a predict package.')
 @click.argument('predict_package')
@@ -225,7 +256,8 @@
           'that exist in the prediction package'))
 @click.option(
     '--channel-order',
-    help='String containing channel_order. Example: \"2 1 0\"')
+    cls=OptionEatAll,
+    help='List of indices comprising channel_order. Example: 2 1 0')
 @click.option(
     '--export-config',
     type=click.Path(exists=False),

{"golden_diff": "diff --git a/rastervision/cli/main.py b/rastervision/cli/main.py\n--- a/rastervision/cli/main.py\n+++ b/rastervision/cli/main.py\n@@ -211,6 +211,37 @@\n         click.echo('{}'.format(e.id))\n \n \n+# https://stackoverflow.com/questions/48391777/nargs-equivalent-for-options-in-click\n+class OptionEatAll(click.Option):\n+    def __init__(self, *args, **kwargs):\n+        self.save_other_options = kwargs.pop('save_other_options', True)\n+        nargs = kwargs.pop('nargs', -1)\n+        assert nargs == -1, 'nargs, if set, must be -1 not {}'.format(nargs)\n+        super(OptionEatAll, self).__init__(*args, **kwargs)\n+        self._previous_parser_process = None\n+        self._eat_all_parser = None\n+\n+    def add_to_parser(self, parser, ctx):\n+        def parser_process(value, state):\n+            value = str(value)\n+            while state.rargs:\n+                value = '{} {}'.format(value, state.rargs.pop(0))\n+            self._previous_parser_process(value, state)\n+\n+        retval = super(OptionEatAll, self).add_to_parser(parser, ctx)\n+\n+        for name in self.opts:\n+            our_parser = parser._long_opt.get(name) or parser._short_opt.get(\n+                name)\n+            if our_parser:\n+                self._eat_all_parser = our_parser\n+                self._previous_parser_process = our_parser.process\n+                our_parser.process = parser_process\n+                break\n+\n+        return retval\n+\n+\n @main.command(\n     'predict', short_help='Make predictions using a predict package.')\n @click.argument('predict_package')\n@@ -225,7 +256,8 @@\n           'that exist in the prediction package'))\n @click.option(\n     '--channel-order',\n-    help='String containing channel_order. Example: \\\"2 1 0\\\"')\n+    cls=OptionEatAll,\n+    help='List of indices comprising channel_order. Example: 2 1 0')\n @click.option(\n     '--export-config',\n     type=click.Path(exists=False),\n", "issue": "predict --channel-order not working\nThe `channel-order` option of `rastervision predict` does not work when the command is run as a stand-alone script.\r\n\r\n```\r\nroot@122d4f0150f4:/opt/data/mar5# rastervision predict potsdam.zip example.jpg out.tif --channel-order \"0 1 2\"\r\nUsage: python -m rastervision predict [OPTIONS] PREDICT_PACKAGE IMAGE_URI\r\n                                      OUTPUT_URI\r\nTry \"python -m rastervision predict --help\" for help.\r\n\r\nError: Got unexpected extra arguments (1 2)\r\n```\r\n\r\nHowever, when it is run as a python module, it works. \r\n```\r\nroot@122d4f0150f4:/opt/data/mar5# python -m rastervision.cli.main predict potsdam.zip example.jpg out.tif --channel-order \"0 1 2\"\r\n/usr/local/lib/python3.5/dist-packages/pluginbase.py:439: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\r\n  fromlist, level)\r\n2019-03-06 18:46:21.105826: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA\r\n/usr/local/lib/python3.5/dist-packages/rasterio/__init__.py:217: NotGeoreferencedWarning: Dataset has no geotransform set. The identity matrix may be returned.\r\n  s = DatasetReader(path, driver=driver, **kwargs)\r\n[0, 1, 2]\r\n[0]\r\n2019-03-06 18:46:21:rastervision.task.semantic_segmentation: INFO - Making predictions for scene\r\n/usr/local/lib/python3.5/dist-packages/rasterio/__init__.py:226: NotGeoreferencedWarning: Dataset has no geotransform set. The identity matrix may be returned.\r\n  **kwargs)\r\n.........................\r\n```\n", "before_files": [{"content": "\"\"\"Raster Vision main program\"\"\"\nimport sys\nimport os\n\nimport click\nimport logging\n\nimport rastervision as rv\nfrom rastervision.experiment import (ExperimentLoader, LoaderError)\nfrom rastervision.runner import (ExperimentRunner)\nfrom rastervision.rv_config import RVConfig\n\nlog = logging.getLogger(__name__)\n\n\ndef print_error(msg):\n    click.echo(click.style(msg, fg='red'), err=True)\n\n\n@click.group()\n@click.option(\n    '--profile', '-p', help='Sets the configuration profile name to use.')\n@click.option(\n    '-v', '--verbose', help='Sets the output to  be verbose.', count=True)\ndef main(profile, verbose):\n    # Make sure current directory is on PYTHON_PATH\n    # so that we can run against modules in current dir.\n    sys.path.append(os.curdir)\n\n    # Initialize configuration\n    rv._registry.initialize_config(profile=profile, verbosity=verbose + 1)\n\n\n@main.command(\n    'run', short_help='Run Raster Vision commands against Experiments.')\n@click.argument('runner')\n@click.argument('commands', nargs=-1)\n@click.option(\n    '--experiment_module',\n    '-e',\n    help=('Name of an importable module to look for experiment sets '\n          'in. If not supplied, experiments will be loaded '\n          'from __main__'))\n@click.option(\n    '--path',\n    '-p',\n    metavar='PATTERN',\n    help=('Path of file containing ExprimentSet to run.'))\n@click.option(\n    '--dry-run',\n    '-n',\n    is_flag=True,\n    help=('Execute a dry run, which will print out information '\n          'about the commands to be run, but will not actually '\n          'run the commands'))\n@click.option(\n    '--skip-file-check',\n    '-x',\n    is_flag=True,\n    help=('Skip the step that verifies that file exist.'))\n@click.option(\n    '--arg',\n    '-a',\n    type=(str, str),\n    multiple=True,\n    metavar='KEY VALUE',\n    help=('Pass a parameter to the experiments if the method '\n          'parameter list takes in a parameter with that key. '\n          'Multiple args can be supplied'))\n@click.option(\n    '--prefix',\n    metavar='PREFIX',\n    default='exp_',\n    help=('Prefix for methods containing experiments. (default: \"exp_\")'))\n@click.option(\n    '--method',\n    '-m',\n    'methods',\n    multiple=True,\n    metavar='PATTERN',\n    help=('Pattern to match method names to run.'))\n@click.option(\n    '--filter',\n    '-f',\n    'filters',\n    multiple=True,\n    metavar='PATTERN',\n    help=('Pattern to match experiment names to run.'))\n@click.option(\n    '--rerun',\n    '-r',\n    is_flag=True,\n    default=False,\n    help=('Rerun commands, regardless if '\n          'their output files already exist.'))\n@click.option('--tempdir', help=('Temporary directory to use for this run.'))\n@click.option(\n    '--splits',\n    '-s',\n    default=1,\n    metavar='INTEGER',\n    help=('The number of processes to attempt to split each stage into.'))\ndef run(runner, commands, experiment_module, dry_run, skip_file_check, arg,\n        prefix, methods, path, filters, rerun, tempdir, splits):\n    \"\"\"Run Raster Vision commands from experiments, using the\n    experiment runner named RUNNER.\"\"\"\n\n    if tempdir:\n        RVConfig.set_tmp_dir(tempdir)\n\n    # Validate runner\n    valid_runners = list(\n        map(lambda x: x.lower(), rv.ExperimentRunner.list_runners()))\n    if runner not in valid_runners:\n        print_error('Invalid experiment runner: \"{}\". '\n                    'Must be one of: \"{}\"'.format(runner,\n                                                  '\", \"'.join(valid_runners)))\n        sys.exit(1)\n\n    runner = ExperimentRunner.get_runner(runner)\n\n    if experiment_module and path:\n        print_error('Must specify only one of experiment_module or path')\n        sys.exit(1)\n\n    if not commands:\n        commands = rv.ALL_COMMANDS\n    else:\n        commands = list(map(lambda x: x.upper(), commands))\n\n    experiment_args = {}\n    for k, v in arg:\n        experiment_args[k] = v\n\n    loader = ExperimentLoader(\n        experiment_args=experiment_args,\n        experiment_method_prefix=prefix,\n        experiment_method_patterns=methods,\n        experiment_name_patterns=filters)\n    try:\n        if experiment_module:\n            experiments = loader.load_from_module(experiment_module)\n        elif path:\n            experiments = loader.load_from_file(path)\n        else:\n            experiments = loader.load_from_module('__main__')\n    except LoaderError as e:\n        print_error(str(e))\n        sys.exit(1)\n\n    if not experiments:\n        if experiment_module:\n            print_error(\n                'No experiments found in {}.'.format(experiment_module))\n        elif path:\n            print_error('No experiments found in {}.'.format(path))\n        else:\n            print_error('No experiments found.')\n\n    runner.run(\n        experiments,\n        commands_to_run=commands,\n        rerun_commands=rerun,\n        skip_file_check=skip_file_check,\n        dry_run=dry_run,\n        splits=splits)\n\n\n@main.command()\n@click.option(\n    '--experiment-module',\n    '-e',\n    help=('Name of an importable module to look for experiment sets '\n          'in. If not supplied, experiments will be loaded '\n          'from __main__'))\n@click.option(\n    '--arg',\n    '-a',\n    type=(str, str),\n    multiple=True,\n    metavar='KEY VALUE',\n    help=('Pass a parameter to the experiments if the method '\n          'parameter list takes in a parameter with that key. '\n          'Multiple args can be supplied'))\ndef ls(experiment_module, arg):\n    \"\"\"Print out a list of Experiment IDs.\"\"\"\n    if experiment_module:\n        module_to_load = experiment_module\n    else:\n        module_to_load = '__main__'\n\n    experiment_args = {}\n    for k, v in arg:\n        experiment_args[k] = v\n\n    loader = ExperimentLoader(experiment_args=experiment_args)\n    try:\n        experiments = loader.load_from_module(module_to_load)\n    except LoaderError as e:\n        print_error(str(e))\n        sys.exit(1)\n\n    if not experiments:\n        if experiment_module:\n            print_error(\n                'No experiments found in {}.'.format(experiment_module))\n        else:\n            print_error('No experiments found.')\n\n    for e in experiments:\n        click.echo('{}'.format(e.id))\n\n\n@main.command(\n    'predict', short_help='Make predictions using a predict package.')\n@click.argument('predict_package')\n@click.argument('image_uri')\n@click.argument('output_uri')\n@click.option(\n    '--update-stats',\n    '-a',\n    is_flag=True,\n    help=('Run an analysis on this individual image, as '\n          'opposed to using any analysis like statistics '\n          'that exist in the prediction package'))\n@click.option(\n    '--channel-order',\n    help='String containing channel_order. Example: \\\"2 1 0\\\"')\n@click.option(\n    '--export-config',\n    type=click.Path(exists=False),\n    help='Exports the configuration to the given output file.')\ndef predict(predict_package, image_uri, output_uri, update_stats,\n            channel_order, export_config):\n    \"\"\"Make predictions on the image at IMAGE_URI\n    using PREDICT_PACKAGE and store the\n    prediciton output at OUTPUT_URI.\n    \"\"\"\n    if channel_order is not None:\n        channel_order = [\n            int(channel_ind) for channel_ind in channel_order.split(' ')\n        ]\n\n    with RVConfig.get_tmp_dir() as tmp_dir:\n        predictor = rv.Predictor(predict_package, tmp_dir, update_stats,\n                                 channel_order)\n        predictor.predict(image_uri, output_uri, export_config)\n\n\n@main.command(\n    'run_command', short_help='Run a command from configuration file.')\n@click.argument('command_config_uri')\n@click.option('--tempdir')\ndef run_command(command_config_uri, tempdir):\n    \"\"\"Run a command from a serialized command configuration\n    at COMMAND_CONFIG_URI.\n    \"\"\"\n    if tempdir is not None:\n        RVConfig.set_tmp_dir(tempdir)\n    rv.runner.CommandRunner.run(command_config_uri)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "rastervision/cli/main.py"}], "after_files": [{"content": "\"\"\"Raster Vision main program\"\"\"\nimport sys\nimport os\n\nimport click\nimport logging\n\nimport rastervision as rv\nfrom rastervision.experiment import (ExperimentLoader, LoaderError)\nfrom rastervision.runner import (ExperimentRunner)\nfrom rastervision.rv_config import RVConfig\n\nlog = logging.getLogger(__name__)\n\n\ndef print_error(msg):\n    click.echo(click.style(msg, fg='red'), err=True)\n\n\n@click.group()\n@click.option(\n    '--profile', '-p', help='Sets the configuration profile name to use.')\n@click.option(\n    '-v', '--verbose', help='Sets the output to  be verbose.', count=True)\ndef main(profile, verbose):\n    # Make sure current directory is on PYTHON_PATH\n    # so that we can run against modules in current dir.\n    sys.path.append(os.curdir)\n\n    # Initialize configuration\n    rv._registry.initialize_config(profile=profile, verbosity=verbose + 1)\n\n\n@main.command(\n    'run', short_help='Run Raster Vision commands against Experiments.')\n@click.argument('runner')\n@click.argument('commands', nargs=-1)\n@click.option(\n    '--experiment_module',\n    '-e',\n    help=('Name of an importable module to look for experiment sets '\n          'in. If not supplied, experiments will be loaded '\n          'from __main__'))\n@click.option(\n    '--path',\n    '-p',\n    metavar='PATTERN',\n    help=('Path of file containing ExprimentSet to run.'))\n@click.option(\n    '--dry-run',\n    '-n',\n    is_flag=True,\n    help=('Execute a dry run, which will print out information '\n          'about the commands to be run, but will not actually '\n          'run the commands'))\n@click.option(\n    '--skip-file-check',\n    '-x',\n    is_flag=True,\n    help=('Skip the step that verifies that file exist.'))\n@click.option(\n    '--arg',\n    '-a',\n    type=(str, str),\n    multiple=True,\n    metavar='KEY VALUE',\n    help=('Pass a parameter to the experiments if the method '\n          'parameter list takes in a parameter with that key. '\n          'Multiple args can be supplied'))\n@click.option(\n    '--prefix',\n    metavar='PREFIX',\n    default='exp_',\n    help=('Prefix for methods containing experiments. (default: \"exp_\")'))\n@click.option(\n    '--method',\n    '-m',\n    'methods',\n    multiple=True,\n    metavar='PATTERN',\n    help=('Pattern to match method names to run.'))\n@click.option(\n    '--filter',\n    '-f',\n    'filters',\n    multiple=True,\n    metavar='PATTERN',\n    help=('Pattern to match experiment names to run.'))\n@click.option(\n    '--rerun',\n    '-r',\n    is_flag=True,\n    default=False,\n    help=('Rerun commands, regardless if '\n          'their output files already exist.'))\n@click.option('--tempdir', help=('Temporary directory to use for this run.'))\n@click.option(\n    '--splits',\n    '-s',\n    default=1,\n    metavar='INTEGER',\n    help=('The number of processes to attempt to split each stage into.'))\ndef run(runner, commands, experiment_module, dry_run, skip_file_check, arg,\n        prefix, methods, path, filters, rerun, tempdir, splits):\n    \"\"\"Run Raster Vision commands from experiments, using the\n    experiment runner named RUNNER.\"\"\"\n\n    if tempdir:\n        RVConfig.set_tmp_dir(tempdir)\n\n    # Validate runner\n    valid_runners = list(\n        map(lambda x: x.lower(), rv.ExperimentRunner.list_runners()))\n    if runner not in valid_runners:\n        print_error('Invalid experiment runner: \"{}\". '\n                    'Must be one of: \"{}\"'.format(runner,\n                                                  '\", \"'.join(valid_runners)))\n        sys.exit(1)\n\n    runner = ExperimentRunner.get_runner(runner)\n\n    if experiment_module and path:\n        print_error('Must specify only one of experiment_module or path')\n        sys.exit(1)\n\n    if not commands:\n        commands = rv.ALL_COMMANDS\n    else:\n        commands = list(map(lambda x: x.upper(), commands))\n\n    experiment_args = {}\n    for k, v in arg:\n        experiment_args[k] = v\n\n    loader = ExperimentLoader(\n        experiment_args=experiment_args,\n        experiment_method_prefix=prefix,\n        experiment_method_patterns=methods,\n        experiment_name_patterns=filters)\n    try:\n        if experiment_module:\n            experiments = loader.load_from_module(experiment_module)\n        elif path:\n            experiments = loader.load_from_file(path)\n        else:\n            experiments = loader.load_from_module('__main__')\n    except LoaderError as e:\n        print_error(str(e))\n        sys.exit(1)\n\n    if not experiments:\n        if experiment_module:\n            print_error(\n                'No experiments found in {}.'.format(experiment_module))\n        elif path:\n            print_error('No experiments found in {}.'.format(path))\n        else:\n            print_error('No experiments found.')\n\n    runner.run(\n        experiments,\n        commands_to_run=commands,\n        rerun_commands=rerun,\n        skip_file_check=skip_file_check,\n        dry_run=dry_run,\n        splits=splits)\n\n\n@main.command()\n@click.option(\n    '--experiment-module',\n    '-e',\n    help=('Name of an importable module to look for experiment sets '\n          'in. If not supplied, experiments will be loaded '\n          'from __main__'))\n@click.option(\n    '--arg',\n    '-a',\n    type=(str, str),\n    multiple=True,\n    metavar='KEY VALUE',\n    help=('Pass a parameter to the experiments if the method '\n          'parameter list takes in a parameter with that key. '\n          'Multiple args can be supplied'))\ndef ls(experiment_module, arg):\n    \"\"\"Print out a list of Experiment IDs.\"\"\"\n    if experiment_module:\n        module_to_load = experiment_module\n    else:\n        module_to_load = '__main__'\n\n    experiment_args = {}\n    for k, v in arg:\n        experiment_args[k] = v\n\n    loader = ExperimentLoader(experiment_args=experiment_args)\n    try:\n        experiments = loader.load_from_module(module_to_load)\n    except LoaderError as e:\n        print_error(str(e))\n        sys.exit(1)\n\n    if not experiments:\n        if experiment_module:\n            print_error(\n                'No experiments found in {}.'.format(experiment_module))\n        else:\n            print_error('No experiments found.')\n\n    for e in experiments:\n        click.echo('{}'.format(e.id))\n\n\n# https://stackoverflow.com/questions/48391777/nargs-equivalent-for-options-in-click\nclass OptionEatAll(click.Option):\n    def __init__(self, *args, **kwargs):\n        self.save_other_options = kwargs.pop('save_other_options', True)\n        nargs = kwargs.pop('nargs', -1)\n        assert nargs == -1, 'nargs, if set, must be -1 not {}'.format(nargs)\n        super(OptionEatAll, self).__init__(*args, **kwargs)\n        self._previous_parser_process = None\n        self._eat_all_parser = None\n\n    def add_to_parser(self, parser, ctx):\n        def parser_process(value, state):\n            value = str(value)\n            while state.rargs:\n                value = '{} {}'.format(value, state.rargs.pop(0))\n            self._previous_parser_process(value, state)\n\n        retval = super(OptionEatAll, self).add_to_parser(parser, ctx)\n\n        for name in self.opts:\n            our_parser = parser._long_opt.get(name) or parser._short_opt.get(\n                name)\n            if our_parser:\n                self._eat_all_parser = our_parser\n                self._previous_parser_process = our_parser.process\n                our_parser.process = parser_process\n                break\n\n        return retval\n\n\n@main.command(\n    'predict', short_help='Make predictions using a predict package.')\n@click.argument('predict_package')\n@click.argument('image_uri')\n@click.argument('output_uri')\n@click.option(\n    '--update-stats',\n    '-a',\n    is_flag=True,\n    help=('Run an analysis on this individual image, as '\n          'opposed to using any analysis like statistics '\n          'that exist in the prediction package'))\n@click.option(\n    '--channel-order',\n    cls=OptionEatAll,\n    help='List of indices comprising channel_order. Example: 2 1 0')\n@click.option(\n    '--export-config',\n    type=click.Path(exists=False),\n    help='Exports the configuration to the given output file.')\ndef predict(predict_package, image_uri, output_uri, update_stats,\n            channel_order, export_config):\n    \"\"\"Make predictions on the image at IMAGE_URI\n    using PREDICT_PACKAGE and store the\n    prediciton output at OUTPUT_URI.\n    \"\"\"\n    if channel_order is not None:\n        channel_order = [\n            int(channel_ind) for channel_ind in channel_order.split(' ')\n        ]\n\n    with RVConfig.get_tmp_dir() as tmp_dir:\n        predictor = rv.Predictor(predict_package, tmp_dir, update_stats,\n                                 channel_order)\n        predictor.predict(image_uri, output_uri, export_config)\n\n\n@main.command(\n    'run_command', short_help='Run a command from configuration file.')\n@click.argument('command_config_uri')\n@click.option('--tempdir')\ndef run_command(command_config_uri, tempdir):\n    \"\"\"Run a command from a serialized command configuration\n    at COMMAND_CONFIG_URI.\n    \"\"\"\n    if tempdir is not None:\n        RVConfig.set_tmp_dir(tempdir)\n    rv.runner.CommandRunner.run(command_config_uri)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "rastervision/cli/main.py"}]}