Completed
Push — master ( cc0c85...fb223d )
by Gonzalo
62:48
created

conda/cli/conda_argparse.py (2 issues)

1
# -*- coding: utf-8 -*-
2
from __future__ import absolute_import, division, print_function, unicode_literals
3
4
from argparse import (ArgumentParser as ArgumentParserBase, RawDescriptionHelpFormatter, SUPPRESS,
5
                      _CountAction, _HelpAction)
6
from logging import getLogger
7 7
import os
8
from os.path import abspath, expanduser, join
9 7
from subprocess import Popen
10 7
import sys
11 7
from textwrap import dedent
12 7
13 7
from .. import __version__
14
from ..base.constants import COMPATIBLE_SHELLS, CONDA_HOMEPAGE_URL, DepsModifier, UpdateModifier
15 7
from ..common.constants import NULL
16 7
17 7
log = getLogger(__name__)
18
19 7
# duplicated code in the interest of import efficiency
20
on_win = bool(sys.platform == "win32")
21
user_rc_path = abspath(expanduser('~/.condarc'))
22 7
escaped_user_rc_path = user_rc_path.replace("%", "%%")
23 7
escaped_sys_rc_path = abspath(join(sys.prefix, '.condarc')).replace("%", "%%")
24
25
26
def generate_parser():
27
    p = ArgumentParser(
28
        description='conda is a tool for managing and deploying applications,'
29
                    ' environments and packages.',
30
    )
31
    p.add_argument(
32
        '-V', '--version',
33 7
        action='version',
34 7
        version='conda %s' % __version__,
35
        help="Show the conda version number and exit."
36 7
    )
37
    p.add_argument(
38
        "--debug",
39 7
        action="store_true",
40
        help=SUPPRESS,
41 7
    )
42
    p.add_argument(
43
        "--json",
44
        action="store_true",
45
        help=SUPPRESS,
46
    )
47
    sub_parsers = p.add_subparsers(
48
        metavar='command',
49
        dest='cmd',
50
    )
51
    # http://bugs.python.org/issue9253
52
    # http://stackoverflow.com/a/18283730/1599393
53
    sub_parsers.required = True
54
55
    configure_parser_clean(sub_parsers)
56
    configure_parser_config(sub_parsers)
57
    configure_parser_create(sub_parsers)
58
    configure_parser_help(sub_parsers)
59
    configure_parser_info(sub_parsers)
60
    configure_parser_init(sub_parsers)
61
    configure_parser_install(sub_parsers)
62
    configure_parser_list(sub_parsers)
63
    configure_parser_package(sub_parsers)
64
    configure_parser_remove(sub_parsers)
65
    configure_parser_remove(sub_parsers, name='uninstall')
66
    configure_parser_search(sub_parsers)
67
    configure_parser_update(sub_parsers)
68
    configure_parser_update(sub_parsers, name='upgrade')
69
70
    return p
71
72
73
def generate_pip_parser():
74
    p = ArgumentParser(
75
        description='conda is a tool for managing and deploying applications,'
76
                    ' environments and packages.',
77
    )
78
    p.add_argument(
79 7
        '-V', '--version',
80 7
        action='version',
81 7
        version='conda %s' % __version__,
82 7
        help="Show the conda version number and exit."
83 7
    )
84 7
    sub_parsers = p.add_subparsers(
85 7
        metavar='command',
86
        dest='cmd',
87 7
    )
88 7
    configure_parser_info(sub_parsers)
89
    configure_parser_init(sub_parsers)
90 7
91 7
92
def do_call(args, parser):
93 7
    relative_mod, func_name = args.func.rsplit('.', 1)
94 7
    # func_name should always be 'execute'
95
    from importlib import import_module
96 7
    module = import_module(relative_mod, __name__.rsplit('.', 1)[0])
97
    exit_code = getattr(module, func_name)(args, parser)
98
    return exit_code
99
100
101 7
class ArgumentParser(ArgumentParserBase):
102 7
    def __init__(self, *args, **kwargs):
103
        if not kwargs.get('formatter_class'):
104 7
            kwargs['formatter_class'] = RawDescriptionHelpFormatter
105 7
        if 'add_help' not in kwargs:
106 7
            add_custom_help = True
107 7
            kwargs['add_help'] = False
108
        else:
109 7
            add_custom_help = False
110
        super(ArgumentParser, self).__init__(*args, **kwargs)
111
112 7
        if add_custom_help:
113 7
            add_parser_help(self)
114 7
115 7
        if self.description:
116
            self.description += "\n\nOptions:\n"
117 7
118 7
    def _get_action_from_name(self, name):
119
        """Given a name, get the Action instance registered with this parser.
120
        If only it were made available in the ArgumentError object. It is
121 7
        passed as it's first arg...
122 7
        """
123
        container = self._actions
124
        if name is None:
125 7
            return None
126
        for action in container:
127
            if '/'.join(action.option_strings) == name:
128
                return action
129
            elif action.metavar == name:
130
                return action
131
            elif action.dest == name:
132
                return action
133
134
    def error(self, message):
135
        import re
136
        from .find_commands import find_executable
137
        exc = sys.exc_info()[1]
138
        if exc:
139
            # this is incredibly lame, but argparse stupidly does not expose
140
            # reasonable hooks for customizing error handling
141
            if hasattr(exc, 'argument_name'):
142
                argument = self._get_action_from_name(exc.argument_name)
143
            else:
144
                argument = None
145
            if argument and argument.dest == "cmd":
146
                m = re.match(r"invalid choice: u?'([\w\-]*?)'", exc.message)
147
                if m:
148
                    cmd = m.group(1)
149
                    if not cmd:
150
                        self.print_help()
151
                        sys.exit(0)
152
                    else:
153
                        executable = find_executable('conda-' + cmd)
154
                        if not executable:
155
                            from ..exceptions import CommandNotFoundError
156
                            raise CommandNotFoundError(cmd)
157 7
                        args = [find_executable('conda-' + cmd)]
158
                        args.extend(sys.argv[2:])
159 7
                        p = Popen(args)
160
                        try:
161
                            p.communicate()
162
                        except KeyboardInterrupt:
163
                            p.wait()
164
                        finally:
165
                            sys.exit(p.returncode)
