def get_dependencies(ireq, sources=None, parent=None): """Get all dependencies for a given install requirement. :param ireq: A single InstallRequirement :type ireq: :class:`~pip._internal.req.req_install.InstallRequirement` :param sources: Pipfile-formatted sources, defaults to None :type sources: list[dict], optional :param parent: The parent of this list of dependencies, defaults to None :type parent: :class:`~pip._internal.req.req_install.InstallRequirement` :return: A set of dependency lines for generating new InstallRequirements. :rtype: set(str) """ if not isinstance(ireq, InstallRequirement): name = getattr( ireq, "project_name", getattr(ireq, "project", ireq.name), ) version = getattr(ireq, "version", None) if not version: ireq = InstallRequirement.from_line("{0}".format(name)) else: ireq = InstallRequirement.from_line("{0}=={1}".format( name, version)) pip_options = get_pip_options(sources=sources) getters = [ get_dependencies_from_cache, get_dependencies_from_wheel_cache, get_dependencies_from_json, functools.partial(get_dependencies_from_index, pip_options=pip_options) ] for getter in getters: deps = getter(ireq) if deps is not None: return deps raise RuntimeError('failed to get dependencies for {}'.format(ireq))
def get_dependencies_from_cache(ireq): """Retrieves dependencies for the given install requirement from the dependency cache. :param ireq: A single InstallRequirement :type ireq: :class:`~pip._internal.req.req_install.InstallRequirement` :return: A set of dependency lines for generating new InstallRequirements. :rtype: set(str) or None """ if ireq.editable or not is_pinned_requirement(ireq): return if ireq not in DEPENDENCY_CACHE: return cached = set(DEPENDENCY_CACHE[ireq]) # Preserving sanity: Run through the cache and make sure every entry if # valid. If this fails, something is wrong with the cache. Drop it. try: broken = False for line in cached: dep_ireq = InstallRequirement.from_line(line) name = canonicalize_name(dep_ireq.name) if _marker_contains_extra(dep_ireq): broken = True # The "extra =" marker breaks everything. elif name == canonicalize_name(ireq.name): broken = True # A package cannot depend on itself. if broken: break except Exception: broken = True if broken: del DEPENDENCY_CACHE[ireq] return return cached
def test_link_and_ireq(): url = "git+https://github.com/requests/[email protected]#egg=requests" link = Link(url) ireq = InstallRequirement.from_editable(url) if install_req_from_editable: ireq2 = install_req_from_editable(url) assert ireq2.link == link assert ireq.link == link
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 gen(ireq): info = None info = session.get("https://pypi.org/pypi/{0}/{1}/json".format( ireq.req.name, version)).json()["info"] requires_dist = info.get("requires_dist", info.get("requires")) if not requires_dist: # The API can return None for this. return for requires in requires_dist: i = InstallRequirement.from_line(requires) # See above, we don't handle requirements with extras. if not _marker_contains_extra(i): yield format_requirement(i)
def test_build_wheel(): ireq = InstallRequirement.from_line( "https://files.pythonhosted.org/packages/6e/40/7434b2d9fe24107ada25ec90a1fc646e97f346130a2c51aa6a2b1aba28de/requests-2.12.1.tar.gz#egg=requests" ) with global_tempdir_manager(), ensure_resolution_dirs() as kwargs: ireq.ensure_has_source_dir(kwargs["src_dir"]) cmd = InstallCommand() options, _ = cmd.parser.parse_args([]) session = cmd._build_session(options) shim_unpack( download_dir=kwargs["download_dir"], ireq=ireq, location=ireq.source_dir, only_download=False, session=session, ) wheel = next(iter(build_wheel(req=ireq, **kwargs))) assert os.path.exists(wheel)
def test_get_packagefinder(): install_cmd = InstallCommand() finder = get_package_finder( install_cmd, python_versions=("27", "35", "36", "37", "38"), implementation="cp" ) ireq = InstallRequirement.from_line("requests>=2.18") if install_req_from_line: ireq2 = install_req_from_line("requests>=2.18") assert str(ireq) == str(ireq2) requests_candidates = finder.find_all_candidates(ireq.name) candidates = sorted( [ c for c in requests_candidates if c.version in ireq.specifier.filter( candidate.version for candidate in requests_candidates ) ], key=lambda c: c.version, ) best_version = candidates[-1] location = getattr(best_version, "location", getattr(best_version, "link", None)) assert "pythonhosted" in location.url
def test_resolve(): install_cmd = InstallCommand() ireq = InstallRequirement.from_line("requests>=2.18,<2.25.0") result = resolve(ireq, install_command=install_cmd) assert set(result.keys()) == {"requests", "chardet", "idna", "urllib3", "certifi"}
def test_wheelbuilder(tmpdir, PipCommand): output_dir = tmpdir.join("output") output_dir.mkdir() pip_command = PipCommand() pip_command.parser.add_option_group( make_option_group(index_group, pip_command.parser) ) pip_options, _ = pip_command.parser.parse_args([]) CACHE_DIR = tmpdir.mkdir("CACHE_DIR") pip_options.cache_dir = CACHE_DIR.strpath session = pip_command._build_session(pip_options) if parse_version(pip_version) > parse_version("19.1.1"): index_urls = [pip_options.index_url] + pip_options.extra_index_urls search_scope = SearchScope.create( find_links=pip_options.find_links, index_urls=index_urls ) selection_prefs = SelectionPreferences( True, allow_all_prereleases=False, format_control=None, prefer_binary=False, ignore_requires_python=False, ) target_python = TargetPython() candidate_prefs = CandidatePreferences( prefer_binary=selection_prefs.prefer_binary, allow_all_prereleases=selection_prefs.allow_all_prereleases, ) if parse_version(pip_version) > parse_version("19.2.3"): link_collector = LinkCollector(session=session, search_scope=search_scope) finder_args = {"link_collector": link_collector} else: finder_args = {"search_scope": search_scope, "session": session} finder_args.update( { "candidate_prefs": candidate_prefs, "target_python": target_python, "allow_yanked": selection_prefs.allow_yanked, "format_control": selection_prefs.format_control, "ignore_requires_python": selection_prefs.ignore_requires_python, } ) else: finder_args = { "find_links": pip_options.find_links, "index_urls": [pip_options.index_url] + pip_options.extra_index_urls, "trusted_hosts": pip_options.trusted_hosts, "session": session, "allow_all_prereleases": False, } # finder_args["allow_all_prereleases"] = False finder = PackageFinder(**finder_args) build_dir = tmpdir.mkdir("build_dir") source_dir = tmpdir.mkdir("source_dir") download_dir = tmpdir.mkdir("download_dir") wheel_download_dir = CACHE_DIR.mkdir("wheels") with wheel_cache(USER_CACHE_DIR, FormatControl(None, None)) as wheelcache: kwargs = { "build_dir": build_dir.strpath, "src_dir": source_dir.strpath, "download_dir": download_dir.strpath, "wheel_download_dir": wheel_download_dir.strpath, "finder": finder, "require_hashes": False, "use_user_site": False, "progress_bar": "off", "build_isolation": False, } ireq = InstallRequirement.from_editable( "git+https://github.com/urllib3/[email protected]#egg=urllib3" ) if parse_version(pip_version) <= parse_version("20.0.9999999"): ireq.populate_link(finder, False, False) ireq.ensure_has_source_dir(kwargs["src_dir"]) # Ensure the remote artifact is downloaded locally. For wheels, it is # enough to just download because we'll use them directly. For an sdist, # we need to unpack so we can build it. unpack_kwargs = { "session": session, "hashes": ireq.hashes(True), "link": ireq.link, "location": ireq.source_dir, "download_dir": kwargs["download_dir"], } if parse_version(pip_version) < parse_version("19.2.0"): unpack_kwargs["only_download"] = ireq.is_wheel if parse_version(pip_version) >= parse_version("10"): unpack_kwargs["progress_bar"] = "off" if not is_file_url(ireq.link): shim_unpack(**unpack_kwargs) output_file = None ireq.is_direct = True build_args = { "req": ireq, "output_dir": output_dir.strpath, "verify": False, "build_options": [], "global_options": [], "editable": False, } output_file = call_function_with_correct_args(build_one, **build_args) # XXX: skipping to here is functionally the same and should pass all tests # output_file = build_wheel(**build_wheel_kwargs) assert output_file, output_file
def test_abstract_dist(): ireq = InstallRequirement.from_editable( "git+https://github.com/requests/[email protected]#egg=requests" ) abs_dist = make_abstract_dist(ireq) assert abs_dist.__class__.__name__ == SourceDistribution.__name__
def test_resolution(tmpdir, PipCommand): pip_command = PipCommand() pip_command.parser.add_option_group( make_option_group(index_group, pip_command.parser) ) pip_options, _ = pip_command.parser.parse_args([]) CACHE_DIR = tmpdir.mkdir("CACHE_DIR") pip_options.cache_dir = CACHE_DIR.strpath session = pip_command._build_session(pip_options) assert session if parse_version(pip_version) > parse_version("19.1.1"): index_urls = [pip_options.index_url] + pip_options.extra_index_urls search_scope = SearchScope.create( find_links=pip_options.find_links, index_urls=index_urls ) selection_prefs = SelectionPreferences( True, allow_all_prereleases=False, format_control=None, prefer_binary=False, ignore_requires_python=False, ) target_python = TargetPython() candidate_prefs = CandidatePreferences( prefer_binary=selection_prefs.prefer_binary, allow_all_prereleases=selection_prefs.allow_all_prereleases, ) if parse_version(pip_version) > parse_version("19.2.3"): link_collector = LinkCollector(session=session, search_scope=search_scope) finder_args = {"link_collector": link_collector} else: finder_args = {"search_scope": search_scope, "session": session} finder_args.update( { "candidate_prefs": candidate_prefs, "target_python": target_python, "allow_yanked": selection_prefs.allow_yanked, "format_control": selection_prefs.format_control, "ignore_requires_python": selection_prefs.ignore_requires_python, } ) else: finder_args = { "find_links": pip_options.find_links, "index_urls": [pip_options.index_url], "trusted_hosts": pip_options.trusted_hosts, "session": session, "allow_all_prereleases": False, } # finder_args["allow_all_prereleases"] = False finder = PackageFinder(**finder_args) ireq = InstallRequirement.from_line("requests>=2.18") if install_req_from_line: ireq2 = install_req_from_line("requests>=2.18") assert str(ireq) == str(ireq2) requests_candidates = finder.find_all_candidates(ireq.name) candidates = sorted( [ c for c in requests_candidates if c.version in ireq.specifier.filter( candidate.version for candidate in requests_candidates ) ], key=lambda c: c.version, ) best_version = candidates[-1] location = getattr(best_version, "location", getattr(best_version, "link", None)) assert "pythonhosted" in location.url req_file = tmpdir.mkdir("req_dir").join("requirements.txt") req_file.write_text( textwrap.dedent( """ requests>=2.18 """ ), encoding="utf-8", ) build_dir = tmpdir.mkdir("build_dir") source_dir = tmpdir.mkdir("source_dir") download_dir = tmpdir.mkdir("download_dir") results = None with wheel_cache(USER_CACHE_DIR, FormatControl(None, None)) as wheelcache: preparer_kwargs = { "build_dir": build_dir.strpath, "src_dir": source_dir.strpath, "download_dir": download_dir.strpath, "progress_bar": "off", "build_isolation": False, "finder": finder, "session": session, "require_hashes": False, "use_user_site": False, } resolver_kwargs = { "finder": finder, "upgrade_strategy": "to-satisfy-only", "force_reinstall": False, "ignore_dependencies": False, "ignore_requires_python": False, "ignore_installed": True, "use_user_site": False, } if ( parse_version("19.3") <= parse_version(pip_version) <= parse_version("20.0.99999") ): make_install_req = partial( install_req_from_req_string, isolated=False, wheel_cache=wheelcache, # use_pep517=use_pep517, ) resolver_kwargs["make_install_req"] = make_install_req else: resolver_kwargs["wheel_cache"] = wheelcache if parse_version(pip_version) >= parse_version("20.1"): make_install_req = partial( install_req_from_req_string, isolated=False, use_pep517=True, ) resolver_kwargs["make_install_req"] = make_install_req else: resolver_kwargs["isolated"] = False resolver = None with make_preparer(**preparer_kwargs) as preparer: resolver_kwargs["preparer"] = preparer reqset = RequirementSet() ireq.is_direct = True reqset.add_requirement(ireq) resolver = get_resolver(**resolver_kwargs) resolver.require_hashes = False if parse_version(pip_version) > parse_version("20.0.9999999"): resolver._populate_link(ireq) results = resolver._resolve_one(reqset, ireq) try: reqset.cleanup_files() except AttributeError: pass results = set(results) result_names = [r.name for r in results] assert "urllib3" in result_names
def test_get_editable_from_index(): r = InstallRequirement.from_editable( "git+https://github.com/requests/requests.git#egg=requests[security]") deps = get_dependencies_from_index(r) assert len(deps) > 0
def ireq_from_editable(ireq): from pip_shims import InstallRequirement return InstallRequirement.from_editable(ireq)