def test_errors_pip_overwrites(): with pytest.raises(CondaPackException) as exc: CondaEnv.from_prefix(py36_broken_path) msg = str(exc.value) assert "pip" in msg assert "toolz" in msg
def test_missing_files(): with pytest.raises(CondaPackException) as exc: CondaEnv.from_prefix(py36_missing_files_path) msg = str(exc.value) assert "{}toolz{}__init__.py".format(os.sep, os.sep) in msg, msg assert "{}toolz{}_signatures.py".format(os.sep, os.sep) in msg, msg
def test_errors_root_environment(): info = subprocess.check_output("conda info --json", shell=True).decode() root_prefix = json.loads(info)['root_prefix'] with pytest.raises(CondaPackException) as exc: CondaEnv.from_prefix(root_prefix) assert "Cannot package root environment" in str(exc.value)
def test_missing_package_cache(broken_package_cache): with pytest.warns(UserWarning) as record: env = CondaEnv.from_prefix(py27_path) assert len(env) assert len(record) == 1 msg = str(record[0].message) assert 'conda_pack_test_lib2' in msg with pytest.raises(CondaPackException): CondaEnv.from_prefix(py27_path, on_missing_cache='raise')
def test_from_prefix(): env = CondaEnv.from_prefix(os.path.join(rel_env_dir, 'py36')) assert len(env) # relative path is normalized assert env.prefix == py36_path # Path is missing with pytest.raises(CondaPackException): CondaEnv.from_prefix(os.path.join(env_dir, "this_path_doesnt_exist")) # Path exists, but isn't a conda environment with pytest.raises(CondaPackException): CondaEnv.from_prefix(os.path.join(env_dir))
def test_from_prefix(): rel_env_dir = os.path.relpath(py36_path, os.getcwd()) env = CondaEnv.from_prefix(rel_env_dir) assert len(env) # relative path is normalized assert os.path.normcase(env.prefix) == os.path.normcase(py36_path) # Path is missing with pytest.raises(CondaPackException): CondaEnv.from_prefix(os.path.join(env_dir, "this_path_doesnt_exist")) # Path exists, but isn't a conda environment with pytest.raises(CondaPackException): CondaEnv.from_prefix(os.path.join(env_dir))
def test_pack_with_conda(tmpdir): env = CondaEnv.from_prefix(has_conda_path) out_path = os.path.join(str(tmpdir), 'has_conda.tar') env.pack(out_path) extract_path = os.path.join(str(tmpdir), 'output') os.mkdir(extract_path) assert os.path.exists(out_path) assert tarfile.is_tarfile(out_path) with tarfile.open(out_path) as fil: names = fil.getnames() # Check conda/activate/deactivate all present if on_win: assert 'Scripts/conda.exe' in names else: assert 'bin/conda' in names assert 'bin/activate' in names assert 'bin/deactivate' in names # Extract tarfile fil.extractall(extract_path) # Check the packaged conda works, and the output is a conda environment if not on_win: command = (". {path}/bin/activate && " "conda list --json -p {path} &&" ". {path}/bin/deactivate").format(path=extract_path) out = subprocess.check_output(['/usr/bin/env', 'bash', '-c', command], stderr=subprocess.STDOUT).decode() data = json.loads(out) assert 'conda' in {i['name'] for i in data} # Check the conda-meta directory has been anonymized for path in glob(os.path.join(extract_path, 'conda-meta', '*.json')): with open(path) as fil: data = json.load(fil) for field in ["extracted_package_dir", "package_tarball_full_path"]: if field in data: assert data[field] == "" if "link" in data and "source" in data["link"]: assert data["link"]["source"] == ""
def test_activate(tmpdir): out_path = os.path.join(str(tmpdir), 'activate_scripts.tar') extract_path = str(tmpdir) env = CondaEnv.from_prefix(activate_scripts_path) env.pack(out_path) with tarfile.open(out_path) as fil: fil.extractall(extract_path) # Check that activate environment variable is set command = (". {path}/bin/activate && " "test $CONDAPACK_ACTIVATED -eq 1 && " ". {path}/bin/deactivate && " "test ! $CONDAPACK_ACTIVATED && " "echo 'Done'").format(path=extract_path) out = subprocess.check_output(['/usr/bin/env', 'bash', '-c', command], stderr=subprocess.STDOUT).decode() assert out == 'Done\n'
def test_activate(tmpdir): out_path = os.path.join(str(tmpdir), 'activate_scripts.tar') extract_path = str(tmpdir.join('env')) env = CondaEnv.from_prefix(activate_scripts_path) env.pack(out_path) with tarfile.open(out_path) as fil: fil.extractall(extract_path) # Check that activate environment variable is set if on_win: command = (r"@CALL {path}\Scripts\activate" "\r\n" r"@ECHO CONDAPACK_ACTIVATED=%CONDAPACK_ACTIVATED%" "\r\n" r"@CALL {path}\Scripts\deactivate" "\r\n" r"@ECHO CONDAPACK_ACTIVATED=%CONDAPACK_ACTIVATED%" "\r\n" r"@echo Done").format(path=extract_path) unpack = tmpdir.join('unpack.bat') unpack.write(command) out = subprocess.check_output(['cmd', '/c', str(unpack)], stderr=subprocess.STDOUT).decode() assert out == 'CONDAPACK_ACTIVATED=1\r\nCONDAPACK_ACTIVATED=\r\nDone\r\n' else: command = (". {path}/bin/activate && " "test $CONDAPACK_ACTIVATED -eq 1 && " ". {path}/bin/deactivate && " "test ! $CONDAPACK_ACTIVATED && " "echo 'Done'").format(path=extract_path) out = subprocess.check_output(['/usr/bin/env', 'bash', '-c', command], stderr=subprocess.STDOUT).decode() assert out == 'Done\n'
def test_zip64(tmpdir): # Create an environment that requires ZIP64 extensions, but doesn't use a # lot of disk/RAM source = os.path.join(str(tmpdir), 'source.txt') with open(source, 'wb') as f: f.write(b'0') files = [File(source, target='foo%d' % i) for i in range(1 << 16)] large_env = CondaEnv('large', files=files) out_path = os.path.join(str(tmpdir), 'large.zip') # Errors if ZIP64 disabled with pytest.raises(CondaPackException) as exc: large_env.pack(output=out_path, zip_64=False) assert 'ZIP64' in str(exc.value) assert not os.path.exists(out_path) # Works fine if ZIP64 not disabled large_env.pack(output=out_path) assert os.path.exists(out_path)
def test_errors_conda_missing(bad_conda_exe): with pytest.raises(CondaPackException) as exc: CondaEnv.from_name('probably_fake_env') assert 'Failed to determine path to environment' in str(exc.value)
def test_errors_editable_packages(): with pytest.raises(CondaPackException) as exc: CondaEnv.from_prefix(py36_editable_path) assert "Editable packages found" in str(exc.value)
def test_missing_files(): with pytest.raises(CondaPackException) as exc: CondaEnv.from_prefix(py36_missing_files_path) msg = str(exc.value) assert "toolz" in msg
def test_missing_files_ignored(): CondaEnv.from_prefix(py36_missing_files_path, ignore_missing_files=True)
def test_pack_with_conda(tmpdir, fix_dest): env = CondaEnv.from_prefix(has_conda_path) out_path = os.path.join(str(tmpdir), 'has_conda.tar') extract_path = os.path.join(str(tmpdir), 'output') env.pack(out_path, dest_prefix=extract_path if fix_dest else None) os.mkdir(extract_path) assert os.path.exists(out_path) assert tarfile.is_tarfile(out_path) # Extract tarfile with tarfile.open(out_path, ignore_zeros=True) as fil: fil.extractall(extract_path) if on_win: fnames = ['conda.exe', 'activate.bat'] # New conda drops deactivate.bat files if not fix_dest: fnames.append("deactivate.bat") else: fnames = ['conda', 'activate', 'deactivate'] # Check conda/activate/deactivate all present for fname in fnames: fpath = os.path.join(extract_path, BIN_DIR, fname) assert os.path.exists(fpath) # Make sure we have replaced the activate/deactivate scripts # if the dest_prefix was not fixed; make sure we haven't # done so if it is. if 'activate' in fname: with open(fpath) as fp: data = fp.read() if fix_dest: assert 'CONDA_PACK' not in data else: assert 'CONDA_PACK' in data # Check the packaged conda works and recognizes its environment. # We need to unset CONDA_PREFIX to simulate unpacking into an environment # where conda is not already present. if on_win: if fix_dest: # XXX: Conda windows activatation scripts now seem to assume a base # conda install, rather than relative paths. Given that this tool # is mostly for deploying code, and usually on servers (not # windows), this failure isn't critical but isn't 100% correct. # Ideally this test shouldn't need to special case `fix_dest`, and # use the same batch commands in both cases. commands = (r"@call {path}\condabin\conda activate".format( path=extract_path), r"@conda info --json", r"@conda deactivate") else: commands = (r"@set CONDA_PREFIX=", r"@set CONDA_SHVL=", r"@call {path}\Scripts\activate".format( path=extract_path), r"@conda info --json", r"@deactivate") script_file = tmpdir.join('unpack.bat') cmd = ['cmd', '/c', str(script_file)] else: commands = ("unset CONDA_PREFIX", "unset CONDA_SHLVL", ". {path}/bin/activate".format(path=extract_path), "conda info --json", ". deactivate >/dev/null 2>/dev/null") script_file = tmpdir.join('unpack.sh') cmd = ['/usr/bin/env', 'bash', str(script_file)] script_file.write('\n'.join(commands)) out = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode() conda_info = json.loads(out) extract_path_n = normpath(extract_path) for var in ('conda_prefix', 'sys.prefix', 'default_prefix', 'root_prefix'): assert normpath(conda_info[var]) == extract_path_n assert extract_path_n in list(map(normpath, conda_info['envs'])) # Check the conda-meta directory has been anonymized for path in glob(os.path.join(extract_path, 'conda-meta', '*.json')): with open(path) as fil: data = json.load(fil) for field in ["extracted_package_dir", "package_tarball_full_path"]: if field in data: assert data[field] == "" if "link" in data and "source" in data["link"]: assert data["link"]["source"] == ""
def py36_env(): return CondaEnv.from_prefix(py36_path)
def test_works_with_no_python(): # Collection doesn't require python env = CondaEnv.from_prefix(nopython_path) # non-empty assert len(env)
def test_ignore_errors_editable_packages(): CondaEnv.from_prefix(py36_editable_path, ignore_editable_packages=True)
def test_pack_with_conda(tmpdir, fix_dest): env = CondaEnv.from_prefix(has_conda_path) out_path = os.path.join(str(tmpdir), 'has_conda.tar') extract_path = os.path.join(str(tmpdir), 'output') env.pack(out_path, dest_prefix=extract_path if fix_dest else None) os.mkdir(extract_path) assert os.path.exists(out_path) assert tarfile.is_tarfile(out_path) # Extract tarfile with tarfile.open(out_path) as fil: fil.extractall(extract_path) if on_win: fnames = ('conda.exe', 'activate.bat', 'deactivate.bat') else: fnames = ('conda', 'activate', 'deactivate') # Check conda/activate/deactivate all present for fname in fnames: fpath = os.path.join(extract_path, BIN_DIR, fname) assert os.path.exists(fpath) # Make sure we have replaced the activate/deactivate scripts # if the dest_prefix was not fixed; make sure we haven't # done so if it is. if 'activate' in fname: with open(fpath) as fp: data = fp.read() if fix_dest: assert 'CONDA_PACK' not in data else: assert 'CONDA_PACK' in data # Check the packaged conda works and recognizes its environment. # We need to unset CONDA_PREFIX to simulate unpacking into an environment # where conda is not already present. if on_win: commands = (r"@set CONDA_PREFIX=", r"@call {path}\Scripts\activate".format(path=extract_path), r"@conda info --json", r"@deactivate") script_file = tmpdir.join('unpack.bat') cmd = ['cmd', '/c', str(script_file)] else: commands = ("unset CONDA_PREFIX", ". {path}/bin/activate".format(path=extract_path), "conda info --json", ". deactivate") script_file = tmpdir.join('unpack.sh') cmd = ['/usr/bin/env', 'bash', str(script_file)] script_file.write('\n'.join(commands)) out = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode() conda_info = json.loads(out) extract_path_n = normpath(extract_path) for var in ('conda_prefix', 'sys.prefix', 'default_prefix', 'root_prefix'): assert normpath(conda_info[var]) == extract_path_n assert extract_path_n in list(map(normpath, conda_info['envs'])) # Check the conda-meta directory has been anonymized for path in glob(os.path.join(extract_path, 'conda-meta', '*.json')): with open(path) as fil: data = json.load(fil) for field in ["extracted_package_dir", "package_tarball_full_path"]: if field in data: assert data[field] == "" if "link" in data and "source" in data["link"]: assert data["link"]["source"] == ""