166
167
        super(ArgumentParser, self).error(message)
168 7
169 7
    def print_help(self):
170
        super(ArgumentParser, self).print_help()
171
172 7
        if sys.argv[1:] in ([], [''], ['help'], ['-h'], ['--help']):
173
            from .find_commands import find_commands
174
            other_commands = find_commands()
175
            if other_commands:
176
                builder = ['']
177
                builder.append("conda commands available from other packages:")
178
                builder.extend('  %s' % cmd for cmd in sorted(other_commands))
179
                print('\n'.join(builder))
180
181
182
class NullCountAction(_CountAction):
183
184
    @staticmethod
185
    def _ensure_value(namespace, name, value):
186
        if getattr(namespace, name, NULL) in (NULL, None):
187
            setattr(namespace, name, value)
188
        return getattr(namespace, name)
189
190
    def __call__(self, parser, namespace, values, option_string=None):
191
        new_count = self._ensure_value(namespace, self.dest, 0) + 1
192
        setattr(namespace, self.dest, new_count)
193
194
195
# #############################################################################################
196
#
197
# sub-parsers
198
#
199
# #############################################################################################
200
201 View Code Duplication
def configure_parser_clean(sub_parsers):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
202
    descr = dedent("""
203
    Remove unused packages and caches.
204
    """)
205
    example = dedent("""
206
    Examples:
207
208
        conda clean --tarballs
209
    """)
210
    p = sub_parsers.add_parser(
211
        'clean',
212
        description=descr,
213
        help=descr,
214
        epilog=example,
215
    )
216
217
    removal_target_options = p.add_argument_group("Removal Targets")
218
    removal_target_options.add_argument(
219
        "-a", "--all",
220
        action="store_true",
221
        help="Remove index cache, lock files, unused cache packages, and tarballs.",
222
    )
223
    removal_target_options.add_argument(
224
        "-i", "--index-cache",
225
        action="store_true",
226
        help="Remove index cache.",
227
    )
228
    removal_target_options.add_argument(
229
        "-l", "--lock",
230
        action="store_true",
231
        help="Remove all conda lock files.",
232
    )
233
    removal_target_options.add_argument(
234
        '-p', '--packages',
235
        action='store_true',
236
        help="Remove unused cached packages. Warning: This does not check for symlinked packages.",
237
    )
238
    removal_target_options.add_argument(
239
        '-s', '--source-cache',
240
        action='store_true',
241
        # help="Remove files from the source cache of conda build.",
242
        help=SUPPRESS,
243
    )
244
    removal_target_options.add_argument(
245
        "-t", "--tarballs",
246
        action="store_true",
247
        help="Remove cached package tarballs.",
248
    )
249
250
    add_output_and_prompt_options(p)
251
252
    p.set_defaults(func='.main_clean.execute')
253
254
255
def configure_parser_info(sub_parsers):
256
    help = "Display information about current conda install."
257
258
    p = sub_parsers.add_parser(
259
        'info',
260
        description=help,
261
        help=help,
262
    )
263
    add_parser_json(p)
264
    p.add_argument(
265
        "--offline",
266
        action='store_true',
267
        default=NULL,
268
        help=SUPPRESS,
269
    )
270
    p.add_argument(
271
        '-a', "--all",
272
        action="store_true",
273
        help="Show all information.",
274
    )
275
    p.add_argument(
276
        '--base',
277
        action='store_true',
278
        help='Display base environment path.',
279
    )
280
    # TODO: deprecate 'conda info --envs' and create 'conda list --envs'
281
    p.add_argument(
282
        '-e', "--envs",
283
        action="store_true",
284
        help="List all known conda environments.",
285
    )
286
    p.add_argument(
287
        '-l', "--license",
288
        action="store_true",
289
        help="Display information about the local conda licenses list.",
290
    )
291
    p.add_argument(
292
        '-s', "--system",
293
        action="store_true",
294
        help="List environment variables.",
295
    )
296
    p.add_argument(
297
        '--root',
298
        action='store_true',
299
        help=SUPPRESS,
300
        dest='base',
301
    )
302
    p.add_argument(
303
        '--unsafe-channels',
304
        action='store_true',
305
        help='Display list of channels with tokens exposed.',
306
    )
307
308
    # TODO: deprecate 'conda info <PACKAGE>'
309
    p.add_argument(
310
        'packages',
311
        action="store",
312
        nargs='*',
313
        help="Display information about packages.",
314
    )
315
316
    p.set_defaults(func='.main_info.execute')
317
318
319
def configure_parser_config(sub_parsers):
320
    descr = dedent("""
321
    Modify configuration values in .condarc.  This is modeled after the git
322
    config command.  Writes to the user .condarc file (%s) by default.
323
324
    """) % escaped_user_rc_path
325
326
    # Note, the extra whitespace in the list keys is on purpose. It's so the
327
    # formatting from help2man is still valid YAML (otherwise it line wraps the
328
    # keys like "- conda - defaults"). Technically the parser here still won't
329
    # recognize it because it removes the indentation, but at least it will be
330
    # valid.
331
    additional_descr = dedent("""
332
    See `conda config --describe` or %s/docs/config.html
333
    for details on all the options that can go in .condarc.
334
335
    Examples:
336
337
    Display all configuration values as calculated and compiled:
338
339
        conda config --show
340
341
    Display all identified configuration sources:
342
343
        conda config --show-sources
344
345
    Describe all available configuration options:
346
347
        conda config --describe
348
349
    Add the conda-canary channel:
350
351
        conda config --add channels conda-canary
352
353
    Set the output verbosity to level 3 (highest) for the current activate environment:
354
355
        conda config --set verbosity 3 --env
356
357
    Add the 'conda-forge' channel as a backup to 'defaults':
358
359
        conda config --append channels conda-forge
360
361
    """) % CONDA_HOMEPAGE_URL
362
363
    p = sub_parsers.add_parser(
364
        'config',
365
        description=descr,
366
        help=descr,
367
        epilog=additional_descr,
368
    )
369
    add_parser_json(p)
370
371
    # TODO: use argparse.FileType
372
    config_file_location_group = p.add_argument_group(
373
        'Config File Location Selection',
374
        "Without one of these flags, the user config file at '%s' is used." % escaped_user_rc_path
375
    )
