def test_update_lockfile_missing_minimal_python(workdir, monkeypatch): """It raises an error if the minimal python is not available.""" monkeypatch.setattr('sys.stdin', io.StringIO('pytest\npytest==6.1.2\nppytest\n')) env = appenv.AppEnv(os.path.join(workdir, 'ppytest')) env.init() requirements_file = os.path.join(workdir, "ppytest", "requirements.txt") with open(requirements_file, "r+") as f: lines = f.readlines() lines[0] = "# appenv-python-preference: 3.8,3.6,3.9\n" f.seek(0) f.writelines(lines) old_which = shutil.which def new_which(string): if string == "python3.6": return None else: return old_which(string) with unittest.mock.patch('shutil.which') as which: which.side_effect = new_which with pytest.raises(SystemExit) as e: env.update_lockfile() assert e.value.code == 66
def test_reset_removes_envdir_with_subdirs(tmpdir): env = appenv.AppEnv(os.path.join(tmpdir, 'ducker')) os.makedirs(env.appenv_dir) assert os.path.exists(env.appenv_dir) env.reset() assert not os.path.exists(env.appenv_dir) assert os.path.exists(str(tmpdir))
def test_update_lockfile_minimal_python(workdir, monkeypatch): """It uses the minimal python version even if it is not best python.""" monkeypatch.setattr('sys.stdin', io.StringIO('pytest\npytest==6.1.2\nppytest\n')) env = appenv.AppEnv(os.path.join(workdir, 'ppytest')) env.init() lockfile = os.path.join(workdir, "ppytest", "requirements.lock") requirements_file = os.path.join(workdir, "ppytest", "requirements.txt") with open(requirements_file, "r+") as f: lines = f.readlines() lines.insert(0, "# appenv-python-preference: 3.8,3.6,3.9\n") f.seek(0) f.writelines(lines) env.update_lockfile() assert os.path.exists(lockfile) with open(lockfile) as f: lockfile_content = f.read() assert "pytest==6.1.2" in lockfile_content assert "importlib-metadata==" in lockfile_content assert "typing-extensions==" in lockfile_content
def test_bootstrap_and_run_with_outdated_lockfile(workdir, monkeypatch): monkeypatch.setattr("sys.stdin", io.StringIO("ducker\nducker==2.0.1\n\n")) env = appenv.AppEnv(os.path.join(workdir, 'ducker')) env.init() env.update_lockfile() os.chdir(os.path.join(workdir, "ducker")) with open("ducker", "r") as f: # Ensure we're called with the Python-interpreter-under-test. script = "#!{}\n{}".format(sys.executable, f.read()) with open("ducker", "w") as f: f.write(script) output = subprocess.check_output('./appenv python -c "print(1)"', shell=True) assert output == b"1\n" with open("requirements.txt", 'w') as f: f.write('ducker==2.0.1') s = subprocess.Popen('./appenv python -c "print(1)"', shell=True, stdout=subprocess.PIPE) stdout, stderr = s.communicate() assert stdout == b"""\ requirements.txt seems out of date (hash mismatch). Regenerate using ./appenv update-lockfile """ # noqa subprocess.check_call('./appenv update-lockfile', shell=True) output = subprocess.check_output('./appenv python -c "print(1)"', shell=True) assert output == b"1\n"
def test_init_explicit_package_and_target(workdir, monkeypatch): monkeypatch.setattr("sys.stdin", io.StringIO("foo\nbar\nbaz\n")) env = appenv.AppEnv(os.path.join(workdir, 'ducker')) env.init() assert os.path.exists(os.path.join(workdir, "baz")) with open(os.path.join(workdir, "baz", "foo")) as f: ducker_appenv = f.read() with open(appenv.__file__) as f: original_appenv = f.read() with open(os.path.join(workdir, "baz", "requirements.txt")) as f: requirements = f.read() assert requirements == "bar\n" assert ducker_appenv == original_appenv
def test_bootstrap_and_run_python_with_lockfile(workdir, monkeypatch): monkeypatch.setattr("sys.stdin", io.StringIO("ducker\nducker==2.0.1\n\n")) env = appenv.AppEnv(os.path.join(workdir, 'ducker')) env.init() env.update_lockfile() os.chdir(os.path.join(workdir, "ducker")) with open("ducker", "r") as f: # Ensure we're called with the Python-interpreter-under-test. script = "#!{}\n{}".format(sys.executable, f.read()) with open("ducker", "w") as f: f.write(script) output = subprocess.check_output('./appenv python -c "print(1)"', shell=True) assert output == b"1\n"
def test_init_and_create_lockfile(workdir, monkeypatch): monkeypatch.setattr('sys.stdin', io.StringIO('ducker\nducker<2.0.2\n\n')) env = appenv.AppEnv(os.path.join(workdir, 'ducker')) env.init() lockfile = os.path.join(workdir, "ducker", "requirements.lock") assert not os.path.exists(lockfile) env.update_lockfile() assert os.path.exists(lockfile) with open(lockfile) as f: lockfile_content = f.read() assert (lockfile_content == """\ # appenv-requirements-hash: ffa75c00de4879b41008d0e9f6b9953cf7d65bb5f5b85d1d049e783b2486614d ducker==2.0.1 """) # noqa
def test_bootstrap_and_run_without_lockfile(workdir, monkeypatch): """It raises as error if no requirements.lock is present.""" monkeypatch.setattr("sys.stdin", io.StringIO("ducker\nducker==2.0.1\n\n")) env = appenv.AppEnv(os.path.join(workdir, 'ducker')) env.init() os.chdir(os.path.join(workdir, "ducker")) with open("ducker", "r") as f: # Ensure we're called with the Python-interpreter-under-test. script = "#!{}\n{}".format(sys.executable, f.read()) with open("ducker", "w") as f: f.write(script) with pytest.raises(subprocess.CalledProcessError) as err: subprocess.check_output(["./ducker", "--help"]) assert err.value.output == ( b"No requirements.lock found. Generate it using" b" ./appenv update-lockfile\n")
def test_init(workdir, monkeypatch): monkeypatch.setattr("sys.stdin", io.StringIO("ducker\n\n\n")) assert not os.path.exists(os.path.join(workdir, "ducker")) env = appenv.AppEnv(os.path.join(workdir, 'ducker')) env.init() assert os.readlink(os.path.join(workdir, "ducker", "ducker")) == 'appenv' with open(os.path.join(workdir, "ducker", "appenv")) as f: ducker_appenv = f.read() with open(appenv.__file__) as f: original_appenv = f.read() assert ducker_appenv == original_appenv with open(os.path.join(workdir, "ducker", "requirements.txt")) as f: requirements = f.read() assert requirements == "ducker\n" # calling it again doesn't break: monkeypatch.setattr("sys.stdin", io.StringIO("ducker\n\n\n")) env.init() assert os.readlink(os.path.join(workdir, "ducker", "ducker")) == 'appenv' with open(os.path.join(workdir, "ducker", "appenv")) as f: ducker_appenv = f.read() with open(appenv.__file__) as f: original_appenv = f.read() assert ducker_appenv == original_appenv with open(os.path.join(workdir, "ducker", "requirements.txt")) as f: requirements = f.read() assert requirements == "ducker\n"
def test_reset_nonexisting_envdir_silent(tmpdir): env = appenv.AppEnv(os.path.join(tmpdir, 'ducker')) assert not os.path.exists(env.appenv_dir) env.reset() assert not os.path.exists(env.appenv_dir) assert os.path.exists(str(tmpdir))