diff --git a/conda/_vendor/auxlib/__init__.py b/conda/_vendor/auxlib/__init__.py index c17a8ed10c5..0a34d4dae65 100644 --- a/conda/_vendor/auxlib/__init__.py +++ b/conda/_vendor/auxlib/__init__.py @@ -45,3 +45,30 @@ def emit(self, record): __license__ = "ISC" __copyright__ = "(c) 2015 Kale Franz. All rights reserved." __summary__ = """auxiliary library to the python standard library""" + + +class _Null(object): + """ + Examples: + >>> len(_Null()) + 0 + >>> bool(_Null()) + False + >>> _Null().__nonzero__() + False + """ + def __nonzero__(self): + return self.__bool__() + + def __bool__(self): + return False + + def __len__(self): + return 0 + + +# Use this NULL object when needing to distinguish a value from None +# For example, when parsing json, you may need to determine if a json key was given and set +# to null, or the key didn't exist at all. There could be a bit of potential confusion here, +# because in python null == None, while here I'm defining NULL to mean 'not defined'. +NULL = _Null() diff --git a/conda/_vendor/auxlib/collection.py b/conda/_vendor/auxlib/collection.py index 04e133f4cb4..7905919d08d 100644 --- a/conda/_vendor/auxlib/collection.py +++ b/conda/_vendor/auxlib/collection.py @@ -7,33 +7,6 @@ from .compat import isiterable, iteritems, odict, text_type -class _Null(object): - """ - Examples: - >>> len(_Null()) - 0 - >>> bool(_Null()) - False - >>> _Null().__nonzero__() - False - """ - def __nonzero__(self): - return self.__bool__() - - def __bool__(self): - return False - - def __len__(self): - return 0 - - -# Use this NULL object when needing to distinguish a value from None -# For example, when parsing json, you may need to determine if a json key was given and set -# to null, or the key didn't exist at all. There could be a bit of potential confusion here, -# because in python null == None, while here I'm defining NULL to mean 'not defined'. -NULL = _Null() - - def make_immutable(value): # this function is recursive, and if nested data structures fold back on themselves, # there will likely be recursion errors diff --git a/conda/base/__init__.py b/conda/base/__init__.py index a6087f6532f..02ecbdd1f25 100644 --- a/conda/base/__init__.py +++ b/conda/base/__init__.py @@ -17,7 +17,3 @@ All other ``conda`` modules may import from ``conda.base``. """ -from __future__ import absolute_import, division, print_function -from logging import getLogger - -log = getLogger(__name__) diff --git a/conda/cli/main.py b/conda/cli/main.py index 59433195ec6..b4bd030a9d8 100644 --- a/conda/cli/main.py +++ b/conda/cli/main.py @@ -35,6 +35,7 @@ conda -h """ from __future__ import absolute_import, division, print_function, unicode_literals + import sys PARSER = None @@ -49,17 +50,10 @@ def generate_parser(): from .. import __version__ from .conda_argparse import ArgumentParser - from .main_clean import configure_parser as configure_parser_clean - from .main_config import configure_parser as configure_parser_config - from .main_create import configure_parser as configure_parser_create - from .main_help import configure_parser as configure_parser_help - from .main_info import configure_parser as configure_parser_info - from .main_install import configure_parser as configure_parser_install - from .main_list import configure_parser as configure_parser_list - from .main_package import configure_parser as configure_parser_package - from .main_remove import configure_parser as configure_parser_remove - from .main_search import configure_parser as configure_parser_search - from .main_update import configure_parser as configure_parser_update + from .parsers import (configure_parser_clean, configure_parser_config, configure_parser_create, + configure_parser_help, configure_parser_info, configure_parser_install, + configure_parser_list, configure_parser_package, configure_parser_remove, + configure_parser_search, configure_parser_update) p = ArgumentParser( description='conda is a tool for managing and deploying applications,' @@ -133,7 +127,11 @@ def _main(*args): context.__init__(SEARCH_PATH, 'conda', args) init_loggers(context) - exit_code = args.func(args, p) + relative_mod, func_name = args.func.rsplit('.', 1) + # func_name should always be 'execute' + from importlib import import_module + module = import_module(relative_mod, __name__.rsplit('.', 1)[0]) + exit_code = getattr(module, func_name)(args, p) if isinstance(exit_code, int): return exit_code diff --git a/conda/cli/main_clean.py b/conda/cli/main_clean.py index cc3d671b9f4..e44e8c2c733 100644 --- a/conda/cli/main_clean.py +++ b/conda/cli/main_clean.py @@ -12,66 +12,11 @@ from os.path import getsize, isdir, join import sys -from .conda_argparse import add_parser_json, add_parser_quiet, add_parser_yes from ..base.constants import CONDA_TARBALL_EXTENSION from ..base.context import context log = getLogger(__name__) -descr = """ -Remove unused packages and caches. -""" - -example = """ -Examples: - - conda clean --tarballs -""" - -def configure_parser(sub_parsers): - p = sub_parsers.add_parser( - 'clean', - description=descr, - help=descr, - epilog=example, - ) - add_parser_yes(p) - add_parser_json(p) - add_parser_quiet(p) - p.add_argument( - "-a", "--all", - action="store_true", - help="Remove index cache, lock files, tarballs, " - "unused cache packages, and source cache.", - ) - p.add_argument( - "-i", "--index-cache", - action="store_true", - help="Remove index cache.", - ) - p.add_argument( - "-l", "--lock", - action="store_true", - help="Remove all conda lock files.", - ) - p.add_argument( - "-t", "--tarballs", - action="store_true", - help="Remove cached package tarballs.", - ) - p.add_argument( - '-p', '--packages', - action='store_true', - help="""Remove unused cached packages. Warning: this does not check - for symlinked packages.""", - ) - p.add_argument( - '-s', '--source-cache', - action='store_true', - help="""Remove files from the source cache of conda build.""", - ) - p.set_defaults(func=execute) - def find_tarballs(): from ..core.package_cache import PackageCache diff --git a/conda/cli/main_config.py b/conda/cli/main_config.py index 88dbb9acafa..dc675ce8c99 100644 --- a/conda/cli/main_config.py +++ b/conda/cli/main_config.py @@ -5,7 +5,6 @@ # Consult LICENSE.txt or http://opensource.org/licenses/BSD-3-Clause. from __future__ import absolute_import, division, print_function, unicode_literals -from argparse import SUPPRESS import collections import json import os @@ -13,200 +12,11 @@ import sys from textwrap import wrap -from .conda_argparse import add_parser_json from .. import CondaError -from ..base.constants import CONDA_HOMEPAGE_URL from ..base.context import context, sys_rc_path, user_rc_path from ..common.compat import isiterable, iteritems, string_types, text_type -from ..common.constants import NULL from ..common.io import timeout -descr = """ -Modify configuration values in .condarc. This is modeled after the git -config command. Writes to the user .condarc file (%s) by default. - -""" % user_rc_path - -# Note, the extra whitespace in the list keys is on purpose. It's so the -# formatting from help2man is still valid YAML (otherwise it line wraps the -# keys like "- conda - defaults"). Technically the parser here still won't -# recognize it because it removes the indentation, but at least it will be -# valid. -additional_descr = """ -See `conda config --describe` or %s/docs/config.html -for details on all the options that can go in .condarc. - -Examples: - -Display all configuration values as calculated and compiled: - - conda config --show - -Display all identified configuration sources: - - conda config --show-sources - -Describe all available configuration options: - - conda config --describe - -Add the conda-canary channel: - - conda config --add channels conda-canary - -Set the output verbosity to level 3 (highest): - - conda config --set verbosity 3 -""" % CONDA_HOMEPAGE_URL - - -# Note, the formatting of this is designed to work well with help2man -example = """ -Examples: - -Get the channels defined in the system .condarc: - - conda config --get channels --system - -Add the 'foo' Binstar channel: - - conda config --add channels foo - -Disable the 'show_channel_urls' option: - - conda config --set show_channel_urls no -""" - - -def configure_parser(sub_parsers): - p = sub_parsers.add_parser( - 'config', - description=descr, - help=descr, - epilog=additional_descr, - ) - add_parser_json(p) - - # TODO: use argparse.FileType - location = p.add_mutually_exclusive_group() - location.add_argument( - "--system", - action="store_true", - help="""Write to the system .condarc file ({system}). Otherwise writes to the user - config file ({user}).""".format(system=sys_rc_path, - user=user_rc_path), - ) - location.add_argument( - "--env", - action="store_true", - help="Write to the active conda environment .condarc file (%s). " - "If no environment is active, write to the user config file (%s)." - "" % (os.getenv('CONDA_PREFIX', ""), user_rc_path), - ) - location.add_argument( - "--file", - action="store", - help="""Write to the given file. Otherwise writes to the user config file ({user}) -or the file path given by the 'CONDARC' environment variable, if it is set -(default: %(default)s).""".format(user=user_rc_path), - default=os.environ.get('CONDARC', user_rc_path) - ) - - # XXX: Does this really have to be mutually exclusive. I think the below - # code will work even if it is a regular group (although combination of - # --add and --remove with the same keys will not be well-defined). - action = p.add_mutually_exclusive_group(required=True) - action.add_argument( - "--show", - action="store_true", - help="Display all configuration values as calculated and compiled.", - ) - action.add_argument( - "--show-sources", - action="store_true", - help="Display all identified configuration sources.", - ) - action.add_argument( - "--validate", - action="store_true", - help="Validate all configuration sources.", - ) - action.add_argument( - "--describe", - action="store_true", - help="Describe available configuration parameters.", - ) - action.add_argument( - "--write-default", - action="store_true", - help="Write the default configuration to a file. " - "Equivalent to `conda config --describe > ~/.condarc` " - "when no --env, --system, or --file flags are given.", - ) - action.add_argument( - "--get", - nargs='*', - action="store", - help="Get a configuration value.", - default=None, - metavar='KEY', - ) - action.add_argument( - "--append", - nargs=2, - action="append", - help="""Add one configuration value to the end of a list key.""", - default=[], - metavar=('KEY', 'VALUE'), - ) - action.add_argument( - "--prepend", "--add", - nargs=2, - action="append", - help="""Add one configuration value to the beginning of a list key.""", - default=[], - metavar=('KEY', 'VALUE'), - ) - action.add_argument( - "--set", - nargs=2, - action="append", - help="""Set a boolean or string key""", - default=[], - metavar=('KEY', 'VALUE'), - ) - action.add_argument( - "--remove", - nargs=2, - action="append", - help="""Remove a configuration value from a list key. This removes - all instances of the value.""", - default=[], - metavar=('KEY', 'VALUE'), - ) - action.add_argument( - "--remove-key", - nargs=1, - action="append", - help="""Remove a configuration key (and all its values).""", - default=[], - metavar="KEY", - ) - action.add_argument( - "--stdin", - action="store_true", - help="Apply configuration information given in yaml format piped through stdin.", - ) - - p.add_argument( - "-f", "--force", - action="store_true", - default=NULL, - help=SUPPRESS, # TODO: No longer used. Remove in a future release. - ) - - p.set_defaults(func=execute) - def execute(args, parser): from ..exceptions import CouldntParseError diff --git a/conda/cli/main_create.py b/conda/cli/main_create.py index 1164b52ca35..d84e3572bf9 100644 --- a/conda/cli/main_create.py +++ b/conda/cli/main_create.py @@ -6,61 +6,6 @@ from __future__ import absolute_import, division, print_function, unicode_literals -from .conda_argparse import add_parser_create_install_update, add_parser_json -from ..common.compat import on_win -from ..common.constants import NULL - -help = "Create a new conda environment from a list of specified packages. " -descr = (help + - "To use the created environment, use 'source activate " - "envname' look in that directory first. This command requires either " - "the -n NAME or -p PREFIX option.") - -example = """ -Examples: - - conda create -n myenv sqlite - -""" - - -def configure_parser(sub_parsers): - p = sub_parsers.add_parser( - 'create', - description=descr, - help=help, - epilog=example, - ) - if on_win: - p.add_argument( - "--shortcuts", - action="store_true", - help="Install start menu shortcuts", - dest="shortcuts", - default=NULL, - ) - p.add_argument( - "--no-shortcuts", - action="store_false", - help="Don't install start menu shortcuts", - dest="shortcuts", - default=NULL, - ) - add_parser_create_install_update(p) - add_parser_json(p) - p.add_argument( - "--clone", - action="store", - help='Path to (or name of) existing local environment.', - metavar='ENV', - ) - p.add_argument( - "--no-default-packages", - action="store_true", - help='Ignore create_default_packages in the .condarc file.', - ) - p.set_defaults(func=execute) - def execute(args, parser): from .install import install diff --git a/conda/cli/main_help.py b/conda/cli/main_help.py index c25918fef17..59d6baebca1 100644 --- a/conda/cli/main_help.py +++ b/conda/cli/main_help.py @@ -8,32 +8,6 @@ import subprocess import sys -descr = "Displays a list of available conda commands and their help strings." - -example = """ -Examples: - - conda help install -""" - - -def configure_parser(sub_parsers): - p = sub_parsers.add_parser( - 'help', - description=descr, - help=descr, - epilog=example, - ) - p.add_argument( - 'command', - metavar='COMMAND', - action="store", - nargs='?', - help="""Print help information for COMMAND (same as: conda COMMAND - --help).""", - ) - p.set_defaults(func=execute) - def execute(args, parser): if not args.command: diff --git a/conda/cli/main_info.py b/conda/cli/main_info.py index 1d7dac22d5a..4dbda062ba9 100644 --- a/conda/cli/main_info.py +++ b/conda/cli/main_info.py @@ -15,67 +15,10 @@ import re import sys -from .conda_argparse import add_parser_json, add_parser_offline from ..common.compat import iteritems, itervalues, on_win, text_type log = getLogger(__name__) -help = "Display information about current conda install." - -example = """ - -Examples: - - conda info -a -""" - -def configure_parser(sub_parsers): - p = sub_parsers.add_parser( - 'info', - description=help, - help=help, - epilog=example, - ) - add_parser_json(p) - add_parser_offline(p) - p.add_argument( - '-a', "--all", - action="store_true", - help="Show all information, (environments, license, and system " - "information.") - p.add_argument( - '-e', "--envs", - action="store_true", - help="List all known conda environments.", - ) - p.add_argument( - '-l', "--license", - action="store_true", - help="Display information about the local conda licenses list.", - ) - p.add_argument( - '-s', "--system", - action="store_true", - help="List environment variables.", - ) - p.add_argument( - 'packages', - action="store", - nargs='*', - help="Display information about packages.", - ) - p.add_argument( - '--root', - action='store_true', - help='Display root environment path.', - ) - p.add_argument( - '--unsafe-channels', - action='store_true', - help='Display list of channels with tokens exposed.', - ) - p.set_defaults(func=execute) - def get_user_site(): # pragma: no cover site_dirs = [] diff --git a/conda/cli/main_install.py b/conda/cli/main_install.py index e7388a4d847..951f90f9c9f 100644 --- a/conda/cli/main_install.py +++ b/conda/cli/main_install.py @@ -6,73 +6,6 @@ from __future__ import absolute_import, division, print_function, unicode_literals -from .conda_argparse import add_parser_create_install_update, add_parser_json -from ..common.compat import on_win - -help = "Installs a list of packages into a specified conda environment." -descr = help + """ - -This command accepts a list of package specifications (e.g, bitarray=0.8) -and installs a set of packages consistent with those specifications and -compatible with the underlying environment. If full compatibility cannot -be assured, an error is reported and the environment is not changed. - -Conda attempts to install the newest versions of the requested packages. To -accomplish this, it may update some packages that are already installed, or -install additional packages. To prevent existing packages from updating, -use the --no-update-deps option. This may force conda to install older -versions of the requested packages, and it does not prevent additional -dependency packages from being installed. - -If you wish to skip dependency checking altogether, use the '--force' -option. This may result in an environment with incompatible packages, so -this option must be used with great caution. - -conda can also be called with a list of explicit conda package filenames -(e.g. ./lxml-3.2.0-py27_0.tar.bz2). Using conda in this mode implies the ---force option, and should likewise be used with great caution. Explicit -filenames and package specifications cannot be mixed in a single command. -""" -example = """ -Examples: - - conda install -n myenv scipy - -""" - - -def configure_parser(sub_parsers): - p = sub_parsers.add_parser( - 'install', - description=descr, - help=help, - epilog=example, - ) - p.add_argument( - "--revision", - action="store", - help="Revert to the specified REVISION.", - metavar='REVISION', - ) - if on_win: - p.add_argument( - "--shortcuts", - action="store_true", - help="Install start menu shortcuts", - dest="shortcuts", - default=True - ) - p.add_argument( - "--no-shortcuts", - action="store_false", - help="Don't install start menu shortcuts", - dest="shortcuts", - default=True - ) - add_parser_create_install_update(p) - add_parser_json(p) - p.set_defaults(func=execute) - def execute(args, parser): from .install import install diff --git a/conda/cli/main_list.py b/conda/cli/main_list.py index 1461ada2981..0129049eff5 100644 --- a/conda/cli/main_list.py +++ b/conda/cli/main_list.py @@ -6,100 +6,13 @@ from __future__ import absolute_import, division, print_function, unicode_literals -from argparse import RawDescriptionHelpFormatter import logging from os.path import isdir, isfile import re -from .conda_argparse import (add_parser_help, add_parser_json, add_parser_prefix, - add_parser_show_channel_urls) - -descr = "List linked packages in a conda environment." - -# Note, the formatting of this is designed to work well with help2man -examples = """ -Examples: - -List all packages in the current environment: - - conda list - -List all packages installed into the environment 'myenv': - - conda list -n myenv - -Save packages for future use: - - conda list --export > package-list.txt - -Reinstall packages from an export file: - - conda create -n myenv --file package-list.txt - -""" log = logging.getLogger(__name__) -def configure_parser(sub_parsers): - p = sub_parsers.add_parser( - 'list', - description=descr, - help=descr, - formatter_class=RawDescriptionHelpFormatter, - epilog=examples, - add_help=False, - ) - add_parser_help(p) - add_parser_prefix(p) - add_parser_json(p) - add_parser_show_channel_urls(p) - p.add_argument( - '-c', "--canonical", - action="store_true", - help="Output canonical names of packages only. Implies --no-pip. ", - ) - p.add_argument( - '-f', "--full-name", - action="store_true", - help="Only search for full names, i.e., ^$.", - ) - p.add_argument( - "--explicit", - action="store_true", - help="List explicitly all installed conda packaged with URL " - "(output may be used by conda create --file).", - ) - p.add_argument( - "--md5", - action="store_true", - help="Add MD5 hashsum when using --explicit", - ) - p.add_argument( - '-e', "--export", - action="store_true", - help="Output requirement string only (output may be used by " - " conda create --file).", - ) - p.add_argument( - '-r', "--revisions", - action="store_true", - help="List the revision history and exit.", - ) - p.add_argument( - "--no-pip", - action="store_false", - default=True, - dest="pip", - help="Do not include pip-only installed packages.") - p.add_argument( - 'regex', - action="store", - nargs="?", - help="List only packages matching this regular expression.", - ) - p.set_defaults(func=execute) - - def print_export_header(subdir): print('# This file may be used to create an environment using:') print('# $ conda create --name --file ') diff --git a/conda/cli/main_package.py b/conda/cli/main_package.py index 5b1b5ccfddb..41334a59211 100644 --- a/conda/cli/main_package.py +++ b/conda/cli/main_package.py @@ -17,57 +17,9 @@ import tarfile import tempfile -from .conda_argparse import add_parser_prefix from ..base.context import context from ..common.compat import PY3, itervalues -descr = "Low-level conda package utility. (EXPERIMENTAL)" - - -def configure_parser(sub_parsers): - p = sub_parsers.add_parser( - 'package', - description=descr, - help=descr, - ) - add_parser_prefix(p) - p.add_argument( - '-w', "--which", - metavar="PATH", - nargs='+', - action="store", - help="Given some PATH print which conda package the file came from.", - ) - p.add_argument( - '-r', "--reset", - action="store_true", - help="Remove all untracked files and exit.", - ) - p.add_argument( - '-u', "--untracked", - action="store_true", - help="Display all untracked files and exit.", - ) - p.add_argument( - "--pkg-name", - action="store", - default="unknown", - help="Package name of the created package.", - ) - p.add_argument( - "--pkg-version", - action="store", - default="0.0", - help="Package version of the created package.", - ) - p.add_argument( - "--pkg-build", - action="store", - default=0, - help="Package build number of the created package.", - ) - p.set_defaults(func=execute) - def remove(prefix, files): """ diff --git a/conda/cli/main_remove.py b/conda/cli/main_remove.py index c907f0a6746..9d78800dc42 100644 --- a/conda/cli/main_remove.py +++ b/conda/cli/main_remove.py @@ -6,110 +6,14 @@ from __future__ import absolute_import, division, print_function, unicode_literals -from argparse import RawDescriptionHelpFormatter from collections import defaultdict import logging from os.path import isdir import sys -from .conda_argparse import (add_parser_channels, add_parser_help, add_parser_insecure, - add_parser_json, add_parser_no_pin, add_parser_offline, - add_parser_prefix, add_parser_pscheck, add_parser_quiet, - add_parser_use_index_cache, add_parser_use_local, add_parser_yes) - -help = "%s a list of packages from a specified conda environment." -descr = help + """ - -This command will also remove any package that depends on any of the -specified packages as well---unless a replacement can be found without -that dependency. If you wish to skip this dependency checking and remove -just the requested packages, add the '--force' option. Note however that -this may result in a broken environment, so use this with caution. -""" -example = """ -Examples: - - conda %s -n myenv scipy - -""" - -uninstall_help = "Alias for conda remove. See conda remove --help." log = logging.getLogger(__name__) -def configure_parser(sub_parsers, name='remove'): - if name == 'remove': - p = sub_parsers.add_parser( - name, - formatter_class=RawDescriptionHelpFormatter, - description=descr % name.capitalize(), - help=help % name.capitalize(), - epilog=example % name, - add_help=False, - ) - else: - p = sub_parsers.add_parser( - name, - formatter_class=RawDescriptionHelpFormatter, - description=uninstall_help, - help=uninstall_help, - epilog=example % name, - add_help=False, - ) - add_parser_help(p) - add_parser_yes(p) - add_parser_json(p) - p.add_argument( - "--all", - action="store_true", - help="%s all packages, i.e., the entire environment." % name.capitalize(), - ) - p.add_argument( - "--features", - action="store_true", - help="%s features (instead of packages)." % name.capitalize(), - ) - - # TODO: --features currently sorta still work. But super sloppy. - - # p.add_argument( - # '--feature', - # metavar='FEATURE_NAME=FEATURE_VALUE', - # dest='features', - # action="append", - # help="Feature to remove in the conda environment. " - # "The value must be a key-value pair separated by an equal sign e.g. blas=nomkl. " - # "Can be used multiple times. " - # "Equivalent to a MatchSpec specifying a single 'provides_features'.", - # ) - - p.add_argument( - "--force", - action="store_true", - help="Forces removal of a package without removing packages that depend on it. " - "Using this option will usually leave your environment in a broken and " - "inconsistent state.", - ) - add_parser_no_pin(p) - add_parser_channels(p) - add_parser_prefix(p) - add_parser_quiet(p) - # Putting this one first makes it the default - add_parser_use_index_cache(p) - add_parser_use_local(p) - add_parser_offline(p) - add_parser_pscheck(p) - add_parser_insecure(p) - p.add_argument( - 'package_names', - metavar='package_name', - action="store", - nargs='*', - help="Package names to %s from the environment." % name, - ) - p.set_defaults(func=execute) - - def execute(args, parser): from .common import check_non_admin, confirm_yn, specs_from_args, stdout_json from ..base.context import context diff --git a/conda/cli/main_search.py b/conda/cli/main_search.py index d8f9fe6f14d..a01d94e7071 100644 --- a/conda/cli/main_search.py +++ b/conda/cli/main_search.py @@ -1,122 +1,11 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function, unicode_literals -from argparse import SUPPRESS from collections import defaultdict import sys -from .conda_argparse import (add_parser_channels, add_parser_insecure, add_parser_json, - add_parser_known, add_parser_offline, add_parser_prefix, - add_parser_use_index_cache, add_parser_use_local) from ..compat import text_type -descr = """Search for packages and display associated information. -The input is a MatchSpec, a query language for conda packages. -See examples below. -""" - -example = """ -Examples: - -Search for a specific package named 'scikit-learn': - - conda search scikit-learn - -Search for packages containing 'scikit' in the package name: - - conda search *scikit* - -Note that your shell may expand '*' before handing the command over to conda. -Therefore it is sometimes necessary to use single or double quotes around the query. - - conda search '*scikit' - conda search "*scikit*" - -Search for packages for 64-bit Linux (by default, packages for your current -platform are shown): - - conda search numpy[subdir=linux-64] - -Search for a specific version of a package: - - conda search 'numpy>=1.12' - -Search for a package on a specific channel - - conda search conda-forge::numpy - conda search 'numpy[channel=conda-forge, subdir=osx-64]' -""" - - -def configure_parser(sub_parsers): - p = sub_parsers.add_parser( - 'search', - description=descr, - help=descr, - epilog=example, - ) - add_parser_prefix(p) - p.add_argument( - "--canonical", - action="store_true", - help=SUPPRESS, - ) - p.add_argument( - '-f', "--full-name", - action="store_true", - help=SUPPRESS, - ) - p.add_argument( - '-i', "--info", - action="store_true", - help="Provide detailed information about each package. " - "Similar to output of 'conda info package-name'." - ) - p.add_argument( - "--names-only", - action="store_true", - help=SUPPRESS, - ) - add_parser_known(p) - add_parser_use_index_cache(p) - p.add_argument( - '-o', "--outdated", - action="store_true", - help=SUPPRESS, - ) - p.add_argument( - '--platform', - action='store', - dest='platform', - help="""Search the given platform. Should be formatted like 'osx-64', 'linux-32', - 'win-64', and so on. The default is to search the current platform.""", - default=None, - ) - p.add_argument( - 'match_spec', - default='*', - nargs='?', - help=SUPPRESS, - ) - p.add_argument( - "--spec", - action="store_true", - help=SUPPRESS, - ) - p.add_argument( - "--reverse-dependency", - action="store_true", - help="""Perform a reverse dependency search. When using this flag, the --full-name -flag is recommended. Use 'conda info package' to see the dependencies of a -package.""", - ) - add_parser_offline(p) - add_parser_channels(p) - add_parser_json(p) - add_parser_use_local(p) - add_parser_insecure(p) - p.set_defaults(func=execute) - def execute(args, parser): from ..models.match_spec import MatchSpec diff --git a/conda/cli/main_update.py b/conda/cli/main_update.py index e011843d025..73636082cb9 100644 --- a/conda/cli/main_update.py +++ b/conda/cli/main_update.py @@ -6,59 +6,6 @@ from __future__ import absolute_import, division, print_function, unicode_literals -from .conda_argparse import add_parser_create_install_update, add_parser_json - -help = "Updates conda packages to the latest compatible version." -descr = help + """ - -This command accepts a list of package names and updates them to the latest -versions that are compatible with all other packages in the environment. - -Conda attempts to install the newest versions of the requested packages. To -accomplish this, it may update some packages that are already installed, or -install additional packages. To prevent existing packages from updating, -use the --no-update-deps option. This may force conda to install older -versions of the requested packages, and it does not prevent additional -dependency packages from being installed. - -If you wish to skip dependency checking altogether, use the '--force' -option. This may result in an environment with incompatible packages, so -this option must be used with great caution. -""" -example = """ -Examples: - - conda %s -n myenv scipy - -""" - -alias_help = "Alias for conda update. See conda update --help." - - -def configure_parser(sub_parsers, name='update'): - if name == 'update': - p = sub_parsers.add_parser( - 'update', - description=descr, - help=descr, - epilog=example % name, - ) - else: - p = sub_parsers.add_parser( - name, - description=alias_help, - help=alias_help, - epilog=example % name, - ) - add_parser_create_install_update(p) - add_parser_json(p) - p.add_argument( - "--all", - action="store_true", - help="Update all installed packages in the environment.", - ) - p.set_defaults(func=execute) - def execute(args, parser): from .install import install diff --git a/conda/cli/parsers.py b/conda/cli/parsers.py new file mode 100644 index 00000000000..2f1c3c370e1 --- /dev/null +++ b/conda/cli/parsers.py @@ -0,0 +1,834 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, division, print_function, unicode_literals + +from argparse import RawDescriptionHelpFormatter, SUPPRESS +from logging import getLogger +import os +from os.path import abspath, expanduser, join +import sys +from textwrap import dedent + +from .conda_argparse import (add_parser_channels, add_parser_create_install_update, + add_parser_help, add_parser_insecure, add_parser_json, + add_parser_known, add_parser_no_pin, add_parser_offline, + add_parser_prefix, add_parser_pscheck, add_parser_quiet, + add_parser_show_channel_urls, add_parser_use_index_cache, + add_parser_use_local, add_parser_yes) +from ..base.constants import CONDA_HOMEPAGE_URL +from ..common.constants import NULL + +log = getLogger(__name__) + +# duplicated code in the interest of import efficiency +on_win = bool(sys.platform == "win32") +user_rc_path = abspath(expanduser('~/.condarc')) +sys_rc_path = join(sys.prefix, '.condarc') + + +def configure_parser_clean(sub_parsers): + descr = dedent(""" + Remove unused packages and caches. + """) + example = dedent(""" + Examples: + + conda clean --tarballs + """) + p = sub_parsers.add_parser( + 'clean', + description=descr, + help=descr, + epilog=example, + ) + add_parser_yes(p) + add_parser_json(p) + add_parser_quiet(p) + p.add_argument( + "-a", "--all", + action="store_true", + help="Remove index cache, lock files, tarballs, " + "unused cache packages, and source cache.", + ) + p.add_argument( + "-i", "--index-cache", + action="store_true", + help="Remove index cache.", + ) + p.add_argument( + "-l", "--lock", + action="store_true", + help="Remove all conda lock files.", + ) + p.add_argument( + "-t", "--tarballs", + action="store_true", + help="Remove cached package tarballs.", + ) + p.add_argument( + '-p', '--packages', + action='store_true', + help="""Remove unused cached packages. Warning: this does not check + for symlinked packages.""", + ) + p.add_argument( + '-s', '--source-cache', + action='store_true', + help="""Remove files from the source cache of conda build.""", + ) + p.set_defaults(func='.main_clean.execute') + + +def configure_parser_info(sub_parsers): + help = "Display information about current conda install." + + example = dedent(""" + + Examples: + + conda info -a + """) + p = sub_parsers.add_parser( + 'info', + description=help, + help=help, + epilog=example, + ) + add_parser_json(p) + add_parser_offline(p) + p.add_argument( + '-a', "--all", + action="store_true", + help="Show all information, (environments, license, and system " + "information.") + p.add_argument( + '-e', "--envs", + action="store_true", + help="List all known conda environments.", + ) + p.add_argument( + '-l', "--license", + action="store_true", + help="Display information about the local conda licenses list.", + ) + p.add_argument( + '-s', "--system", + action="store_true", + help="List environment variables.", + ) + p.add_argument( + 'packages', + action="store", + nargs='*', + help="Display information about packages.", + ) + p.add_argument( + '--root', + action='store_true', + help='Display root environment path.', + ) + p.add_argument( + '--unsafe-channels', + action='store_true', + help='Display list of channels with tokens exposed.', + ) + p.set_defaults(func='.main_info.execute') + + +def configure_parser_config(sub_parsers): + descr = dedent(""" + Modify configuration values in .condarc. This is modeled after the git + config command. Writes to the user .condarc file (%s) by default. + + """) % user_rc_path + + # Note, the extra whitespace in the list keys is on purpose. It's so the + # formatting from help2man is still valid YAML (otherwise it line wraps the + # keys like "- conda - defaults"). Technically the parser here still won't + # recognize it because it removes the indentation, but at least it will be + # valid. + additional_descr = """ + See `conda config --describe` or %s/docs/config.html + for details on all the options that can go in .condarc. + + Examples: + + Display all configuration values as calculated and compiled: + + conda config --show + + Display all identified configuration sources: + + conda config --show-sources + + Describe all available configuration options: + + conda config --describe + + Add the conda-canary channel: + + conda config --add channels conda-canary + + Set the output verbosity to level 3 (highest): + + conda config --set verbosity 3 + + Get the channels defined in the system .condarc: + + conda config --get channels --system + + Add the 'foo' Binstar channel: + + conda config --add channels foo + + Disable the 'show_channel_urls' option: + + conda config --set show_channel_urls no + """ % CONDA_HOMEPAGE_URL + + p = sub_parsers.add_parser( + 'config', + description=descr, + help=descr, + epilog=additional_descr, + ) + add_parser_json(p) + + # TODO: use argparse.FileType + location = p.add_mutually_exclusive_group() + location.add_argument( + "--system", + action="store_true", + help="""Write to the system .condarc file ({system}). Otherwise writes to the user + config file ({user}).""".format(system=sys_rc_path, + user=user_rc_path), + ) + location.add_argument( + "--env", + action="store_true", + help="Write to the active conda environment .condarc file (%s). " + "If no environment is active, write to the user config file (%s)." + "" % (os.getenv('CONDA_PREFIX', ""), user_rc_path), + ) + location.add_argument( + "--file", + action="store", + help="""Write to the given file. Otherwise writes to the user config file ({user}) +or the file path given by the 'CONDARC' environment variable, if it is set +(default: %(default)s).""".format(user=user_rc_path), + default=os.environ.get('CONDARC', user_rc_path) + ) + + # XXX: Does this really have to be mutually exclusive. I think the below + # code will work even if it is a regular group (although combination of + # --add and --remove with the same keys will not be well-defined). + action = p.add_mutually_exclusive_group(required=True) + action.add_argument( + "--show", + action="store_true", + help="Display all configuration values as calculated and compiled.", + ) + action.add_argument( + "--show-sources", + action="store_true", + help="Display all identified configuration sources.", + ) + action.add_argument( + "--validate", + action="store_true", + help="Validate all configuration sources.", + ) + action.add_argument( + "--describe", + action="store_true", + help="Describe available configuration parameters.", + ) + action.add_argument( + "--write-default", + action="store_true", + help="Write the default configuration to a file. " + "Equivalent to `conda config --describe > ~/.condarc` " + "when no --env, --system, or --file flags are given.", + ) + action.add_argument( + "--get", + nargs='*', + action="store", + help="Get a configuration value.", + default=None, + metavar='KEY', + ) + action.add_argument( + "--append", + nargs=2, + action="append", + help="""Add one configuration value to the end of a list key.""", + default=[], + metavar=('KEY', 'VALUE'), + ) + action.add_argument( + "--prepend", "--add", + nargs=2, + action="append", + help="""Add one configuration value to the beginning of a list key.""", + default=[], + metavar=('KEY', 'VALUE'), + ) + action.add_argument( + "--set", + nargs=2, + action="append", + help="""Set a boolean or string key""", + default=[], + metavar=('KEY', 'VALUE'), + ) + action.add_argument( + "--remove", + nargs=2, + action="append", + help="""Remove a configuration value from a list key. This removes + all instances of the value.""", + default=[], + metavar=('KEY', 'VALUE'), + ) + action.add_argument( + "--remove-key", + nargs=1, + action="append", + help="""Remove a configuration key (and all its values).""", + default=[], + metavar="KEY", + ) + action.add_argument( + "--stdin", + action="store_true", + help="Apply configuration information given in yaml format piped through stdin.", + ) + + p.add_argument( + "-f", "--force", + action="store_true", + default=NULL, + help=SUPPRESS, # TODO: No longer used. Remove in a future release. + ) + + p.set_defaults(func='.main_config.execute') + + +def configure_parser_create(sub_parsers): + help = "Create a new conda environment from a list of specified packages. " + descr = (help + + "To use the created environment, use 'source activate " + "envname' look in that directory first. This command requires either " + "the -n NAME or -p PREFIX option.") + + example = dedent(""" + Examples: + + conda create -n myenv sqlite + + """) + p = sub_parsers.add_parser( + 'create', + description=descr, + help=help, + epilog=example, + ) + if on_win: + p.add_argument( + "--shortcuts", + action="store_true", + help="Install start menu shortcuts", + dest="shortcuts", + default=NULL, + ) + p.add_argument( + "--no-shortcuts", + action="store_false", + help="Don't install start menu shortcuts", + dest="shortcuts", + default=NULL, + ) + add_parser_create_install_update(p) + add_parser_json(p) + p.add_argument( + "--clone", + action="store", + help='Path to (or name of) existing local environment.', + metavar='ENV', + ) + p.add_argument( + "--no-default-packages", + action="store_true", + help='Ignore create_default_packages in the .condarc file.', + ) + p.set_defaults(func='.main_create.execute') + + +def configure_parser_help(sub_parsers): + descr = "Displays a list of available conda commands and their help strings." + + example = dedent(""" + Examples: + + conda help install + """) + + p = sub_parsers.add_parser( + 'help', + description=descr, + help=descr, + epilog=example, + ) + p.add_argument( + 'command', + metavar='COMMAND', + action="store", + nargs='?', + help="Print help information for COMMAND (same as: conda COMMAND --help).", + ) + p.set_defaults(func='.main_help.execute') + + +def configure_parser_install(sub_parsers): + help = "Installs a list of packages into a specified conda environment." + descr = dedent(help + """ + + This command accepts a list of package specifications (e.g, bitarray=0.8) + and installs a set of packages consistent with those specifications and + compatible with the underlying environment. If full compatibility cannot + be assured, an error is reported and the environment is not changed. + + Conda attempts to install the newest versions of the requested packages. To + accomplish this, it may update some packages that are already installed, or + install additional packages. To prevent existing packages from updating, + use the --no-update-deps option. This may force conda to install older + versions of the requested packages, and it does not prevent additional + dependency packages from being installed. + + If you wish to skip dependency checking altogether, use the '--force' + option. This may result in an environment with incompatible packages, so + this option must be used with great caution. + + conda can also be called with a list of explicit conda package filenames + (e.g. ./lxml-3.2.0-py27_0.tar.bz2). Using conda in this mode implies the + --force option, and should likewise be used with great caution. Explicit + filenames and package specifications cannot be mixed in a single command. + """) + example = dedent(""" + Examples: + + conda install -n myenv scipy + + """) + p = sub_parsers.add_parser( + 'install', + description=descr, + help=help, + epilog=example, + ) + p.add_argument( + "--revision", + action="store", + help="Revert to the specified REVISION.", + metavar='REVISION', + ) + if on_win: + p.add_argument( + "--shortcuts", + action="store_true", + help="Install start menu shortcuts", + dest="shortcuts", + default=True + ) + p.add_argument( + "--no-shortcuts", + action="store_false", + help="Don't install start menu shortcuts", + dest="shortcuts", + default=True + ) + add_parser_create_install_update(p) + add_parser_json(p) + p.set_defaults(func='.main_install.execute') + + +def configure_parser_list(sub_parsers): + descr = "List linked packages in a conda environment." + + # Note, the formatting of this is designed to work well with help2man + examples = dedent(""" + Examples: + + List all packages in the current environment: + + conda list + + List all packages installed into the environment 'myenv': + + conda list -n myenv + + Save packages for future use: + + conda list --export > package-list.txt + + Reinstall packages from an export file: + + conda create -n myenv --file package-list.txt + + """) + p = sub_parsers.add_parser( + 'list', + description=descr, + help=descr, + formatter_class=RawDescriptionHelpFormatter, + epilog=examples, + add_help=False, + ) + add_parser_help(p) + add_parser_prefix(p) + add_parser_json(p) + add_parser_show_channel_urls(p) + p.add_argument( + '-c', "--canonical", + action="store_true", + help="Output canonical names of packages only. Implies --no-pip. ", + ) + p.add_argument( + '-f', "--full-name", + action="store_true", + help="Only search for full names, i.e., ^$.", + ) + p.add_argument( + "--explicit", + action="store_true", + help="List explicitly all installed conda packaged with URL " + "(output may be used by conda create --file).", + ) + p.add_argument( + "--md5", + action="store_true", + help="Add MD5 hashsum when using --explicit", + ) + p.add_argument( + '-e', "--export", + action="store_true", + help="Output requirement string only (output may be used by " + " conda create --file).", + ) + p.add_argument( + '-r', "--revisions", + action="store_true", + help="List the revision history and exit.", + ) + p.add_argument( + "--no-pip", + action="store_false", + default=True, + dest="pip", + help="Do not include pip-only installed packages.") + p.add_argument( + 'regex', + action="store", + nargs="?", + help="List only packages matching this regular expression.", + ) + p.set_defaults(func='.main_list.execute') + + +def configure_parser_package(sub_parsers): + descr = "Low-level conda package utility. (EXPERIMENTAL)" + p = sub_parsers.add_parser( + 'package', + description=descr, + help=descr, + ) + add_parser_prefix(p) + p.add_argument( + '-w', "--which", + metavar="PATH", + nargs='+', + action="store", + help="Given some PATH print which conda package the file came from.", + ) + p.add_argument( + '-r', "--reset", + action="store_true", + help="Remove all untracked files and exit.", + ) + p.add_argument( + '-u', "--untracked", + action="store_true", + help="Display all untracked files and exit.", + ) + p.add_argument( + "--pkg-name", + action="store", + default="unknown", + help="Package name of the created package.", + ) + p.add_argument( + "--pkg-version", + action="store", + default="0.0", + help="Package version of the created package.", + ) + p.add_argument( + "--pkg-build", + action="store", + default=0, + help="Package build number of the created package.", + ) + p.set_defaults(func='.main_package.execute') + + +def configure_parser_remove(sub_parsers, name='remove'): + help = "%s a list of packages from a specified conda environment." + descr = dedent(help + """ + + This command will also remove any package that depends on any of the + specified packages as well---unless a replacement can be found without + that dependency. If you wish to skip this dependency checking and remove + just the requested packages, add the '--force' option. Note however that + this may result in a broken environment, so use this with caution. + """) + example = dedent(""" + Examples: + + conda %s -n myenv scipy + + """) + + uninstall_help = "Alias for conda remove. See conda remove --help." + if name == 'remove': + p = sub_parsers.add_parser( + name, + formatter_class=RawDescriptionHelpFormatter, + description=descr % name.capitalize(), + help=help % name.capitalize(), + epilog=example % name, + add_help=False, + ) + else: + p = sub_parsers.add_parser( + name, + formatter_class=RawDescriptionHelpFormatter, + description=uninstall_help, + help=uninstall_help, + epilog=example % name, + add_help=False, + ) + add_parser_help(p) + add_parser_yes(p) + add_parser_json(p) + p.add_argument( + "--all", + action="store_true", + help="%s all packages, i.e., the entire environment." % name.capitalize(), + ) + p.add_argument( + "--features", + action="store_true", + help="%s features (instead of packages)." % name.capitalize(), + ) + + # TODO: --features currently sorta still work. But super sloppy. + + # p.add_argument( + # '--feature', + # metavar='FEATURE_NAME=FEATURE_VALUE', + # dest='features', + # action="append", + # help="Feature to remove in the conda environment. " + # "The value must be a key-value pair separated by an equal sign e.g. blas=nomkl. " + # "Can be used multiple times. " + # "Equivalent to a MatchSpec specifying a single 'provides_features'.", + # ) + + p.add_argument( + "--force", + action="store_true", + help="Forces removal of a package without removing packages that depend on it. " + "Using this option will usually leave your environment in a broken and " + "inconsistent state.", + ) + add_parser_no_pin(p) + add_parser_channels(p) + add_parser_prefix(p) + add_parser_quiet(p) + # Putting this one first makes it the default + add_parser_use_index_cache(p) + add_parser_use_local(p) + add_parser_offline(p) + add_parser_pscheck(p) + add_parser_insecure(p) + p.add_argument( + 'package_names', + metavar='package_name', + action="store", + nargs='*', + help="Package names to %s from the environment." % name, + ) + p.set_defaults(func='.main_remove.execute') + + +def configure_parser_search(sub_parsers): + descr = dedent("""Search for packages and display associated information. + The input is a MatchSpec, a query language for conda packages. + See examples below. + """) + + example = dedent(""" + Examples: + + Search for a specific package named 'scikit-learn': + + conda search scikit-learn + + Search for packages containing 'scikit' in the package name: + + conda search *scikit* + + Note that your shell may expand '*' before handing the command over to conda. + Therefore it is sometimes necessary to use single or double quotes around the query. + + conda search '*scikit' + conda search "*scikit*" + + Search for packages for 64-bit Linux (by default, packages for your current + platform are shown): + + conda search numpy[subdir=linux-64] + + Search for a specific version of a package: + + conda search 'numpy>=1.12' + + Search for a package on a specific channel + + conda search conda-forge::numpy + conda search 'numpy[channel=conda-forge, subdir=osx-64]' + """) + p = sub_parsers.add_parser( + 'search', + description=descr, + help=descr, + epilog=example, + ) + add_parser_prefix(p) + p.add_argument( + "--canonical", + action="store_true", + help=SUPPRESS, + ) + p.add_argument( + '-f', "--full-name", + action="store_true", + help=SUPPRESS, + ) + p.add_argument( + '-i', "--info", + action="store_true", + help="Provide detailed information about each package. " + "Similar to output of 'conda info package-name'." + ) + p.add_argument( + "--names-only", + action="store_true", + help=SUPPRESS, + ) + add_parser_known(p) + add_parser_use_index_cache(p) + p.add_argument( + '-o', "--outdated", + action="store_true", + help=SUPPRESS, + ) + p.add_argument( + '--platform', + action='store', + dest='platform', + help="""Search the given platform. Should be formatted like 'osx-64', 'linux-32', + 'win-64', and so on. The default is to search the current platform.""", + default=None, + ) + p.add_argument( + 'match_spec', + default='*', + nargs='?', + help=SUPPRESS, + ) + p.add_argument( + "--spec", + action="store_true", + help=SUPPRESS, + ) + p.add_argument( + "--reverse-dependency", + action="store_true", + help="Perform a reverse dependency search. When using this flag, the --full-name " + "flag is recommended. Use 'conda info package' to see the dependencies of a " + "package.", + ) + add_parser_offline(p) + add_parser_channels(p) + add_parser_json(p) + add_parser_use_local(p) + add_parser_insecure(p) + p.set_defaults(func='.main_search.execute') + + +def configure_parser_update(sub_parsers, name='update'): + help = "Updates conda packages to the latest compatible version." + descr = dedent(help + """ + + This command accepts a list of package names and updates them to the latest + versions that are compatible with all other packages in the environment. + + Conda attempts to install the newest versions of the requested packages. To + accomplish this, it may update some packages that are already installed, or + install additional packages. To prevent existing packages from updating, + use the --no-update-deps option. This may force conda to install older + versions of the requested packages, and it does not prevent additional + dependency packages from being installed. + + If you wish to skip dependency checking altogether, use the '--force' + option. This may result in an environment with incompatible packages, so + this option must be used with great caution. + """) + example = dedent(""" + Examples: + + conda %s -n myenv scipy + + """) + + alias_help = "Alias for conda update. See conda update --help." + if name == 'update': + p = sub_parsers.add_parser( + 'update', + description=descr, + help=descr, + epilog=example % name, + ) + else: + p = sub_parsers.add_parser( + name, + description=alias_help, + help=alias_help, + epilog=example % name, + ) + add_parser_create_install_update(p) + add_parser_json(p) + p.add_argument( + "--all", + action="store_true", + help="Update all installed packages in the environment.", + ) + p.set_defaults(func='.main_update.execute') + + +# ############################################################################################# +# +# parser helpers +# +# ############################################################################################# diff --git a/conda/common/configuration.py b/conda/common/configuration.py index c0c7768818f..795f5a965e8 100644 --- a/conda/common/configuration.py +++ b/conda/common/configuration.py @@ -29,7 +29,7 @@ from .compat import (isiterable, iteritems, itervalues, odict, primitive_types, string_types, text_type, with_metaclass) -from .constants import EMPTY_MAP, NULL +from .constants import NULL from .path import expand from .serialize import yaml_load from .. import CondaError, CondaMultiError @@ -55,6 +55,8 @@ log = getLogger(__name__) +EMPTY_MAP = frozendict() + def pretty_list(iterable, padding=' '): # TODO: move elsewhere in conda.common if not isiterable(iterable): diff --git a/conda/common/constants.py b/conda/common/constants.py index 9f73219c91c..43dc2179d33 100644 --- a/conda/common/constants.py +++ b/conda/common/constants.py @@ -1,10 +1,7 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import, division, print_function, unicode_literals -from .._vendor.auxlib.collection import NULL, frozendict - -EMPTY_MAP = frozendict() - +from .._vendor.auxlib import NULL # Use this NULL object when needing to distinguish a value from None # For example, when parsing json, you may need to determine if a json key was given and set diff --git a/setup.cfg b/setup.cfg index 4c360a087c4..cf0a7ac1d04 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,13 +24,13 @@ markers = [pep8] max-line-length = 99 ignore = E126,E133,E226,E241,E242,E302,E704,E731,W503 -exclude = build/*,.tox/*,tests/*,ve/*,*/_vendor/*,conda/compat.py,conda/common/compat.py,conda_env/compat.py +exclude = build/*,env/*,.tox/*,tests/*,ve/*,*/_vendor/*,conda/compat.py,conda/common/compat.py,conda_env/compat.py [flake8] max-line-length = 99 ignore = E126,E133,E226,E241,E242,E302,E704,E731,W503 -exclude = build/*,.tox/*,tests/*,ve/*,*/_vendor/*,conda/compat.py,conda/common/compat.py,conda_env/compat.py +exclude = build/*,env/*,.tox/*,tests/*,ve/*,*/_vendor/*,conda/compat.py,conda/common/compat.py,conda_env/compat.py [coverage:report]