Skip to content
Commits on Source (3)
......@@ -36,3 +36,6 @@ miniconda*.exe
docs/source/_build
**/.vscode
conda.tmp/
*.iml
*.ipr
*.iws
## 4.8.1 (2019-12-19)
### Enhancements:
* improve performance for conda run by avoiding Popen.communicate (#9381)
* Put conda keyring in /usr/share/keyrings on Debian (#9424)
* refactor common.logic to fix some bugs and prepare for better modularity (#9427)
* Support nested configuration (#9449)
* Support Object configuration parameters (#9465)
* Use freeze_installed to speed up conda env update (#9511)
* add networking args to conda env create (#9525)
### Docs:
* fix string concatenation running words together regarding CONDA_EXE (#9411)
* Fix typo ("list" -> "info") (#9433)
* typo in condarc key envs_dirs (#9478)
* Clarify channel priority and package sorting (#9492)
* improve description of DLL loading verification and activating environments (#9453)
* Installing with specific build number (#9534)
### Bug fixes:
* Fix calling python api run_command with list and string arguments (#9331)
* revert init bash completion (#9421)
* set tmp to shortened path that excludes spaces (#9409)
* avoid function redefinition upon resourcing conda.fish (#9444)
* propagate pip error level when creating envs with conda env (#9460)
* fix incorrect chown call (#9464)
* Add subdir to PackageRecord dist_str (#9418)
* Fix running conda activate in multiple processes on windows (#9477)
* Don't check in pkgs for trash (#9472)
* remove setuptools from run_constrained in recipe (#9485)
* Fix `__conda_activate` function to correctly return exit code (#9532)
* fix overly greedy capture done by subprocess for conda run (#9537)
### Contributors:
* @AntoinePrv
* @brettcannon
* @bwildenhain
* @cjmartian
* @felker
* @forrestwaters
* @gilescope
* @isuruf
* @jeremyjliu
* @jjhelmus
* @jhultman
* @marcuscaisey
* @mbargull
* @mingwandroid
* @msarahan
* @okhoma
* @osamoylenko
* @rrigdon
* @rulerofthehuns
* @soapy1
* @tartansandal
## 4.8.0rc0 (2019-11-04)
### Enhancements:
* retry downloads if they fail, controlled by `remote_max_retries` and `remote_backoff_factor` configuration values (#9318)
* redact authentication information in some URLs (#9341)
* add osx version virtual package , `__osx` (#9349)
* add glibc virtual package, `__glibc` (#9358)
### Docs
* removeed references to MD5s from docs (#9247)
* Add docs on `CONDA_DLL_SEARCH_MODIFICATION_ENABLED` (#9286)
* document threads, spec history and configuration (#9327)
* more documentation on channels (#9335)
* document the .condarc search order (#9369)
* various minor documentation fixes (#9238, #9248, #9267, #9334, #9351, #9372, #9378, #9388, #9391, #9393)
### Bug fixes
* fix issues with xonsh activation on Windows (#8246)
* remove unsupported --lock argument from conda clean (#8310)
* do not add `sys_prefix_path` to failed activation or deactivation (#9282)
* fix csh setenv command (#9284)
* do not memorize `PackageRecord.combined_depends` (#9289)
* use `CONDA_INTERNAL_OLDPATH` rather than `OLDPATH` in activation script (#9303)
* fixes xonsh activation and tab completion (#9305)
* fix what channels are queried when context.offline is True (#9385)
### Contributors
* @analog-cbarber
* @andreasg123
* @beckermr
* @bryant1410
* @colinbrislawn
* @felker
* @forrestwaters
* @gabrielcnr
* @isuruf
* @jakirkham
* @jeremyjliu
* @jjhelmus
* @jooh
* @jpigla
* @marcelotrevisani
* @melund
* @mfansler
* @mingwandroid
* @msarahan
* @rrigdon
* @scopatz
* @soapy1
* @WillyChen123
* @xhochy
## 4.7.12 (2019-09-12)
### Enhancements:
......
......@@ -18,7 +18,7 @@ main_test: &main_test
if [[ $(git diff origin/master --name-only | wc -l) == $(git diff origin/master --name-only | grep docs | wc -l) && $(git diff origin/master --name-only | grep docs) ]]; then
echo "Only docs changed detected, skipping tests"
else
echo "local_repodata_ttl: 1800" >> ~/.condarc
echo "local_repodata_ttl: 1800" > ~/.condarc
eval "$(sudo /opt/conda/bin/python -m conda init --dev bash)"
conda info
# remove the pkg cache. We can't hardlink from here anyway. Having it around causes log problems.
......@@ -74,7 +74,7 @@ conda_build_test: &conda_build_test
# pre-populating the package cache helps avoid race conditions for testing in parallel
command: |
eval "$(sudo /opt/conda/bin/python -m conda init --dev bash)"
echo "safety_checks: disabled" >> ~/.condarc
echo "safety_checks: disabled" > ~/.condarc
echo "local_repodata_ttl: 1800" >> ~/.condarc
conda create -n blarg -yq --download-only python=2.7
conda create -n blarg -yq -c https://repo.anaconda.com/pkgs/free --download-only python=3.4
......
......@@ -10,10 +10,11 @@ from glob import glob
from itertools import chain
from logging import getLogger
import os
from os.path import abspath, basename, dirname, expanduser, expandvars, isdir, join
from os.path import abspath, basename, dirname, expanduser, expandvars, isdir, join, exists
import re
import sys
from textwrap import dedent
import json
# Since we have to have configuration context here, anything imported by
# conda.base.context is fair game, but nothing more.
......@@ -23,6 +24,7 @@ from ._vendor.auxlib.compat import Utf8NamedTemporaryFile
from .base.context import ROOT_ENV_NAME, context, locate_prefix_by_name
from .common.compat import FILESYSTEM_ENCODING, PY2, iteritems, on_win, string_types, text_type
from .common.path import paths_equal
from .base.constants import PREFIX_STATE_FILE, PACKAGE_ENV_VARS_DIR, CONDA_ENV_VARS_UNSET_VAR
log = getLogger(__name__)
......@@ -244,13 +246,24 @@ class _Activator(object):
context.dev = True
if command == 'activate':
self.stack = context.auto_stack and context.shlvl <= context.auto_stack
try:
stack_idx = remainder_args.index('--stack')
except ValueError:
self.stack = False
else:
del remainder_args[stack_idx]
stack_idx = -1
try:
no_stack_idx = remainder_args.index('--no-stack')
except ValueError:
no_stack_idx = -1
if stack_idx >= 0 and no_stack_idx >= 0:
from .exceptions import ArgumentError
raise ArgumentError('cannot specify both --stack and --no-stack to ' + command)
if stack_idx >= 0:
self.stack = True
del remainder_args[stack_idx]
if no_stack_idx >= 0:
self.stack = False
del remainder_args[no_stack_idx]
if len(remainder_args) > 1:
from .exceptions import ArgumentError
raise ArgumentError(command + ' does not accept more than one argument:\n'
......@@ -312,17 +325,34 @@ class _Activator(object):
activate_scripts = self._get_activate_scripts(prefix)
conda_default_env = self._default_env(prefix)
conda_prompt_modifier = self._prompt_modifier(prefix, conda_default_env)
conda_environment_env_vars = self._get_environment_env_vars(prefix)
unset_env_vars = [k for k, v in conda_environment_env_vars.items()
if v == CONDA_ENV_VARS_UNSET_VAR]
[conda_environment_env_vars.pop(_) for _ in unset_env_vars]
clobbering_env_vars = [k for k in conda_environment_env_vars.keys()
if k in os.environ.keys()]
for cvar in clobbering_env_vars:
save_var = "__CONDA_SHLVL_%s_%s" % (old_conda_shlvl, cvar)
conda_environment_env_vars[save_var] = os.environ.get(cvar)
if clobbering_env_vars:
print("WARNING: overwriting environment variables set in the machine", file=sys.stderr)
print("overwriting variable %s" % ' '.join(clobbering_env_vars), file=sys.stderr)
unset_vars = []
if old_conda_shlvl == 0:
new_path = self.pathsep_join(self._add_prefix_to_path(prefix))
export_vars, unset_vars = self.get_export_unset_vars(
odargs=OrderedDict((
env_vars_to_export = OrderedDict((
('path', new_path),
('conda_prefix', prefix),
('conda_shlvl', new_conda_shlvl),
('conda_default_env', conda_default_env),
('conda_prompt_modifier', conda_prompt_modifier))))
('conda_prompt_modifier', conda_prompt_modifier)))
for k, v in conda_environment_env_vars.items():
env_vars_to_export[k] = v
export_vars, unset_vars = self.get_export_unset_vars(odargs=env_vars_to_export)
deactivate_scripts = ()
else:
if self.environ.get('CONDA_PREFIX_%s' % (old_conda_shlvl - 1)) == prefix:
......@@ -332,24 +362,30 @@ class _Activator(object):
if stack:
new_path = self.pathsep_join(self._add_prefix_to_path(prefix))
deactivate_scripts = ()
export_vars, unset_vars = self.get_export_unset_vars(odargs=OrderedDict((
env_vars_to_export = OrderedDict((
('path', new_path),
('conda_prefix', prefix),
('conda_shlvl', new_conda_shlvl),
('conda_default_env', conda_default_env),
('conda_prompt_modifier', conda_prompt_modifier))))
('conda_prompt_modifier', conda_prompt_modifier)))
for k, v in conda_environment_env_vars.items():
env_vars_to_export[k] = v
export_vars, unset_vars = self.get_export_unset_vars(odargs=env_vars_to_export)
export_vars['CONDA_PREFIX_%d' % old_conda_shlvl] = old_conda_prefix
export_vars['CONDA_STACKED_%d' % new_conda_shlvl] = 'true'
else:
new_path = self.pathsep_join(
self._replace_prefix_in_path(old_conda_prefix, prefix))
deactivate_scripts = self._get_deactivate_scripts(old_conda_prefix)
export_vars, unset_vars = self.get_export_unset_vars(odargs=OrderedDict((
env_vars_to_export = OrderedDict((
('path', new_path),
('conda_prefix', prefix),
('conda_shlvl', new_conda_shlvl),
('conda_default_env', conda_default_env),
('conda_prompt_modifier', conda_prompt_modifier))))
('conda_prompt_modifier', conda_prompt_modifier)))
for k, v in conda_environment_env_vars.items():
env_vars_to_export[k] = v
export_vars, unset_vars = self.get_export_unset_vars(odargs=env_vars_to_export)
export_vars['CONDA_PREFIX_%d' % old_conda_shlvl] = old_conda_prefix
set_vars = {}
......@@ -381,6 +417,7 @@ class _Activator(object):
'activate_scripts': (),
}
deactivate_scripts = self._get_deactivate_scripts(old_conda_prefix)
old_conda_environment_env_vars = self._get_environment_env_vars(old_conda_prefix)
new_conda_shlvl = old_conda_shlvl - 1
set_vars = {}
......@@ -406,6 +443,7 @@ class _Activator(object):
new_prefix = self.environ.get('CONDA_PREFIX_%d' % new_conda_shlvl)
conda_default_env = self._default_env(new_prefix)
conda_prompt_modifier = self._prompt_modifier(new_prefix, conda_default_env)
new_conda_environment_env_vars = self._get_environment_env_vars(new_prefix)
old_prefix_stacked = 'CONDA_STACKED_%d' % old_conda_shlvl in self.environ
new_path = ''
......@@ -419,11 +457,14 @@ class _Activator(object):
self._replace_prefix_in_path(old_conda_prefix, new_prefix)
)
export_vars, unset_vars2 = self.get_export_unset_vars(odargs=OrderedDict((
env_vars_to_export = OrderedDict((
('conda_prefix', new_prefix),
('conda_shlvl', new_conda_shlvl),
('conda_default_env', conda_default_env),
('conda_prompt_modifier', conda_prompt_modifier))))
('conda_prompt_modifier', conda_prompt_modifier)))
for k, v in new_conda_environment_env_vars.items():
env_vars_to_export[k] = v
export_vars, unset_vars2 = self.get_export_unset_vars(odargs=env_vars_to_export)
unset_vars += unset_vars2
export_path = {'PATH': new_path, }
activate_scripts = self._get_activate_scripts(new_prefix)
......@@ -431,6 +472,11 @@ class _Activator(object):
if context.changeps1:
self._update_prompt(set_vars, conda_prompt_modifier)
for env_var in old_conda_environment_env_vars.keys():
unset_vars.append(env_var)
save_var = "__CONDA_SHLVL_%s_%s" % (new_conda_shlvl, env_var)
if save_var in os.environ.keys():
export_vars[env_var] = os.environ[save_var]
return {
'unset_vars': unset_vars,
'set_vars': set_vars,
......@@ -456,19 +502,27 @@ class _Activator(object):
conda_default_env = self.environ.get('CONDA_DEFAULT_ENV', self._default_env(conda_prefix))
new_path = self.pathsep_join(self._replace_prefix_in_path(conda_prefix, conda_prefix))
set_vars = {}
conda_prompt_modifier = self._prompt_modifier(conda_prefix, conda_default_env)
if context.changeps1:
self._update_prompt(set_vars, conda_prompt_modifier)
env_vars_to_unset = ()
env_vars_to_export = OrderedDict([
('PATH', new_path),
('CONDA_SHLVL', conda_shlvl),
('CONDA_PROMPT_MODIFIER', self._prompt_modifier(conda_prefix, conda_default_env)),
])
conda_environment_env_vars = self._get_environment_env_vars(conda_prefix)
for k, v in conda_environment_env_vars.items():
if v == CONDA_ENV_VARS_UNSET_VAR:
env_vars_to_unset = env_vars_to_unset + (k,)
else:
env_vars_to_export[k] = v
# environment variables are set only to aid transition from conda 4.3 to conda 4.4
return {
'unset_vars': (),
'unset_vars': env_vars_to_unset,
'set_vars': set_vars,
'export_vars': OrderedDict([('PATH', new_path),
('CONDA_SHLVL', conda_shlvl),
('CONDA_PROMPT_MODIFIER', self._prompt_modifier(
conda_prefix, conda_default_env))]),
'export_vars': env_vars_to_export,
'deactivate_scripts': self._get_deactivate_scripts(conda_prefix),
'activate_scripts': self._get_activate_scripts(conda_prefix),
}
......@@ -651,6 +705,31 @@ class _Activator(object):
prefix, 'etc', 'conda', 'deactivate.d', '*' + self.script_extension
)), reverse=True))
def _get_environment_env_vars(self, prefix):
env_vars_file = join(prefix, PREFIX_STATE_FILE)
pkg_env_var_dir = join(prefix, PACKAGE_ENV_VARS_DIR)
env_vars = OrderedDict()
# First get env vars from packages
if exists(pkg_env_var_dir):
for pkg_env_var_file in sorted(os.listdir(pkg_env_var_dir)):
with open(join(pkg_env_var_dir, pkg_env_var_file), 'r') as f:
env_vars.update(json.loads(f.read(), object_pairs_hook=OrderedDict))
# Then get env vars from environment specification
if exists(env_vars_file):
with open(env_vars_file, 'r') as f:
prefix_state = json.loads(f.read(), object_pairs_hook=OrderedDict)
prefix_state_env_vars = prefix_state.get('env_vars', {})
dup_vars = [ev for ev in env_vars.keys() if ev in prefix_state_env_vars.keys()]
for dup in dup_vars:
print("WARNING: duplicate env vars detected. Vars from the environment "
"will overwrite those from packages", file=sys.stderr)
print("variable %s duplicated" % dup, file=sys.stderr)
env_vars.update(prefix_state_env_vars)
return env_vars
def expand(path):
return abspath(expanduser(expandvars(path)))
......@@ -833,25 +912,43 @@ class CshActivator(_Activator):
class XonshActivator(_Activator):
@staticmethod
def path_conversion(paths):
if not on_win:
return path_identity(paths)
elif isinstance(paths, string_types):
return paths.replace('\\', '/')
elif paths is None:
return None
else:
return tuple([path.replace('\\', '/') for path in paths])
def __init__(self, arguments=None):
self.pathsep_join = ':'.join
self.pathsep_join = ';'.join if on_win else ':'.join
self.sep = '/'
self.path_conversion = native_path_to_unix
self.script_extension = '.xsh'
self.tempfile_extension = None
self.command_join = '\n'
self.unset_var_tmpl = 'del $%s'
self.export_var_tmpl = "$%s = '%s'"
self.set_var_tmpl = "$%s = '%s'" # TODO: determine if different than export_var_tmpl
self.run_script_tmpl = 'source "%s"'
# 'scripts' really refer to de/activation scripts, not scripts in the language per se
# xonsh can piggy-back activation scripts from other languages depending on the platform
import platform
if platform.system() == 'Windows':
self.script_extension = '.bat'
self.run_script_tmpl = 'source-cmd "%s"'
else:
self.script_extension = '.sh'
self.run_script_tmpl = 'source-bash "%s"'
self.hook_source_path = join(CONDA_PACKAGE_ROOT, 'shell', 'conda.xsh')
super(XonshActivator, self).__init__(arguments)
def _hook_preamble(self):
return '$CONDA_EXE = "%s"' % context.conda_exe
return '$CONDA_EXE = "%s"' % self.path_conversion(context.conda_exe)
class CmdExeActivator(_Activator):
......
......@@ -228,6 +228,10 @@ class SatSolverChoice(Enum):
PACKAGE_CACHE_MAGIC_FILE = 'urls.txt'
PREFIX_MAGIC_FILE = join('conda-meta', 'history')
PREFIX_STATE_FILE = join('conda-meta', 'state')
PACKAGE_ENV_VARS_DIR = join('etc', 'conda', 'env_vars.d')
CONDA_ENV_VARS_UNSET_VAR = "***unset***"
# TODO: should be frozendict(), but I don't want to import frozendict from auxlib here.
NAMESPACES_MAP = { # base package name, namespace
......
This diff is collapsed.
......@@ -79,8 +79,7 @@ def do_call(args, parser):
from importlib import import_module
module = import_module(relative_mod, __name__.rsplit('.', 1)[0])
exit_code = getattr(module, func_name)(args, parser)
return exit_code
return getattr(module, func_name)(args, parser)
def find_builtin_commands(parser):
......@@ -228,11 +227,6 @@ def configure_parser_clean(sub_parsers):
action="store_true",
help="Remove index cache.",
)
removal_target_options.add_argument(
"-l", "--lock",
action="store_true",
help="Remove all conda lock files.",
)
removal_target_options.add_argument(
'-p', '--packages',
action='store_true',
......@@ -518,7 +512,7 @@ def configure_parser_config(sub_parsers):
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 "
descr = (help + "To use the created environment, use 'conda activate "
"envname' look in that directory first. This command requires either "
"the -n NAME or -p PREFIX option.")
......@@ -554,7 +548,7 @@ def configure_parser_create(sub_parsers):
p.add_argument(
"--dev",
action=NullCountAction,
help="Use `sys.executable -m conda` in wrapper scripts instead of CONDA_EXE "
help="Use `sys.executable -m conda` in wrapper scripts instead of CONDA_EXE. "
"This is mainly for use during tests where we test new conda source "
"against old Python versions.",
dest="dev",
......@@ -775,7 +769,7 @@ def configure_parser_install(sub_parsers):
p.add_argument(
"--dev",
action=NullCountAction,
help="Use `sys.executable -m conda` in wrapper scripts instead of CONDA_EXE "
help="Use `sys.executable -m conda` in wrapper scripts instead of CONDA_EXE. "
"This is mainly for use during tests where we test new conda source "
"against old Python versions.",
dest="dev",
......@@ -996,7 +990,7 @@ def configure_parser_remove(sub_parsers, name='remove'):
p.add_argument(
"--dev",
action=NullCountAction,
help="Use `sys.executable -m conda` in wrapper scripts instead of CONDA_EXE "
help="Use `sys.executable -m conda` in wrapper scripts instead of CONDA_EXE. "
"This is mainly for use during tests where we test new conda source "
"against old Python versions.",
dest="dev",
......
......@@ -3,13 +3,13 @@ from __future__ import absolute_import, division, print_function, unicode_litera
from logging import getLogger
import os
from subprocess import PIPE, Popen
import sys
from ..base.context import context
from ..utils import wrap_subprocess_call
from ..gateways.disk.delete import rm_rf
from ..common.compat import encode_environment
from ..gateways.subprocess import subprocess_call
def execute(args, parser):
......@@ -22,21 +22,12 @@ def execute(args, parser):
script_caller, command_args = wrap_subprocess_call(on_win, context.root_prefix, prefix,
args.dev, args.debug_wrapper_scripts, call)
env = encode_environment(os.environ.copy())
process = Popen(command_args, universal_newlines=False, stdout=PIPE, stderr=PIPE,
env=env, cwd=cwd)
stdout, stderr = process.communicate()
if hasattr(stdout, "decode"):
stdout = stdout.decode('utf-8', errors='replace')
if hasattr(stderr, "decode"):
stderr = stderr.decode('utf-8', errors='replace')
if stdout:
sys.stdout.write(stdout)
if stderr:
sys.stderr.write(stderr)
if process.returncode != 0:
response = subprocess_call(command_args, env=env, path=cwd, raise_on_error=False)
if response.rc != 0:
log = getLogger(__name__)
log.error("Subprocess for 'conda run {}' command failed. Stderr was:\n{}"
.format(call, stderr))
log.error("Subprocess for 'conda run {}' command failed. (See above for error)"
.format(call))
if script_caller is not None:
if 'CONDA_TEST_SAVE_TEMPS' not in os.environ:
rm_rf(script_caller)
......@@ -44,4 +35,8 @@ def execute(args, parser):
log = getLogger(__name__)
log.warning('CONDA_TEST_SAVE_TEMPS :: retaining main_run script_caller {}'.format(
script_caller))
return process.returncode
if response.stdout:
print(response.stdout, file=sys.stdout)
if response.stderr:
print(response.stderr, file=sys.stderr)
return response
......@@ -81,6 +81,9 @@ def run_command(command, *arguments, **kwargs):
stderr = kwargs.pop('stderr', STRING)
p = generate_parser()
if len(arguments) > 0 and isinstance(arguments[0], list):
arguments = arguments[0]
arguments = list(arguments)
arguments.insert(0, command)
......@@ -93,16 +96,29 @@ def run_command(command, *arguments, **kwargs):
from subprocess import list2cmdline
log.debug("executing command >>> conda %s", list2cmdline(arguments))
is_run = arguments[0] == 'run'
if is_run:
cap_args = (None, None)
else:
cap_args = (stdout, stderr)
try:
with argv(['python_api'] + encode_arguments(arguments)), captured(stdout, stderr) as c:
with argv(['python_api'] + encode_arguments(arguments)), captured(*cap_args) as c:
if use_exception_handler:
return_code = conda_exception_handler(do_call, args, p)
result = conda_exception_handler(do_call, args, p)
else:
result = do_call(args, p)
if is_run:
stdout = result.stdout
stderr = result.stderr
result = result.rc
else:
return_code = do_call(args, p)
stdout = c.stdout
stderr = c.stderr
except Exception as e:
log.debug("\n stdout: %s\n stderr: %s", c.stdout, c.stderr)
e.stdout, e.stderr = c.stdout, c.stderr
log.debug("\n stdout: %s\n stderr: %s", stdout, stderr)
e.stdout, e.stderr = stdout, stderr
raise e
return_code = return_code or 0
log.debug("\n stdout: %s\n stderr: %s\n return_code: %s", c.stdout, c.stderr, return_code)
return c.stdout, c.stderr, return_code
return_code = result or 0
log.debug("\n stdout: %s\n stderr: %s\n return_code: %s", stdout, stderr, return_code)
return stdout, stderr, return_code
This diff is collapsed.
......@@ -16,6 +16,7 @@ import warnings as _warnings
on_win = bool(sys.platform == "win32")
on_mac = bool(sys.platform == "darwin")
on_linux = bool(sys.platform == "linux")
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
......
This diff is collapsed.
This diff is collapsed.
......@@ -365,7 +365,14 @@ def maybe_add_auth(url, auth, force=False):
def maybe_unquote(url):
return unquote_plus(url) if url else url
return unquote_plus(remove_auth(url)) if url else url
def remove_auth(url):
url_parts = parse_url(url)._asdict()
if url_parts['auth']:
del url_parts['auth']
return Url(**url_parts).url
if __name__ == "__main__":
......
......@@ -5,7 +5,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
from errno import EACCES, EROFS, ENOENT
from logging import getLogger
from os import devnull, listdir, makedirs
from os import devnull, listdir
from os.path import dirname, isdir, isfile, join, normpath
from .prefix_data import PrefixData
......
......@@ -3,6 +3,7 @@
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import absolute_import, division, print_function, unicode_literals
import os
from itertools import chain
from logging import getLogger
......@@ -157,6 +158,19 @@ def _supplement_index_with_system(index):
rec = _make_virtual_package('__cuda', cuda_version)
index[rec] = rec
dist_name, dist_version = context.os_distribution_name_version
if dist_name == 'OSX':
dist_version = os.environ.get('CONDA_OVERRIDE_OSX', dist_version)
if len(dist_version) > 0:
rec = _make_virtual_package('__osx', dist_version)
index[rec] = rec
libc_family, libc_version = context.libc_family_version
if libc_family and libc_version:
libc_version = os.getenv("CONDA_OVERRIDE_{}".format(libc_family.upper()), libc_version)
rec = _make_virtual_package('__' + libc_family, libc_version)
index[rec] = rec
def calculate_channel_urls(channel_urls=(), prepend=True, platform=None, use_local=False):
if use_local:
......
......@@ -1199,7 +1199,7 @@ def _bashrc_content(conda_prefix, shell):
if ( -f "%(conda_prefix)s/etc/profile.d/conda.csh" ) then
source "%(conda_prefix)s/etc/profile.d/conda.csh"
else
setenv PATH="%(conda_bin)s:$PATH"
setenv PATH "%(conda_bin)s:$PATH"
endif
# <<< conda initialize <<<
""") % {
......
......@@ -8,9 +8,12 @@ from logging import getLogger
from os import listdir
from os.path import basename, isdir, isfile, join, lexists
import re
from collections import OrderedDict
import json
from ..base.constants import PREFIX_STATE_FILE
from .._vendor.auxlib.exceptions import ValidationError
from ..base.constants import CONDA_PACKAGE_EXTENSIONS, PREFIX_MAGIC_FILE
from ..base.constants import CONDA_PACKAGE_EXTENSIONS, PREFIX_MAGIC_FILE, CONDA_ENV_VARS_UNSET_VAR
from ..base.context import context
from ..common.compat import JSONDecodeError, itervalues, odict, string_types, with_metaclass
from ..common.constants import NULL
......@@ -295,6 +298,49 @@ class PrefixData(object):
return new_packages
def _get_environment_state_file(self):
env_vars_file = join(self.prefix_path, PREFIX_STATE_FILE)
if lexists(env_vars_file):
with open(env_vars_file, 'r') as f:
prefix_state = json.loads(f.read(), object_pairs_hook=OrderedDict)
else:
prefix_state = {}
return prefix_state
def _write_environment_state_file(self, state):
env_vars_file = join(self.prefix_path, PREFIX_STATE_FILE)
with open(env_vars_file, 'w') as f:
f.write(json.dumps(state, ensure_ascii=False, default=lambda x: x.__dict__))
def get_environment_env_vars(self):
prefix_state = self._get_environment_state_file()
env_vars_all = OrderedDict(prefix_state.get('env_vars', {}))
env_vars = {
k: v for k, v in env_vars_all.items()
if v != CONDA_ENV_VARS_UNSET_VAR
}
return env_vars
def set_environment_env_vars(self, env_vars):
env_state_file = self._get_environment_state_file()
current_env_vars = env_state_file.get('env_vars')
if current_env_vars:
current_env_vars.update(env_vars)
else:
env_state_file['env_vars'] = env_vars
self._write_environment_state_file(env_state_file)
return env_state_file.get('env_vars')
def unset_environment_env_vars(self, env_vars):
env_state_file = self._get_environment_state_file()
current_env_vars = env_state_file.get('env_vars')
if current_env_vars:
for env_var in env_vars:
if env_var in current_env_vars.keys():
current_env_vars[env_var] = CONDA_ENV_VARS_UNSET_VAR
self._write_environment_state_file(env_state_file)
return env_state_file.get('env_vars')
def get_conda_anchor_files_and_records(site_packages_short_path, python_records):
"""Return the anchor files for the conda records of python packages."""
......
......@@ -22,12 +22,13 @@ import warnings
from .. import CondaError
from .._vendor.auxlib.ish import dals
from .._vendor.auxlib.logz import stringify
from .._vendor.toolz import concat, take
from .._vendor.boltons.setutils import IndexedSet
from .._vendor.toolz import concat, take, groupby
from ..base.constants import CONDA_HOMEPAGE_URL, CONDA_PACKAGE_EXTENSION_V1, REPODATA_FN
from ..base.context import context
from ..common.compat import (ensure_binary, ensure_text_type, ensure_unicode, iteritems, iterkeys,
string_types, text_type, with_metaclass)
from ..common.io import ThreadLimitedThreadPoolExecutor, DummyExecutor
from ..common.io import ThreadLimitedThreadPoolExecutor, DummyExecutor, dashlist
from ..common.url import join_url, maybe_unquote
from ..core.package_cache_data import PackageCacheData
from ..exceptions import (CondaDependencyError, CondaHTTPError, CondaUpgradeError,
......@@ -85,6 +86,13 @@ class SubdirData(object):
if subdirs is None:
subdirs = context.subdirs
channel_urls = all_channel_urls(channels, subdirs=subdirs)
if context.offline:
grouped_urls = groupby(lambda url: url.startswith('file://'), channel_urls)
ignored_urls = grouped_urls.get(False, ())
if ignored_urls:
log.info("Ignoring the following channel urls because mode is offline.%s",
dashlist(ignored_urls))
channel_urls = IndexedSet(grouped_urls.get(True, ()))
check_whitelist(channel_urls)
subdir_query = lambda url: tuple(SubdirData(Channel(url), repodata_fn=repodata_fn).query(
package_ref_or_match_spec))
......@@ -570,13 +578,13 @@ def fetch_repodata_remote_request(url, etag, mod_stamp, repodata_fn=REPODATA_FN)
a support request with your network engineering team.
%s
""") % maybe_unquote(repr(e))
""") % maybe_unquote(repr(url))
else:
help_message = dals("""
An HTTP error occurred when trying to retrieve this URL.
HTTP errors are often intermittent, and a simple retry will get you on your way.
%s
""") % maybe_unquote(repr(e))
""") % maybe_unquote(repr(url))
raise CondaHTTPError(help_message,
join_url(url, filename),
......
......@@ -72,7 +72,7 @@ class ActivateHelp(Help):
def __init__(self):
message = dals("""
usage: conda activate [-h] [--stack] [env_name_or_prefix]
usage: conda activate [-h] [--[no-]stack] [env_name_or_prefix]
Activate a conda environment.
......@@ -88,7 +88,11 @@ class ActivateHelp(Help):
--stack Stack the environment being activated on top of the
previous active environment, rather replacing the
current active environment with a new one. Currently,
only the PATH environment variable is stacked.
only the PATH environment variable is stacked. This
may be enabled implicitly by the 'auto_stack'
configuration variable.
--no-stack Do not stack the environment. Overrides 'auto_stack'
setting.
""")
super(ActivateHelp, self).__init__(message)
......@@ -1364,5 +1368,4 @@ class ExceptionHandler(object):
def conda_exception_handler(func, *args, **kwargs):
exception_handler = ExceptionHandler()
return_value = exception_handler(func, *args, **kwargs)
if isinstance(return_value, int):
return return_value