def test_format_specifier(): ireq = Requirement.from_line('foo').as_ireq() assert utils.format_specifier(ireq) == '<any>' ireq = Requirement.from_line('foo==1.2').as_ireq() assert utils.format_specifier(ireq) == '==1.2' ireq = Requirement.from_line('foo>1.2,~=1.1,<1.5').as_ireq() assert utils.format_specifier(ireq) == '~=1.1,>1.2,<1.5' ireq = Requirement.from_line('foo~=1.1,<1.5,>1.2').as_ireq() assert utils.format_specifier(ireq) == '~=1.1,>1.2,<1.5'
def test_format_specifier(): ireq = Requirement.from_line("foo").as_ireq() assert utils.format_specifier(ireq) == "<any>" ireq = Requirement.from_line("foo==1.2").as_ireq() assert utils.format_specifier(ireq) == "==1.2" ireq = Requirement.from_line("foo>1.2,~=1.1,<1.5").as_ireq() assert utils.format_specifier(ireq) == "~=1.1,>1.2,<1.5" ireq = Requirement.from_line("foo~=1.1,<1.5,>1.2").as_ireq() assert utils.format_specifier(ireq) == "~=1.1,>1.2,<1.5"
def test_local_req(test_artifact): r = Requirement.from_line(test_artifact.as_posix()) assert r.name == "environ-config" setup_dict = r.req.setup_info.as_dict() assert sorted(list(setup_dict.get("requires").keys())) == [ "attrs", ]
def test_stdout_is_suppressed(capsys, tmpdir): r = Requirement.from_line( "git+https://github.com/benjaminp/six.git@master#egg=six") r.req.get_vcs_repo(src_dir=tmpdir.strpath) out, err = capsys.readouterr() assert out.strip() == "", out assert err.strip() == "", err
def test_remote_req(url_line, name, requires): r = Requirement.from_line(url_line) assert r.name == name setup_dict = r.req.setup_info.as_dict() if "typing" in requires and not sys.version_info < (3, 5): requires.remove("typing") assert sorted(list(setup_dict.get("requires").keys())) == sorted(requires)
def test_convert_non_installable_dir_fail(pathlib_tmpdir): """Convert a non-installable directory link should fail without deleting the directory.""" dep = "-e file://{}".format(pathlib_tmpdir.as_posix()) with pytest.raises(RequirementError): req = Requirement.from_line(dep) assert pathlib_tmpdir.exists()
def test_no_duplicate_egg_info(): """When the package has 'src' directory, do not write egg-info in base dir.""" base_dir = os.path.abspath(os.getcwd()) r = Requirement.from_line("-e {}".format(base_dir)) egg_info_name = "{}.egg-info".format(r.name.replace("-", "_")) assert os.path.isdir(os.path.join(base_dir, "src", egg_info_name)) assert not os.path.isdir(os.path.join(base_dir, egg_info_name))
def test_ast_parser_handles_repeated_assignments(setup_py_dir): target = (setup_py_dir.joinpath( "package_with_repeated_assignments").absolute().as_posix()) r = Requirement.from_line(target) setup_dict = r.req.setup_info.as_dict() assert setup_dict["name"] == "test-package-with-repeated-assignments" assert sorted(setup_dict["requires"]) == ["six"]
def test_no_duplicate_egg_info(): """When the package has 'src' directory, do not write egg-info in base dir.""" base_dir = vistir.compat.Path(os.path.abspath(os.getcwd())).as_posix() r = Requirement.from_line("-e {}".format(base_dir)) egg_info_name = "{}.egg-info".format(r.name.replace("-", "_")) distinfo_name = "{0}.dist-info".format(r.name.replace("-", "_")) def find_metadata(path): metadata_names = [ os.path.join(path, name) for name in (egg_info_name, distinfo_name) ] if not os.path.isdir(path): return None pth = next(iter(pth for pth in metadata_names if os.path.isdir(pth)), None) if not pth: pth = next( iter(pth for pth in os.listdir(path) if any( pth.endswith(md_ending) for md_ending in [".egg-info", ".dist-info", ".whl"])), None, ) return pth assert not find_metadata(base_dir) assert not find_metadata(os.path.join(base_dir, "src", "reqlib-metadata")) assert r.req.setup_info and os.path.isdir(r.req.setup_info.egg_base) setup_info = r.req.setup_info setup_info.get_info() assert (find_metadata(setup_info.egg_base) or find_metadata(setup_info.extra_kwargs["build_dir"]) or setup_info.get_egg_metadata())
def test_convert_from_pip_fail_if_no_egg(): """Parsing should fail without `#egg=`. """ dep = "git+https://github.com/kennethreitz/requests.git" with pytest.raises(ValueError) as e: dep = Requirement.from_line(dep).as_pipfile() assert "pipenv requires an #egg fragment for vcs" in str(e)
def test_get_dependencies(): r = Requirement.from_line("requests==2.19.1") deps = r.get_dependencies() assert len(deps) > 0 deps_from_ireq = get_dependencies(r.as_ireq()) assert len(deps_from_ireq) > 0 assert sorted(set(deps_from_ireq)) == sorted(set(deps))
def test_parse_function_call_as_name(setup_py_dir, pathlib_tmpdir): package_dir = pathlib_tmpdir.joinpath( "package_with_function_call_as_name").as_posix() setup_dir = setup_py_dir.joinpath( "package_with_function_call_as_name").as_posix() shutil.copytree(setup_dir, package_dir) req = Requirement.from_line("-e {}".format(package_dir)) assert req.name == "package-with-function-call-as-name"
def test_get_ref(artifact_dir): req_uri = (artifact_dir.joinpath("git/shellingham").as_uri().replace( "file:/", "file:///")) git_uri = "-e git+{0}@1.2.1#egg=shellingham".format(req_uri) r = Requirement.from_line(git_uri) # "-e git+https://github.com/sarugaku/[email protected]#egg=shellingham" # ) assert r.commit_hash == "9abe7464dab5cc362fe08361619d3fb15f2e16ab"
def test_named_requirement_selected_over_non_installable_path( monkeypatch, pathlib_tmpdir): with monkeypatch.context() as m: m.chdir(pathlib_tmpdir.as_posix()) pathlib_tmpdir.joinpath("alembic").write_text(u"") r = Requirement.from_line("alembic") assert isinstance(r.req, NamedRequirement) assert r.as_line() == "alembic" assert r.line_instance.is_named is True
def test_format_requirement_editable(monkeypatch): with monkeypatch.context() as m: m.setattr(SetupInfo, "get_info", mock_run_requires) m.setattr(Requirement, "run_requires", mock_run_requires) m.setattr(pip_shims.shims, "unpack_url", mock_unpack) ireq = Requirement.from_line( "-e git+git://fake.org/x/y.git#egg=y").as_ireq() assert utils.format_requirement( ireq) == "-e git+git://fake.org/x/y.git#egg=y"
def test_convert_from_pip_git_uri_normalize(monkeypatch): """Pip does not parse this correctly, but we can (by converting to ssh://). """ with monkeypatch.context() as m: m.setattr(Requirement, "run_requires", mock_run_requires) m.setattr(SetupInfo, "get_info", mock_run_requires) m.setattr(pip_shims.shims, "unpack_url", mock_unpack) dep = "git+git@host:user/repo.git#egg=myname" dep = Requirement.from_line(dep).as_pipfile() assert dep == {"myname": {"git": "git@host:user/repo.git"}}
def get_abstract_deps(): r = Requirement.from_line("requests") deps = [InstallRequirement.from_line(d) for d in r.get_dependencies()] abstract_deps = r.get_abstract_dependencies() req_abstract_dep = AbstractDependency.from_requirement(r) assert r.abstract_dep == req_abstract_dep assert len(abstract_deps) > 0 deps_from_ireqs = get_abstract_dependencies(deps, parent=r) assert len(deps_from_ireqs) > 0 assert sorted(set(deps_from_ireqs)) == sorted(set(abstract_deps))
def test_get_local_ref(tmpdir): # TODO: add this as a git submodule and don't clone it from the internet all the time six_dir = tmpdir.join("six") import vistir c = vistir.misc.run( ["git", "clone", "https://github.com/benjaminp/six.git", six_dir.strpath], return_object=True, nospin=True, ) assert c.returncode == 0 r = Requirement.from_line("git+{0}#egg=six".format(Path(six_dir.strpath).as_uri())) assert r.commit_hash
def test_as_tuple(): ireq = Requirement.from_line("foo==1.1").as_ireq() name, version, extras = utils.as_tuple(ireq) assert name == "foo" assert version == "1.1" assert extras == () ireq = Requirement.from_line("foo[extra1,extra2]==1.1").as_ireq() name, version, extras = utils.as_tuple(ireq) assert name == "foo" assert version == "1.1" assert extras == ("extra1", "extra2") # Non-pinned versions aren't accepted should_be_rejected = [ "foo==1.*", "foo~=1.1,<1.5,>1.2", "foo", ] for spec in should_be_rejected: ireq = Requirement.from_line(spec).as_ireq() with pytest.raises(TypeError): utils.as_tuple(ireq)
def test_pep_508(): r = Requirement.from_line( "tablib@ https://codeload.github.com/jazzband/tablib/zip/v0.12.1") assert r.specifiers == "==0.12.1" assert ( r.req.link.url == "https://codeload.github.com/jazzband/tablib/zip/v0.12.1#egg=tablib") assert r.req.req.name == "tablib" assert r.req.req.url == "https://codeload.github.com/jazzband/tablib/zip/v0.12.1" requires, setup_requires, build_requires = r.req.dependencies assert all(dep in requires for dep in ["openpyxl", "odfpy", "xlrd"]) assert r.as_pipfile() == { "tablib": { "file": "https://codeload.github.com/jazzband/tablib/zip/v0.12.1" } }
def test_convert_from_pip(monkeypatch, expected, requirement): with monkeypatch.context() as m: m.setattr(Requirement, "run_requires", mock_run_requires) m.setattr(SetupInfo, "get_info", mock_run_requires) m.setattr(Line, "get_setup_info", mock_run_requires) m.setattr(pip_shims.shims, "unpack_url", mock_unpack) pkg_name = next(iter(expected.keys())) pkg_pipfile = expected[pkg_name] line = Line(requirement) if (hasattr(pkg_pipfile, "keys") and "editable" in pkg_pipfile and not pkg_pipfile["editable"]): del expected[pkg_name]["editable"] req = Requirement.from_line(requirement) assert req.as_pipfile() == expected assert line.line_with_prefix == req.as_line(include_hashes=False) assert hash(Line(line.line_with_prefix)) == hash( Line(line.line_with_prefix))
def test_remote_requirement_with_env_vars(): with temp_environ(): os.environ["USERNAME"] = "******" os.environ["PASSWORD"] = "******" r = Requirement.from_line( "https://${USERNAME}:${PASSWORD}@codeload.github.com/jazzband/tablib/zip/v0.12.1#egg=tablib" ) assert ( r.as_ireq().link.url_without_fragment == "https://*****:*****@codeload.github.com/jazzband/tablib/zip/v0.12.1") assert ( r.as_line() == "https://${USERNAME}:${PASSWORD}@codeload.github.com/jazzband/tablib/zip/v0.12.1#egg=tablib" ) assert ( r.as_pipfile()["tablib"]["file"] == "https://${USERNAME}:${PASSWORD}@codeload.github.com/jazzband/tablib/zip/v0.12.1" )
def test_format_requirement(): ireq = Requirement.from_line("test==1.2").as_ireq() assert utils.format_requirement(ireq) == "test==1.2"
def test_remote_req(url_line, name, requires): r = Requirement.from_line(url_line) assert r.name == name setup_dict = r.req.setup_info.as_dict() assert sorted(list(setup_dict.get("requires").keys())) == sorted(requires)
def test_one_way_editable_extras(): dep = "-e .[socks]" dep = Requirement.from_line(dep).as_pipfile() k = next(iter(dep.keys())) assert dep[k]["extras"] == ["socks"]
def test_read_requirements_with_list_comp(setup_py_dir): req = Requirement.from_line( f"-e {(setup_py_dir / 'package_with_setup_with_list_comp').as_posix()}" ) setup_info = req.req.setup_info.as_dict() assert sorted(setup_info["requires"]) == ["requests"]
def test_ast_parser_handles_exceptions(artifact_dir): path = artifact_dir.joinpath("git/pyinstaller") r = Requirement.from_line(path.as_posix()) setup_dict = r.req.setup_info.as_dict() assert "altgraph" in setup_dict["requires"]
def test_get_requirements(monkeypatch_if_needed): # Test eggs in URLs # m.setattr(pip_shims.shims, "unpack_url", mock_unpack) # m.setattr(SetupInfo, "get_info", mock_run_requires) url_with_egg = Requirement.from_line( "https://github.com/IndustriaTech/django-user-clipboard/archive/0.6.1.zip#egg=django-user-clipboard" ).requirement assert ( url_with_egg.url == "https://github.com/IndustriaTech/django-user-clipboard/archive/0.6.1.zip" ) assert url_with_egg.name == "django-user-clipboard" # Test URLs without eggs pointing at installable zipfiles url = Requirement.from_line( "https://codeload.github.com/kennethreitz/tablib/zip/v0.12.1" ).requirement assert url.url == "https://codeload.github.com/kennethreitz/tablib/zip/v0.12.1" wheel_line = "https://github.com/pypa/pipenv/raw/master/tests/test_artifacts/six-1.11.0+mkl-py2.py3-none-any.whl" wheel = Requirement.from_line(wheel_line) assert wheel.as_pipfile() == { "six": { "file": "https://github.com/pypa/pipenv/raw/master/tests/test_artifacts/six-1.11.0+mkl-py2.py3-none-any.whl" } } # Requirementslib inserts egg fragments as names when possible if we know the appropriate name # this allows for custom naming assert (Requirement.from_pipfile( wheel.name, list(wheel.as_pipfile().values())[0]).as_line().split("#")[0] == wheel_line) # Test VCS urls with refs and eggnames vcs_url = Requirement.from_line( "git+https://github.com/kennethreitz/tablib.git@master#egg=tablib" ).requirement assert (vcs_url.vcs == "git" and vcs_url.name == "tablib" and vcs_url.revision == "master") assert vcs_url.url == "git+https://github.com/kennethreitz/tablib.git" # Test normal package requirement normal = Requirement.from_line("tablib").requirement assert normal.name == "tablib" # Pinned package requirement spec = Requirement.from_line("tablib==0.12.1").requirement assert spec.name == "tablib" and spec.specs == [("==", "0.12.1")] # Test complex package with both extras and markers extras_markers = Requirement.from_line( "requests[security]; os_name=='posix'").requirement assert list(extras_markers.extras) == ["security"] assert extras_markers.name == "requests" assert str(extras_markers.marker) == 'os_name == "posix"' # Test VCS uris get generated correctly, retain git+git@ if supplied that way, and are named according to egg fragment git_reformat = Requirement.from_line( "-e [email protected]:pypa/pipenv.git#egg=pipenv").requirement assert git_reformat.url == "git+ssh://[email protected]/pypa/pipenv.git" assert git_reformat.name == "pipenv" assert git_reformat.editable # Previously VCS uris were being treated as local files, so make sure these are not handled that way assert not git_reformat.local_file # Test regression where VCS uris were being handled as paths rather than VCS entries assert git_reformat.vcs == "git" assert git_reformat.link.url == "git+ssh://[email protected]/pypa/pipenv.git#egg=pipenv" # Test VCS requirements being added with extras for constraint_line git_extras = Requirement.from_line( "-e git+https://github.com/requests/requests.git@master#egg=requests[security]" ) assert ( git_extras.as_line() == "-e git+https://github.com/requests/requests.git@master#egg=requests[security]" ) assert ( git_extras.constraint_line == "-e git+https://github.com/requests/requests.git@master#egg=requests[security]" )
def test_find_all_matches(): r = Requirement.from_line("six") matches = r.find_all_matches() assert len(matches) > 0
def test_get_deps_from_index(): r = Requirement.from_line("requests==2.19.1") deps = get_dependencies_from_index(r.as_ireq()) assert len(deps) > 0