Exemplo n.º 1
0
    def test_pyenv_shims(self):
        # type: () -> None
        py35, _, run_pyenv = ensure_python_distribution(PY35)
        py36 = ensure_python_interpreter(PY36)

        pyenv_root = str(run_pyenv(["root"]).strip())
        pyenv_shims = os.path.join(pyenv_root, "shims")

        def pyenv_global(*versions):
            run_pyenv(["global"] + list(versions))

        def assert_shim(shim_name, expected_binary_path):
            python = PythonInterpreter.from_binary(
                os.path.join(pyenv_shims, shim_name))
            assert expected_binary_path == python.binary

        with temporary_dir() as pex_root:
            with ENV.patch(PEX_ROOT=pex_root) as pex_env:
                with environment_as(PYENV_ROOT=pyenv_root, **pex_env):
                    pyenv_global(PY35, PY36)
                    assert_shim("python3", py35)

                    pyenv_global(PY36, PY35)
                    # The python3 shim is now pointing at python3.6 but the Pex cache has a valid
                    # entry for the old python3.5 association (the interpreter still exists.)
                    assert_shim("python3", py35)

                    # The shim pointer is now invalid since python3.5 was uninstalled and so should
                    # be re-read.
                    py35_deleted = "{}.uninstalled".format(py35)
                    os.rename(py35, py35_deleted)
                    try:
                        assert_shim("python3", py36)
                    finally:
                        os.rename(py35_deleted, py35)
Exemplo n.º 2
0
def test_pex_run_strip_env():
    with temporary_dir() as pex_root:
        pex_env = dict(PEX_MODULE='does_not_exist_in_sub_pex',
                       PEX_ROOT=pex_root)
        with environment_as(**pex_env), temporary_dir() as pex_chroot:
            pex_builder = PEXBuilder(path=pex_chroot)
            with tempfile.NamedTemporaryFile(mode="w") as fp:
                fp.write(
                    dedent("""
          import json
          import os

          print(json.dumps({k: v for k, v in os.environ.items() if k.startswith("PEX_")}))
        """))
                fp.flush()
                pex_builder.set_executable(fp.name, 'print_pex_env.py')
            pex_builder.freeze()

            stdout, returncode = run_simple_pex(pex_chroot)
            assert 0 == returncode
            assert {} == json.loads(stdout.decode('utf-8')), (
                'Expected the entrypoint environment to be stripped of PEX_ environment variables.'
            )
            assert pex_env == {
                k: v
                for k, v in os.environ.items() if k.startswith("PEX_")
            }, ('Expected the parent environment to be left un-stripped.')
Exemplo n.º 3
0
 def test_iter_candidates_empty_paths(self, test_interpreter1):
     # type: (str) -> None
     # Whereas `paths=None` should inspect $PATH, `paths=[]` means to search nothing.
     with environment_as(PATH=test_interpreter1):
         assert [] == list(PythonInterpreter.iter_candidates(paths=[]))
         assert [PythonInterpreter.from_binary(test_interpreter1)
                 ] == list(PythonInterpreter.iter_candidates(paths=None))
Exemplo n.º 4
0
def assert_pex_vars_hermetic():
    v = Variables()
    assert os.environ == v.copy()

    existing = os.environ.get('TEST')
    expected = (existing or '') + 'different'
    assert expected != existing

    with environment_as(TEST=expected):
        assert expected != v.copy().get('TEST')
Exemplo n.º 5
0
def assert_pex_vars_hermetic():
    # type: () -> None
    v = Variables()
    assert os.environ.copy() == v.copy()

    existing = os.environ.get("TEST")
    expected = (existing or "") + "different"
    assert expected != existing

    with environment_as(TEST=expected):
        assert expected != v.copy().get("TEST")
