def resolve(self, root_reqs, check_supported_wheels): # type: (List[InstallRequirement], bool) -> RequirementSet """Resolve what operations need to be done As a side-effect of this method, the packages (and their dependencies) are downloaded, unpacked and prepared for installation. This preparation is done by ``pip.operations.prepare``. Once PyPI has static dependency metadata available, it would be possible to move the preparation to become a step separated from dependency resolution. """ requirement_set = RequirementSet( check_supported_wheels=check_supported_wheels) for req in root_reqs: requirement_set.add_requirement(req) # Actually prepare the files, and collect any exceptions. Most hash # exceptions cannot be checked ahead of time, because # _populate_link() needs to be called before we can make decisions # based on link type. discovered_reqs = [] # type: List[InstallRequirement] hash_errors = HashErrors() for req in chain(root_reqs, discovered_reqs): try: discovered_reqs.extend(self._resolve_one(requirement_set, req)) except HashError as exc: exc.req = req hash_errors.append(exc) if hash_errors: raise hash_errors return requirement_set
def get_requirements(args: Iterable[str]) -> List[InstallRequirement]: requirement_set = RequirementSet() for req in args: req_to_add = install_req_from_line(req, comes_from=None) req_to_add.is_direct = True requirement_set.add_requirement(req_to_add) return cast(List[InstallRequirement], requirement_set.all_requirements)
def get_supported_wheels(wheel_directory): requirement_set = RequirementSet() for f in os.listdir(wheel_directory): wheel_filename = os.path.join(wheel_directory, f) requirement = install_req_from_line(wheel_filename) requirement.is_direct = True try: requirement_set.add_requirement(requirement) except InstallationError: # This deliberately filters out incompatible requirements. pass return [req.link.path for req in requirement_set.requirements.values()]
def _resolve_one( self, requirement_set: RequirementSet, req_to_install: InstallRequirement, ) -> List[InstallRequirement]: """Prepare a single requirements file. :return: A list of additional InstallRequirements to also install. """ # Tell user what we are doing for this requirement: # obtain (editable), skipping, processing (local url), collecting # (remote url or package name) if req_to_install.constraint or req_to_install.prepared: return [] req_to_install.prepared = True # Parse and return dependencies dist = self._get_dist_for(req_to_install) # This will raise UnsupportedPythonVersion if the given Python # version isn't compatible with the distribution's Requires-Python. _check_dist_requires_python( dist, version_info=self._py_version_info, ignore_requires_python=self.ignore_requires_python, ) more_reqs: List[InstallRequirement] = [] def add_req(subreq: Distribution, extras_requested: Iterable[str]) -> None: sub_install_req = self._make_install_req( str(subreq), req_to_install, ) parent_req_name = req_to_install.name to_scan_again, add_to_parent = requirement_set.add_requirement( sub_install_req, parent_req_name=parent_req_name, extras_requested=extras_requested, ) if parent_req_name and add_to_parent: self._discovered_dependencies[parent_req_name].append( add_to_parent) more_reqs.extend(to_scan_again) with indent_log(): # We add req_to_install before its dependencies, so that we # can refer to it when adding dependencies. if not requirement_set.has_requirement(req_to_install.name): # 'unnamed' requirements will get added here # 'unnamed' requirements can only come from being directly # provided by the user. assert req_to_install.user_supplied requirement_set.add_requirement(req_to_install, parent_req_name=None) if not self.ignore_dependencies: if req_to_install.extras: logger.debug( "Installing extra requirements: %r", ",".join(req_to_install.extras), ) missing_requested = sorted( set(req_to_install.extras) - set(dist.extras)) for missing in missing_requested: logger.warning("%s does not provide the extra '%s'", dist, missing) available_requested = sorted( set(dist.extras) & set(req_to_install.extras)) for subreq in dist.requires(available_requested): add_req(subreq, extras_requested=available_requested) return more_reqs
def get_requirements( self, args, # type: List[str] options, # type: Values finder, # type: PackageFinder session, # type: PipSession check_supported_wheels=True, # type: bool ): # type: (...) -> List[InstallRequirement] """ Parse command-line arguments into the corresponding requirements. """ requirement_set = RequirementSet( check_supported_wheels=check_supported_wheels) for filename in options.constraints: for parsed_req in parse_requirements( filename, constraint=True, finder=finder, options=options, session=session, ): req_to_add = install_req_from_parsed_requirement( parsed_req, isolated=options.isolated_mode, ) req_to_add.is_direct = True requirement_set.add_requirement(req_to_add) for req in args: req_to_add = install_req_from_line( req, None, isolated=options.isolated_mode, use_pep517=options.use_pep517, ) req_to_add.is_direct = True requirement_set.add_requirement(req_to_add) for req in options.editables: req_to_add = install_req_from_editable( req, isolated=options.isolated_mode, use_pep517=options.use_pep517, ) req_to_add.is_direct = True requirement_set.add_requirement(req_to_add) # NOTE: options.require_hashes may be set if --require-hashes is True for filename in options.requirements: for parsed_req in parse_requirements(filename, finder=finder, options=options, session=session): req_to_add = install_req_from_parsed_requirement( parsed_req, isolated=options.isolated_mode, use_pep517=options.use_pep517, ) req_to_add.is_direct = True requirement_set.add_requirement(req_to_add) # If any requirement has hash options, enable hash checking. requirements = requirement_set.all_requirements if any(req.has_hash_options for req in requirements): options.require_hashes = True if not (args or options.editables or options.requirements): opts = {"name": self.name} if options.find_links: raise CommandError( "You must give at least one requirement to {name} " '(maybe you meant "pip {name} {links}"?)'.format( **dict(opts, links=" ".join(options.find_links)))) else: raise CommandError( "You must give at least one requirement to {name} " '(see "pip help {name}")'.format(**opts)) return requirements
for filename in options.constraints: for parsed_req in parse_requirements( filename, constraint=True, finder=finder, options=options, session=session): req_to_add = install_req_from_parsed_requirement( parsed_req, isolated=options.isolated_mode, <<<<<<< HEAD user_supplied=False, ) requirements.append(req_to_add) ======= ) req_to_add.is_direct = True requirement_set.add_requirement(req_to_add) >>>>>>> b66a76afa15ab74019740676a52a071b85ed8f71 for req in args: req_to_add = install_req_from_line( req, None, isolated=options.isolated_mode, use_pep517=options.use_pep517, <<<<<<< HEAD user_supplied=True, ) requirements.append(req_to_add) ======= ) req_to_add.is_direct = True requirement_set.add_requirement(req_to_add) >>>>>>> b66a76afa15ab74019740676a52a071b85ed8f71