376
    location = config_file_location_group.add_mutually_exclusive_group()
377
    location.add_argument(
378
        "--system",
379
        action="store_true",
380
        help="Write to the system .condarc file at '%s'." % escaped_sys_rc_path,
381
    )
382
    location.add_argument(
383
        "--env",
384
        action="store_true",
385
        help="Write to the active conda environment .condarc file (%s). "
386
             "If no environment is active, write to the user config file (%s)."
387
             "" % (
388
                 os.getenv('CONDA_PREFIX', "<no active environment>").replace("%", "%%"),
389
                 escaped_user_rc_path,
390
             ),
391
    )
392
    location.add_argument(
393
        "--file",
394
        action="store",
395
        help="Write to the given file."
396
    )
397
398
    # XXX: Does this really have to be mutually exclusive. I think the below
399
    # code will work even if it is a regular group (although combination of
400
    # --add and --remove with the same keys will not be well-defined).
401
    _config_subcommands = p.add_argument_group("Config Subcommands")
402
    config_subcommands = _config_subcommands.add_mutually_exclusive_group()
403
    config_subcommands.add_argument(
404
        "--show",
405
        nargs='*',
406
        default=None,
407
        help="Display configuration values as calculated and compiled. "
408
             "If no arguments given, show information for all configuration values.",
409
    )
410
    config_subcommands.add_argument(
411
        "--show-sources",
412
        action="store_true",
413
        help="Display all identified configuration sources.",
414
    )
415
    config_subcommands.add_argument(
416
        "--validate",
417
        action="store_true",
418
        help="Validate all configuration sources.",
419
    )
420
    config_subcommands.add_argument(
421
        "--describe",
422
        nargs='*',
423
        default=None,
424
        help="Describe given configuration parameters. If no arguments given, show "
425
             "information for all configuration parameters.",
426
    )
427
    config_subcommands.add_argument(
428
        "--write-default",
429
        action="store_true",
430
        help="Write the default configuration to a file. "
431
             "Equivalent to `conda config --describe > ~/.condarc`.",
432
    )
433
434
    _config_modifiers = p.add_argument_group("Config Modifiers")
435
    config_modifiers = _config_modifiers.add_mutually_exclusive_group()
436
    config_modifiers.add_argument(
437
        "--get",
438
        nargs='*',
439
        action="store",
440
        help="Get a configuration value.",
441
        default=None,
442
        metavar='KEY',
443
    )
444
    config_modifiers.add_argument(
445
        "--append",
446
        nargs=2,
447
        action="append",
448
        help="""Add one configuration value to the end of a list key.""",
449
        default=[],
450
        metavar=('KEY', 'VALUE'),
451
    )
452
    config_modifiers.add_argument(
453
        "--prepend", "--add",
454
        nargs=2,
455
        action="append",
456
        help="""Add one configuration value to the beginning of a list key.""",
457
        default=[],
458
        metavar=('KEY', 'VALUE'),
459
    )
460
    config_modifiers.add_argument(
461
        "--set",
462
        nargs=2,
463
        action="append",
464
        help="""Set a boolean or string key""",
465
        default=[],
466
        metavar=('KEY', 'VALUE'),
467
    )
468
    config_modifiers.add_argument(
469
        "--remove",
470
        nargs=2,
471
        action="append",
472
        help="""Remove a configuration value from a list key. This removes
473
    all instances of the value.""",
474
        default=[],
475
        metavar=('KEY', 'VALUE'),
476
    )
477
    config_modifiers.add_argument(
478
        "--remove-key",
479
        nargs=1,
480
        action="append",
481
        help="""Remove a configuration key (and all its values).""",
482
        default=[],
483
        metavar="KEY",
484
    )
485
    config_modifiers.add_argument(
486
        "--stdin",
487
        action="store_true",
488
        help="Apply configuration information given in yaml format piped through stdin.",
489
    )
490
491
    p.add_argument(
492
        "-f", "--force",
493
        action="store_true",
494
        default=NULL,
495
        help=SUPPRESS,  # TODO: No longer used.  Remove in a future release.
496
    )
497
498
    p.set_defaults(func='.main_config.execute')
499
500
501
def configure_parser_create(sub_parsers):
502
    help = "Create a new conda environment from a list of specified packages. "
503
    descr = (help +
504
             "To use the created environment, use 'source activate "
505
             "envname' look in that directory first.  This command requires either "
506
             "the -n NAME or -p PREFIX option.")
507
508
    example = dedent("""
509
    Examples:
510
511
        conda create -n myenv sqlite
512
513
    """)
514
    p = sub_parsers.add_parser(
515
        'create',
516
        description=descr,
517
        help=help,
518
        epilog=example,
519
    )
520
    p.add_argument(
521
        "--clone",
522
        action="store",
523
        help='Path to (or name of) existing local environment.',
524
        metavar='ENV',
525
    )
526
    solver_mode_options, package_install_options = add_parser_create_install_update(p)
527
    solver_mode_options.add_argument(
528
        "--no-default-packages",
529
        action="store_true",
530
        help='Ignore create_default_packages in the .condarc file.',
531
    )
532
    p.add_argument(
533
        '-m', "--mkdir",
534
        action="store_true",
535
        help=SUPPRESS,
536
    )
537
    p.set_defaults(func='.main_create.execute')
538
539
540
def configure_parser_init(sub_parsers):
541
    help = "Initialize conda for shell interaction. [Experimental]"
542
    descr = help
543
544
    epilog = dedent("""
545
    Key parts of conda's functionality require that it interact directly with the shell
546
    within which conda is being invoked. The `conda activate` and `conda deactivate` commands
547
    specifically are shell-level commands. That is, they affect the state (e.g. environment
548
    variables) of the shell context being interacted with. Other core commands, like
549
    `conda create` and `conda install`, also necessarily interact with the shell environment.
550
    They're therefore implemented in ways specific to each shell. Each shell must be configured
551
    to make use of them.
552
553
    This command makes changes to your system that are specific and customized for each shell.
554
    To see the specific files and locations on your system that will be affected before, use the
555
    '--dry-run' flag.  To see the exact changes that are being or will be made to each location,
556
    use the '--verbose' flag.
557
558
    IMPORTANT: After running `conda init`, most shells will need to be closed and restarted
559
               for changes to take effect.
560
561
    """)