Exemplo n.º 6
0
def test_parse_requirements_stress(chroot):
    # type: (str) -> None
    with safe_open(os.path.join(chroot, "other-requirements.txt"), "w") as fp:
        fp.write(
            # This includes both example snippets taken directly from
            # https://pip.pypa.io/en/stable/reference/pip_install/#requirements-file-format
            # not already covered by
            # https://pip.pypa.io/en/stable/reference/pip_install/#example-requirements-file.
            dedent(
                """\
                SomeProject
                SomeProject == 1.3
                SomeProject >=1.2,<2.0
                SomeProject[foo, bar]
                SomeProject~=1.4.2
                
                SomeProject ==5.4 ; python_version < '2.7'
                SomeProject; sys_platform == 'win32'
                
                SomeProject @ https://example.com/somewhere/over/here
                SomeProject @ file:somewhere/over/here
                
                FooProject >= 1.2 --global-option="--no-user-cfg" \\
                      --install-option="--prefix='/usr/local'" \\
                      --install-option="--no-compile"
                
                git+https://git.example.com/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709#egg=MyProject
                git+ssh://git.example.com/MyProject#egg=MyProject
                git+file:///home/user/projects/MyProject#egg=MyProject&subdirectory=pkg_dir
                
                # N.B. This is not from the Pip docs unlike the examples above. We just want to 
                # chain in one more set of stress tests.
                -r extra/stress.txt
                """
            )
        )
    touch("somewhere/over/here/pyproject.toml")

    with safe_open(os.path.join(chroot, "extra", "stress.txt"), "w") as fp:
        fp.write(
            # These are tests of edge cases not included anywhere in the examples found in
            # https://pip.pypa.io/en/stable/reference/pip_install/#requirements-file-format.
            dedent(
                """\
                -c file:subdir/more-requirements.txt

                a/local/project[foo]; python_full_version == "2.7.8"
                ./another/local/project;python_version == "2.7.*"
                ./another/local/project
                ./
                # Local projects with basenames that are invalid Python project names (trailing _):
                tmp/tmpW8tdb_ 
                tmp/tmpW8tdb_[foo]
                tmp/tmpW8tdb_[foo];python_version == "3.9"

                hg+http://hg.example.com/MyProject@da39a3ee5e6b#egg=AnotherProject[extra,more];python_version=="3.9.*"&subdirectory=foo/bar

                ftp://a/${PROJECT_NAME}-1.0.tar.gz
                http://a/${PROJECT_NAME}-1.0.zip
                https://a/numpy-1.9.2-cp34-none-win32.whl

                Django@ git+https://github.com/django/django.git
                Django@git+https://github.com/django/django.git@stable/2.1.x
                Django@ git+https://github.com/django/django.git@fd209f62f1d83233cc634443cfac5ee4328d98b8
                Django @ file:projects/django-2.3.zip; python_version >= "3.10"
                """
            )
        )
    touch("extra/pyproject.toml")
    touch("extra/a/local/project/pyproject.toml")
    touch("extra/another/local/project/setup.py")
    touch("extra/tmp/tmpW8tdb_/setup.py")
    touch("extra/projects/django-2.3.zip")

    with safe_open(os.path.join(chroot, "subdir", "more-requirements.txt"), "w") as fp:
        fp.write(
            # This checks requirements (`ReqInfo`s) are wrapped up into `Constraints`.
            dedent(
                """\
                AnotherProject
                """
            )
        )

    req_iter = parse_requirements(
        Source.from_text(
            # N.B.: Taken verbatim from:
            #   https://pip.pypa.io/en/stable/reference/pip_install/#example-requirements-file
            dedent(
                """\
                #
                ####### example-requirements.txt #######
                #
                ###### Requirements without Version Specifiers ######
                nose
                nose-cov
                beautifulsoup4
                #
                ###### Requirements with Version Specifiers ######
                #   See https://www.python.org/dev/peps/pep-0440/#version-specifiers
                docopt == 0.6.1             # Version Matching. Must be version 0.6.1
                keyring >= 4.1.1            # Minimum version 4.1.1
                coverage != 3.5             # Version Exclusion. Anything except version 3.5
                Mopidy-Dirble ~= 1.1        # Compatible release. Same as >= 1.1, == 1.*
                #
                ###### Refer to other requirements files ######
                -r other-requirements.txt
                #
                #
                ###### A particular file ######
                ./downloads/numpy-1.9.2-cp34-none-win32.whl
                http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev1820+49a8884-cp34-none-win_amd64.whl
                #
                ###### Additional Requirements without Version Specifiers ######
                #   Same as 1st section, just here to show that you can put things in any order.
                rejected
                green
                #
                """
            ),
        )
    )

    # Ensure local non-distribution files matching distribution names are not erroneously probed
    # as distributions to find name and version metadata.
    touch("nose")

    touch("downloads/numpy-1.9.2-cp34-none-win32.whl")
    with environment_as(PROJECT_NAME="Project"):
        results = normalize_results(req_iter)

    assert [
        req(project_name="nose"),
        req(project_name="nose-cov"),
        req(project_name="beautifulsoup4"),
        req(project_name="docopt", specifier="==0.6.1"),
        req(project_name="keyring", specifier=">=4.1.1"),
        req(project_name="coverage", specifier="!=3.5"),
        req(project_name="Mopidy-Dirble", specifier="~=1.1"),
        req(project_name="SomeProject"),
        req(project_name="SomeProject", specifier="==1.3"),
        req(project_name="SomeProject", specifier=">=1.2,<2.0"),
        req(project_name="SomeProject", extras=["foo", "bar"]),
        req(project_name="SomeProject", specifier="~=1.4.2"),
        req(project_name="SomeProject", specifier="==5.4", marker="python_version < '2.7'"),
        req(project_name="SomeProject", marker="sys_platform == 'win32'"),
        url_req(project_name="SomeProject", url="https://example.com/somewhere/over/here"),
        local_req(path=os.path.realpath("somewhere/over/here")),
        req(project_name="FooProject", specifier=">=1.2"),
        url_req(
            project_name="MyProject",
            url="git+https://git.example.com/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709",
        ),
        url_req(project_name="MyProject", url="git+ssh://git.example.com/MyProject"),
        url_req(project_name="MyProject", url="git+file:/home/user/projects/MyProject"),
        Constraint(DUMMY_LINE, Requirement.parse("AnotherProject")),
        local_req(
            path=os.path.realpath("extra/a/local/project"),
            extras=["foo"],
            marker="python_full_version == '2.7.8'",
        ),
        local_req(
            path=os.path.realpath("extra/another/local/project"),
            marker="python_version == '2.7.*'",
        ),
        local_req(path=os.path.realpath("extra/another/local/project")),
        local_req(path=os.path.realpath("extra")),
        local_req(path=os.path.realpath("extra/tmp/tmpW8tdb_")),
        local_req(path=os.path.realpath("extra/tmp/tmpW8tdb_"), extras=["foo"]),
        local_req(
            path=os.path.realpath("extra/tmp/tmpW8tdb_"),
            extras=["foo"],
            marker="python_version == '3.9'",
        ),
        url_req(
            project_name="AnotherProject",
            url="hg+http://hg.example.com/MyProject@da39a3ee5e6b",
            extras=["more", "extra"],
            marker="python_version == '3.9.*'",
        ),
        url_req(project_name="Project", url="ftp://a/Project-1.0.tar.gz", specifier="==1.0"),
        url_req(project_name="Project", url="http://a/Project-1.0.zip", specifier="==1.0"),
        url_req(
            project_name="numpy",
            url="https://a/numpy-1.9.2-cp34-none-win32.whl",
            specifier="==1.9.2",
        ),
        url_req(project_name="Django", url="git+https://github.com/django/django.git"),
        url_req(project_name="Django", url="git+https://github.com/django/django.git@stable/2.1.x"),
        url_req(
            project_name="Django",
            url="git+https://github.com/django/django.git@fd209f62f1d83233cc634443cfac5ee4328d98b8",
        ),
        url_req(
            project_name="Django",
            url=os.path.realpath("extra/projects/django-2.3.zip"),
            specifier="==2.3",
            marker="python_version>='3.10'",
        ),
        url_req(
            project_name="numpy",
            url=os.path.realpath("./downloads/numpy-1.9.2-cp34-none-win32.whl"),
            specifier="==1.9.2",
        ),
        url_req(
            project_name="wxPython_Phoenix",
            url="http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev1820+49a8884-cp34-none-win_amd64.whl",
            specifier="==3.0.3.dev1820+49a8884",
        ),
        req(project_name="rejected"),
        req(project_name="green"),
    ] == results
