예제 #1
0
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
예제 #2
0
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))
예제 #3
0
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
예제 #4
0
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"
예제 #5
0
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
예제 #6
0
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"
예제 #7
0
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
예제 #8
0
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")
예제 #9
0
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"
예제 #10
0
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))