562
563
    # dev_example = dedent("""
564
    #     # An example for creating an environment to develop on conda's own code. Clone the
565
    #     # conda repo and install a dedicated miniconda within it. Remove all remnants of
566
    #     # conda source files in the `site-packages` directory associated with
567
    #     # `~/conda/devenv/bin/python`. Write a `conda.pth` file in that `site-packages`
568
    #     # directory pointing to source code in `~/conda`, the current working directory.
569
    #     # Write commands to stdout, suitable for bash `eval`, that sets up the current
570
    #     # shell as a dev environment.
571
    #
572
    #         $ CONDA_PROJECT_ROOT="~/conda"
573
    #         $ git clone [email protected]:conda/conda "$CONDA_PROJECT_ROOT"
574
    #         $ cd "$CONDA_PROJECT_ROOT"
575
    #         $ wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
576
    #         $ bash Miniconda3-latest-Linux-x86_64.sh -bfp ./devenv
577
    #         $ eval "$(./devenv/bin/python -m conda init --dev bash)"
578
    #
579
    #
580
    # """)
581
582
    p = sub_parsers.add_parser(
583
        'init',
584
        description=descr,
585
        help=help,
586
        epilog=epilog,
587
    )
588
589
    p.add_argument(
590
        "--dev",
591
        action="store_true",
592
        help=SUPPRESS,
593
        default=NULL,
594
    )
595
596
    p.add_argument(
597
        "--all",
598
        action="store_true",
599
        help="Initialize all currently available shells.",
600
        default=NULL,
601
    )
602
603
    setup_type_group = p.add_argument_group('setup type')
604
    setup_type_group.add_argument(
605
        "--install",
606
        action="store_true",
607
        help=SUPPRESS,
608
        default=NULL,
609
    )
610
    setup_type_group.add_argument(
611
        "--user",
612
        action="store_true",
613
        # help="Initialize conda for the current user (default).",
614
        help=SUPPRESS,
615
        default=NULL,
616
    )
617
    setup_type_group.add_argument(
618
        "--no-user",
619
        action="store_false",
620
        # help="Don't initialize conda for the current user (default).",
621
        help=SUPPRESS,
622
        default=NULL,
623
    )
624
    setup_type_group.add_argument(
625
        "--system",
626
        action="store_true",
627
        # help="Initialize conda for all users on the system.",
628
        help=SUPPRESS,
629
        default=NULL,
630
    )
631
632
    p.add_argument(
633
        'shells',
634
        nargs='*',
635
        help="One or more shells to be initialized. If not given, the default value is "
636
             "'bash' on unix and 'cmd.exe' on Windows. Use the '--all' flag to initialize "
637
             "all shells. Currently compatible shells are {%s}"
638
             % ", ".join(sorted(COMPATIBLE_SHELLS)),
639
    )
640
641
    if on_win:
642
        p.add_argument(
643
            "--anaconda-prompt",
644
            action="store_true",
645
            help="Add an 'Anaconda Prompt' icon to your desktop.",
646
            default=NULL,
647
        )
648
649
    add_parser_json(p)
650
    p.add_argument(
651
        "--dry-run",
652
        action="store_true",
653
        help="Only display what would have been done.",
654
    )
655
    p.set_defaults(func='.main_init.execute')
656
657
658
def configure_parser_help(sub_parsers):
659
    descr = "Displays a list of available conda commands and their help strings."
660
661
    p = sub_parsers.add_parser(
662
        'help',
663
        description=descr,
664
        help=descr,
665
    )
666
    p.add_argument(
667
        'command',
668
        metavar='COMMAND',
669
        action="store",
670
        nargs='?',
671
        help="Print help information for COMMAND (same as: conda COMMAND --help).",
672
    )
673
    p.set_defaults(func='.main_help.execute')
674
675
676 View Code Duplication
def configure_parser_install(sub_parsers):
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
677
    help = "Installs a list of packages into a specified conda environment."
678
    descr = dedent(help + """
679
680
    This command accepts a list of package specifications (e.g, bitarray=0.8)
681
    and installs a set of packages consistent with those specifications and
682
    compatible with the underlying environment. If full compatibility cannot
683
    be assured, an error is reported and the environment is not changed.
684
685
    Conda attempts to install the newest versions of the requested packages. To
686
    accomplish this, it may update some packages that are already installed, or
687
    install additional packages. To prevent existing packages from updating,
688
    use the --no-update-deps option. This may force conda to install older
689
    versions of the requested packages, and it does not prevent additional
690
    dependency packages from being installed.
691
692
    If you wish to skip dependency checking altogether, use the '--no-deps'
693
    option. This may result in an environment with incompatible packages, so
694
    this option must be used with great caution.
695
696
    conda can also be called with a list of explicit conda package filenames
697
    (e.g. ./lxml-3.2.0-py27_0.tar.bz2). Using conda in this mode implies the
698
    --no-deps option, and should likewise be used with great caution. Explicit
699
    filenames and package specifications cannot be mixed in a single command.
700
    """)
701
    example = dedent("""
702
    Examples:
703
704
        conda install -n myenv scipy
705
706
    """)
707
    p = sub_parsers.add_parser(
708
        'install',
709
        description=descr,
710
        help=help,
711
        epilog=example,
712
    )
713
    p.add_argument(
714
        "--revision",
715
        action="store",
716
        help="Revert to the specified REVISION.",
717
        metavar='REVISION',
718
    )
719
720
    solver_mode_options, package_install_options = add_parser_create_install_update(p)
721
722
    add_parser_prune(solver_mode_options)
723
    solver_mode_options.add_argument(
724
        "--force-reinstall",
725
        action="store_true",
726
        default=NULL,
727
        help="Ensure that any user-requested package for the current operation is uninstalled and "
728
             "reinstalled, even if that package already exists in the environment.",
729
    )
730
    add_parser_update_modifiers(solver_mode_options)
731
    package_install_options.add_argument(
732
        '-m', "--mkdir",
733
        action="store_true",
734
        help="Create the environment directory if necessary.",
735
    )