Exemplo n.º 7
0
def test_pex_vars_hermetic():
    with environment_as(PEX_IGNORE_RCFILES='True'):
        assert_pex_vars_hermetic()
Exemplo n.º 8
0
def test_pex_vars_hermetic():
    # type: () -> None
    with environment_as(PEX_IGNORE_RCFILES="True"):
        assert_pex_vars_hermetic()
Exemplo n.º 9
0
 def pyenv_shell(*versions):
     # type: (*str) -> Iterator[None]
     with environment_as(PYENV_VERSION=":".join(versions)):
         yield
Exemplo n.º 10
0
    def test_pyenv_shims(self, tmpdir):
        # type: (Any) -> None
        py35, _, run_pyenv = ensure_python_distribution(PY35)
        py36 = ensure_python_interpreter(PY36)

        pyenv_root = str(run_pyenv(["root"]).strip())
        pyenv_shims = os.path.join(pyenv_root, "shims")

        def pyenv_global(*versions):
            # type: (*str) -> None
            run_pyenv(["global"] + list(versions))

        def pyenv_local(*versions):
            # type: (*str) -> None
            run_pyenv(["local"] + list(versions))

        @contextmanager
        def pyenv_shell(*versions):
            # type: (*str) -> Iterator[None]
            with environment_as(PYENV_VERSION=":".join(versions)):
                yield

        pex_root = os.path.join(str(tmpdir), "pex_root")
        cwd = safe_mkdir(os.path.join(str(tmpdir), "home", "jake", "project"))
        with ENV.patch(PEX_ROOT=pex_root) as pex_env, environment_as(
            PYENV_ROOT=pyenv_root, PEX_PYTHON_PATH=pyenv_shims, **pex_env
        ), pyenv_shell(), pushd(cwd):
            pyenv = Pyenv.find()
            assert pyenv is not None
            assert pyenv_root == pyenv.root

            def interpreter_for_shim(shim_name):
                # type: (str) -> PythonInterpreter
                binary = os.path.join(pyenv_shims, shim_name)
                return PythonInterpreter.from_binary(binary, pyenv=pyenv)

            def assert_shim(
                shim_name,  # type: str
                expected_binary_path,  # type: str
            ):
                # type: (...) -> None
                python = interpreter_for_shim(shim_name)
                assert expected_binary_path == python.binary

            def assert_shim_inactive(shim_name):
                # type: (str) -> None
                with pytest.raises(PythonInterpreter.IdentificationError):
                    interpreter_for_shim(shim_name)

            pyenv_global(PY35, PY36)
            assert_shim("python", py35)
            assert_shim("python3", py35)
            assert_shim("python3.5", py35)
            assert_shim("python3.6", py36)

            pyenv_global(PY36, PY35)
            assert_shim("python", py36)
            assert_shim("python3", py36)
            assert_shim("python3.6", py36)
            assert_shim("python3.5", py35)

            pyenv_local(PY35)
            assert_shim("python", py35)
            assert_shim("python3", py35)
            assert_shim("python3.5", py35)
            assert_shim_inactive("python3.6")

            with pyenv_shell(PY36):
                assert_shim("python", py36)
                assert_shim("python3", py36)
                assert_shim("python3.6", py36)
                assert_shim_inactive("python3.5")

            with pyenv_shell(PY35, PY36):
                assert_shim("python", py35)
                assert_shim("python3", py35)
                assert_shim("python3.5", py35)
                assert_shim("python3.6", py36)

            # The shim pointer is now invalid since python3.5 was uninstalled and so
            # should be re-read and found invalid.
            py35_version_dir = os.path.dirname(os.path.dirname(py35))
            py35_deleted = "{}.uninstalled".format(py35_version_dir)
            os.rename(py35_version_dir, py35_deleted)
            try:
                assert_shim_inactive("python")
                assert_shim_inactive("python3")
                assert_shim_inactive("python3.5")
            finally:
                os.rename(py35_deleted, py35_version_dir)

            assert_shim("python", py35)