736
    package_install_options.add_argument(
737
        "--clobber",
738
        action="store_true",
739
        default=NULL,
740
        help="Allow clobbering of overlapping file paths within packages, "
741
             "and suppress related warnings.",
742
    )
743
    p.set_defaults(func='.main_install.execute')
744
745
746
def configure_parser_list(sub_parsers):
747
    descr = "List linked packages in a conda environment."
748
749
    # Note, the formatting of this is designed to work well with help2man
750
    examples = dedent("""
751
    Examples:
752
753
    List all packages in the current environment:
754
755
        conda list
756
757
    List all packages installed into the environment 'myenv':
758
759
        conda list -n myenv
760
761
    Save packages for future use:
762
763
        conda list --export > package-list.txt
764
765
    Reinstall packages from an export file:
766
767
        conda create -n myenv --file package-list.txt
768
769
    """)
770
    p = sub_parsers.add_parser(
771
        'list',
772
        description=descr,
773
        help=descr,
774
        formatter_class=RawDescriptionHelpFormatter,
775
        epilog=examples,
776
        add_help=False,
777
    )
778
    add_parser_help(p)
779
    add_parser_prefix(p)
780
    add_parser_json(p)
781
    add_parser_show_channel_urls(p)
782
    p.add_argument(
783
        '-c', "--canonical",
784
        action="store_true",
785
        help="Output canonical names of packages only. Implies --no-pip. ",
786
    )
787
    p.add_argument(
788
        '-f', "--full-name",
789
        action="store_true",
790
        help="Only search for full names, i.e., ^<regex>$.",
791
    )
792
    p.add_argument(
793
        "--explicit",
794
        action="store_true",
795
        help="List explicitly all installed conda packaged with URL "
796
             "(output may be used by conda create --file).",
797
    )
798
    p.add_argument(
799
        "--md5",
800
        action="store_true",
801
        help="Add MD5 hashsum when using --explicit",
802
    )
803
    p.add_argument(
804
        '-e', "--export",
805
        action="store_true",
806
        help="Output requirement string only (output may be used by "
807
             " conda create --file).",
808
    )
809
    p.add_argument(
810
        '-r', "--revisions",
811
        action="store_true",
812
        help="List the revision history and exit.",
813
    )
814
    p.add_argument(
815
        "--no-pip",
816
        action="store_false",
817
        default=True,
818
        dest="pip",
819
        help="Do not include pip-only installed packages.")
820
    p.add_argument(
821
        'regex',
822
        action="store",
823
        nargs="?",
824
        help="List only packages matching this regular expression.",
825
    )
826
    p.set_defaults(func='.main_list.execute')
827
828
829
def configure_parser_package(sub_parsers):
830
    descr = "Low-level conda package utility. (EXPERIMENTAL)"
831
    p = sub_parsers.add_parser(
832
        'package',
833
        description=descr,
834
        help=descr,
835
    )
836
    add_parser_prefix(p)
837
    p.add_argument(
838
        '-w', "--which",
839
        metavar="PATH",
840
        nargs='+',
841
        action="store",
842
        help="Given some PATH print which conda package the file came from.",
843
    )
844
    p.add_argument(
845
        '-r', "--reset",
846
        action="store_true",
847
        help="Remove all untracked files and exit.",
848
    )
849
    p.add_argument(
850
        '-u', "--untracked",
851
        action="store_true",
852
        help="Display all untracked files and exit.",
853
    )
854
    p.add_argument(
855
        "--pkg-name",
856
        action="store",
857
        default="unknown",
858
        help="Package name of the created package.",
859
    )
860
    p.add_argument(
861
        "--pkg-version",
862
        action="store",
863
        default="0.0",
864
        help="Package version of the created package.",
865
    )
866
    p.add_argument(
867
        "--pkg-build",
868
        action="store",
869
        default=0,
870
        help="Package build number of the created package.",
871
    )
872
    p.set_defaults(func='.main_package.execute')
873
874
875
def configure_parser_remove(sub_parsers, name='remove'):
876
    help = "%s a list of packages from a specified conda environment."
877
    descr = dedent(help + """
878
879
    This command will also remove any package that depends on any of the
880
    specified packages as well---unless a replacement can be found without
881
    that dependency. If you wish to skip this dependency checking and remove
882
    just the requested packages, add the '--force' option. Note however that
883
    this may result in a broken environment, so use this with caution.
884
    """)
885
    example = dedent("""
886
    Examples:
887
888
        conda %s -n myenv scipy
889
890
    """)
891
892
    uninstall_help = "Alias for conda remove."
893
    if name == 'remove':
894
        p = sub_parsers.add_parser(
895
            name,
896
            formatter_class=RawDescriptionHelpFormatter,
897
            description=descr % name.capitalize(),
898
            help=help % name.capitalize(),
899
            epilog=example % name,
900
            add_help=False,
901
        )
902
    else:
903
        p = sub_parsers.add_parser(
904
            name,
905
            formatter_class=RawDescriptionHelpFormatter,
906
            description=uninstall_help,
907
            help=uninstall_help,
908
            epilog=example % name,
909
            add_help=False,
910
        )
911
    add_parser_help(p)
912
    add_parser_pscheck(p)
913
914
    add_parser_prefix(p)
915
    add_parser_channels(p)
916
917
    solver_mode_options = p.add_argument_group("Solver Mode Modifiers")
918
    solver_mode_options.add_argument(
919
        "--all",
920
        action="store_true",
921
        help="%s all packages, i.e., the entire environment." % name.capitalize(),
922
    )
923
    solver_mode_options.add_argument(
924
        "--features",
925
        action="store_true",
926
        help="%s features (instead of packages)." % name.capitalize(),
927
    )
928
    solver_mode_options.add_argument(
929
        "--force-remove", "--force",
930
        action="store_true",
931
        help="Forces removal of a package without removing packages that depend on it. "
932
             "Using this option will usually leave your environment in a broken and "
933
             "inconsistent state.",
934
        dest='force_remove',
935
    )
936
    solver_mode_options.add_argument(
937
        "--no-pin",
938
        action="store_true",
939
        dest='ignore_pinned',
940
        default=NULL,
941
        help="Ignore pinned file.",
942
    )
943
    add_parser_prune(solver_mode_options)
944
945
    add_parser_networking(p)
946
    add_output_and_prompt_options(p)
947
948
    p.add_argument(
949
        'package_names',
950
        metavar='package_name',
951
        action="store",
952
        nargs='*',
953
        help="Package names to %s from the environment." % name,
954
    )
955
956
    p.set_defaults(func='.main_remove.execute')
957
958
959
def configure_parser_search(sub_parsers):
960
    descr = dedent("""Search for packages and display associated information.
961
    The input is a MatchSpec, a query language for conda packages.
962
    See examples below.
963
    """)
964
965
    example = dedent("""
966
    Examples:
967
968
    Search for a specific package named 'scikit-learn':
969
970
        conda search scikit-learn
971
972
    Search for packages containing 'scikit' in the package name:
973
974
        conda search *scikit*
975
976
    Note that your shell may expand '*' before handing the command over to conda.
977
    Therefore it is sometimes necessary to use single or double quotes around the query.
978
979
        conda search '*scikit'
980
        conda search "*scikit*"
981
982
    Search for packages for 64-bit Linux (by default, packages for your current
983
    platform are shown):
984
985
        conda search numpy[subdir=linux-64]
986
987
    Search for a specific version of a package:
988
989
        conda search 'numpy>=1.12'
990
991
    Search for a package on a specific channel
992
993
        conda search conda-forge::numpy
994
        conda search 'numpy[channel=conda-forge, subdir=osx-64]'
995
    """)
996
    p = sub_parsers.add_parser(
997
        'search',
998
        description=descr,
999
        help=descr,
1000
        epilog=example,
1001
    )
1002
    p.add_argument(
1003
        "--envs",
1004
        action="store_true",
1005
        help="Search all of the current user's environments. If run as Administrator "
1006
             "(on Windows) or UID 0 (on unix), search all known environments on the system.",
1007
    )
1008
    p.add_argument(
1009
        '-i', "--info",
1010
        action="store_true",
1011
        help="Provide detailed information about each package."
1012
    )
1013
    p.add_argument(
1014
        '--subdir', '--platform',
1015
        action='store',
1016
        dest='subdir',
1017
        help="Search the given subdir. Should be formatted like 'osx-64', 'linux-32', "
1018
             "'win-64', and so on. The default is to search the current platform.",
1019
        default=NULL,
1020
    )
1021
    p.add_argument(
1022
        'match_spec',
1023
        default='*',
1024
        nargs='?',
1025
        help=SUPPRESS,
1026
    )
1027
1028
    p.add_argument(
1029
        "--canonical",
1030
        action="store_true",
1031
        help=SUPPRESS,
1032
    )
1033
    p.add_argument(
1034
        '-f', "--full-name",
1035
        action="store_true",
1036
        help=SUPPRESS,
1037
    )
1038
    p.add_argument(
1039
        "--names-only",
1040
        action="store_true",
1041
        help=SUPPRESS,
1042
    )
1043
    add_parser_known(p)
1044
    p.add_argument(
1045
        '-o', "--outdated",
1046
        action="store_true",
1047
        help=SUPPRESS,
1048
    )
1049
    p.add_argument(
1050
        "--spec",
1051
        action="store_true",
1052
        help=SUPPRESS,
1053
    )
1054
    p.add_argument(
1055
        "--reverse-dependency",
1056
        action="store_true",
1057
        # help="Perform a reverse dependency search. Use 'conda search package --info' "
1058
        #      "to see the dependencies of a package.",
1059
        help=SUPPRESS,  # TODO: re-enable once we have --reverse-dependency working again
1060
    )
1061
1062
    add_parser_channels(p)
1063
    add_parser_networking(p)
1064
    add_parser_json(p)
1065
    p.set_defaults(func='.main_search.execute')
1066
1067
1068
def configure_parser_update(sub_parsers, name='update'):
1069
    help = "Updates conda packages to the latest compatible version."
1070
    descr = dedent(help + """
1071
1072
    This command accepts a list of package names and updates them to the latest
1073
    versions that are compatible with all other packages in the environment.
1074
1075
    Conda attempts to install the newest versions of the requested packages. To
1076
    accomplish this, it may update some packages that are already installed, or
1077
    install additional packages. To prevent existing packages from updating,
1078
    use the --no-update-deps option. This may force conda to install older
1079
    versions of the requested packages, and it does not prevent additional
1080
    dependency packages from being installed.
1081
    """)
1082
    example = dedent("""
1083
    Examples:
1084
1085
        conda %s -n myenv scipy
1086
1087
    """)
1088
1089
    alias_help = "Alias for conda update."
1090
    if name == 'update':
1091
        p = sub_parsers.add_parser(
1092
            'update',
1093
            description=descr,
1094
            help=help,
1095
            epilog=example % name,
1096
        )
1097
    else:
1098
        p = sub_parsers.add_parser(
1099
            name,
1100
            description=alias_help,
1101
            help=alias_help,
1102
            epilog=example % name,
1103
        )
1104
    solver_mode_options, package_install_options = add_parser_create_install_update(p)
1105
1106
    add_parser_prune(solver_mode_options)
1107
    solver_mode_options.add_argument(
1108
        "--force-reinstall",
1109
        action="store_true",
1110
        default=NULL,
1111
        help="Ensure that any user-requested package for the current operation is uninstalled and "
1112
             "reinstalled, even if that package already exists in the environment.",
1113
    )
1114
    add_parser_update_modifiers(solver_mode_options)
1115
1116
    package_install_options.add_argument(
1117
        "--clobber",
1118
        action="store_true",
1119
        default=NULL,
1120
        help="Allow clobbering of overlapping file paths within packages, "
1121
             "and suppress related warnings.",
1122
    )
1123
    p.set_defaults(func='.main_update.execute')
1124
1125
1126
# #############################################################################################
1127
#
1128
# parser helpers
1129
#
1130
# #############################################################################################
1131
1132
def add_parser_create_install_update(p):
1133
    add_parser_prefix(p)
1134
    add_parser_channels(p)
1135
    solver_mode_options = add_parser_solver_mode(p)
1136
    package_install_options = add_parser_package_install_options(p)
1137
    add_parser_networking(p)
1138
1139
    output_and_prompt_options = add_output_and_prompt_options(p)
1140
    output_and_prompt_options.add_argument(
1141
        "--download-only",
1142
        action="store_true",
1143
        default=NULL,
1144
        help="Solve an environment and ensure package caches are populated, but exit "
1145
             "prior to unlinking and linking packages into the prefix.",
1146
    )
1147
    add_parser_show_channel_urls(output_and_prompt_options)
1148
1149
    add_parser_pscheck(p)
1150
    add_parser_known(p)
1151
1152
    # Add the file kwarg. We don't use {action="store", nargs='*'} as we don't
1153
    # want to gobble up all arguments after --file.
1154
    p.add_argument(
1155
        "--file",
1156
        default=[],
1157
        action='append',
1158
        help="Read package versions from the given file. Repeated file "
1159
             "specifications can be passed (e.g. --file=file1 --file=file2).",
1160
    )
1161
    p.add_argument(
1162
        'packages',
1163
        metavar='package_spec',
1164
        action="store",
1165
        nargs='*',
1166
        help="Packages to install or update in the conda environment.",
1167
    )
1168
1169
    return solver_mode_options, package_install_options
1170
1171
1172
def add_parser_pscheck(p):
1173
    p.add_argument(
1174
        "--force-pscheck",
1175
        action="store_true",
1176
        help=SUPPRESS
1177
    )
1178
1179
1180
def add_parser_show_channel_urls(p):
1181
    p.add_argument(
1182
        "--show-channel-urls",
1183
        action="store_true",
1184
        dest="show_channel_urls",
1185
        default=NULL,
1186
        help="Show channel urls. "
1187
             "Overrides the value given by `conda config --show show_channel_urls`.",
1188
    )
1189
    p.add_argument(
1190
        "--no-show-channel-urls",
1191
        action="store_false",
1192
        dest="show_channel_urls",
1193
        help=SUPPRESS,
1194
    )
1195
1196
1197
def add_parser_help(p):
1198
    """
1199
    So we can use consistent capitalization and periods in the help. You must
1200
    use the add_help=False argument to ArgumentParser or add_parser to use
1201
    this. Add this first to be consistent with the default argparse output.
1202
1203
    """
1204
    p.add_argument(
1205
        '-h', '--help',
1206
        action=_HelpAction,
1207
        help="Show this help message and exit.",
1208
    )
1209
1210
1211
def add_parser_prefix(p):
1212
    target_environment_group = p.add_argument_group("Target Environment Specification")
1213
    npgroup = target_environment_group.add_mutually_exclusive_group()
1214
    npgroup.add_argument(
1215
        '-n', "--name",
1216
        action="store",
1217
        help="Name of environment.",
1218
        metavar="ENVIRONMENT",
1219
    )
1220
    npgroup.add_argument(
1221
        '-p', "--prefix",
1222
        action="store",
1223
        help="Full path to environment location (i.e. prefix).",
1224
        metavar='PATH',
1225
    )
1226
1227
1228
def add_parser_json(p):
1229
    output_and_prompt_options = p.add_argument_group("Output, Prompt, and Flow Control Options")
1230
    output_and_prompt_options.add_argument(
1231
        "--debug",
1232
        action="store_true",
1233
        default=NULL,
1234
        help=SUPPRESS,
1235
    )
1236
    output_and_prompt_options.add_argument(
1237
        "--json",
1238
        action="store_true",
1239
        default=NULL,
1240
        help="Report all output as json. Suitable for using conda programmatically."
1241
    )
1242
    output_and_prompt_options.add_argument(
1243
        "-v", "--verbose",
1244
        action=NullCountAction,
1245
        help="Use once for info, twice for debug, three times for trace.",
1246
        dest="verbosity",
1247
        default=NULL,
1248
    )
1249
    output_and_prompt_options.add_argument(
1250
        '-q', "--quiet",
1251
        action="store_true",
1252
        default=NULL,
1253
        help="Do not display progress bar.",
1254
    )
1255
    return output_and_prompt_options
1256
1257
1258
def add_output_and_prompt_options(p):
1259
    output_and_prompt_options = p.add_argument_group("Output, Prompt, and Flow Control Options")
1260
    output_and_prompt_options.add_argument(
1261
        "--debug",
1262
        action="store_true",
1263
        default=NULL,
1264
        help=SUPPRESS,
1265
    )
1266
    output_and_prompt_options.add_argument(
1267
        "--dry-run",
1268
        action="store_true",
1269
        help="Only display what would have been done.",
1270
    )
1271
    output_and_prompt_options.add_argument(
1272
        "--json",
1273
        action="store_true",
1274
        default=NULL,
1275
        help="Report all output as json. Suitable for using conda programmatically."
1276
    )
1277
    output_and_prompt_options.add_argument(
1278
        '-q', "--quiet",
1279
        action="store_true",
1280
        default=NULL,
1281
        help="Do not display progress bar.",
1282
    )
1283
    output_and_prompt_options.add_argument(
1284
        "-v", "--verbose",
1285
        action=NullCountAction,
1286
        help="Can be used multiple times. Once for INFO, twice for DEBUG, three times for TRACE.",
1287
        dest="verbosity",
1288
        default=NULL,
1289
    )
1290
    output_and_prompt_options.add_argument(
1291
        "-y", "--yes",
1292
        action="store_true",
1293
        default=NULL,
1294
        help="Do not ask for confirmation.",
1295
    )
1296
    return output_and_prompt_options
1297
1298
1299
def add_parser_channels(p):
1300
    channel_customization_options = p.add_argument_group("Channel Customization")
1301
    channel_customization_options.add_argument(
1302
        '-c', '--channel',
1303
        dest='channel',  # apparently conda-build uses this; someday rename to channels are remove context.channels alias to channel  # NOQA
1304
        # TODO: if you ever change 'channel' to 'channels', make sure you modify the context.channels property accordingly # NOQA
1305
        action="append",
1306
        help="""Additional channel to search for packages. These are URLs searched in the order
1307
        they are given (including file:// for local directories).  Then, the defaults
1308
        or channels from .condarc are searched (unless --override-channels is given).  You can use
1309
        'defaults' to get the default packages for conda.  You can also use any name and the
1310
        .condarc channel_alias value will be prepended.  The default channel_alias
1311
        is http://conda.anaconda.org/.""",
1312
    )
1313
    channel_customization_options.add_argument(
1314
        "--use-local",
1315
        action="store_true",
1316
        default=NULL,
1317
        help="Use locally built packages. Identical to '-c local'.",
1318
    )
1319
    channel_customization_options.add_argument(
1320
        "--override-channels",
1321
        action="store_true",
1322
        help="""Do not search default or .condarc channels.  Requires --channel.""",
1323
    )
1324
    return channel_customization_options
1325
1326
1327
def add_parser_solver_mode(p):
1328
    solver_mode_options = p.add_argument_group("Solver Mode Modifiers")
1329
    deps_modifiers = solver_mode_options.add_mutually_exclusive_group()
1330
    solver_mode_options.add_argument(
1331
        "--channel-priority",
1332
        action="store_true",
1333
        dest="channel_priority",
1334
        default=NULL,
1335
        help=SUPPRESS,
1336
    )
1337
    solver_mode_options.add_argument(
1338
        "--no-channel-priority",
1339
        action="store_false",
1340
        dest="channel_priority",
1341
        default=NULL,
1342
        help="Package version takes precedence over channel priority. "
1343
             "Overrides the value given by `conda config --show channel_priority`."
1344
    )
1345
    deps_modifiers.add_argument(
1346
        "--no-deps",
1347
        action="store_const",
1348
        const=DepsModifier.NO_DEPS,
1349
        dest="deps_modifier",
1350
        help="Do not install, update, remove, or change dependencies. This WILL lead "
1351
             "to broken environments and inconsistent behavior. Use at your own risk.",
1352
        default=NULL,
1353
    )
1354
    deps_modifiers.add_argument(
1355
        "--only-deps",
1356
        action="store_const",
1357
        const=DepsModifier.ONLY_DEPS,
1358
        dest="deps_modifier",
1359
        help="Only install dependencies.",
1360
        default=NULL,
1361
    )
1362
    solver_mode_options.add_argument(
1363
        "--no-pin",
1364
        action="store_true",
1365
        dest='ignore_pinned',
1366
        default=NULL,
1367
        help="Ignore pinned file.",
1368
    )
1369
    return solver_mode_options
1370
1371
1372
def add_parser_update_modifiers(solver_mode_options):
1373
    update_modifiers = solver_mode_options.add_mutually_exclusive_group()
1374
    update_modifiers.add_argument(
1375
        "--freeze-installed", "--no-update-deps",
1376
        action="store_const",
1377
        const=UpdateModifier.FREEZE_INSTALLED,
1378
        dest="update_modifier",
1379
        default=NULL,
1380
        help="Do not update or change already-installed dependencies.",
1381
    )
1382
    update_modifiers.add_argument(
1383
        "--update-deps",
1384
        action="store_const",
1385
        const=UpdateModifier.UPDATE_DEPS,
1386
        dest="update_modifier",
1387
        default=NULL,
1388
        help="Update dependencies.",
1389
    )
1390
    update_modifiers.add_argument(
1391
        "-S", "--satisfied-skip-solve",
1392
        action="store_const",
1393
        const=UpdateModifier.SPECS_SATISFIED_SKIP_SOLVE,
1394
        dest="update_modifier",
1395
        default=NULL,
1396
        help="Exit early and do not run the solver if the requested specs are satisfied. "
1397
             "Also skips aggressive updates as configured by 'aggressive_update_packages'. "
1398
             "Similar to the default behavior of 'pip install'.",
1399
    )
1400
    update_modifiers.add_argument(
1401
        "--update-all", "--all",
1402
        action="store_const",
1403
        const=UpdateModifier.UPDATE_ALL,
1404
        dest="update_modifier",
1405
        help="Update all installed packages in the environment.",
1406
        default=NULL,
1407
    )
1408
1409
1410
def add_parser_prune(p):
1411
    p.add_argument(
1412
        "--prune",
1413
        action="store_true",
1414
        default=NULL,
1415
        help="Remove packages that have previously been brought into the environment to satisfy "
1416
             "dependencies of user-requested packages, but are no longer needed.",
1417
    )
1418
1419
1420
def add_parser_networking(p):
1421
    networking_options = p.add_argument_group("Networking Options")
1422
    networking_options.add_argument(
1423
        "-C", "--use-index-cache",
1424
        action="store_true",
1425
        default=False,
1426
        help="Use cache of channel index files, even if it has expired.",
1427
    )
1428
    networking_options.add_argument(
1429
        "-k", "--insecure",
1430
        action="store_false",
1431
        dest="ssl_verify",
1432
        default=NULL,
1433
        help="Allow conda to perform \"insecure\" SSL connections and transfers. "
1434
             "Equivalent to setting 'ssl_verify' to 'false'."
1435
    )
1436
    networking_options.add_argument(
1437
        "--offline",
1438
        action='store_true',
1439
        default=NULL,
1440
        help="Offline mode. Don't connect to the Internet.",
1441
    )
1442
    return networking_options
1443
1444
1445
def add_parser_package_install_options(p):
1446
    package_install_options = p.add_argument_group("Package Linking and Install-time Options")
1447
    package_install_options.add_argument(
1448
        '-f', "--force",
1449
        action="store_true",
1450
        default=NULL,
1451
        help=SUPPRESS,
1452
    )
1453
    package_install_options.add_argument(
1454
        '--copy',
1455
        action="store_true",
1456
        default=NULL,
1457
        help="Install all packages using copies instead of hard- or soft-linking."
1458
    )
1459
    if on_win:
1460
        package_install_options.add_argument(
1461
            "--shortcuts",
1462
            action="store_true",
1463
            help=SUPPRESS,
1464
            dest="shortcuts",
1465
            default=NULL,
1466
        )
1467
        package_install_options.add_argument(
1468
            "--no-shortcuts",
1469
            action="store_false",
1470
            help="Don't install start menu shortcuts",
1471
            dest="shortcuts",
1472
            default=NULL,
1473
        )
1474
    return package_install_options
1475
1476
1477
def add_parser_known(p):
1478
    p.add_argument(
1479
        "--unknown",
1480
        action="store_true",
1481
        default=False,
1482
        dest='unknown',
1483
        help=SUPPRESS,
1484
    )
1485