def package(): p = ProjectPackage("root", "1.0") p.root_dir = Path.cwd() return p
def root(): return ProjectPackage("root", "1.2.3")
def solve_pypi( pip_specs: Dict[str, src_parser.Dependency], use_latest: List[str], pip_locked: Dict[str, src_parser.LockedDependency], conda_locked: Dict[str, src_parser.LockedDependency], python_version: str, platform: str, verbose: bool = False, ) -> Dict[str, src_parser.LockedDependency]: """ Solve pip dependencies for the given platform Parameters ---------- conda : Path to conda, mamba, or micromamba use_latest : Names of packages to update to the latest version compatible with pip_specs pip_specs : PEP440 package specifications pip_locked : Previous solution for the given platform (pip packages only) conda_locked : Current solution of conda-only specs for the given platform python_version : Version of Python in conda_locked platform : Target platform verbose : Print chatter from solver """ dummy_package = ProjectPackage("_dummy_package_", "0.0.0") dependencies = [get_dependency(spec) for spec in pip_specs.values()] for dep in dependencies: dummy_package.add_dependency(dep) pypi = PyPiRepository() pool = Pool(repositories=[pypi]) installed = Repository() locked = Repository() python_packages = dict() for dep in conda_locked.values(): if dep.name.startswith("__"): continue try: pypi_name = conda_name_to_pypi_name(dep.name).lower() except KeyError: continue # Prefer the Python package when its name collides with the Conda package # for the underlying library, e.g. python-xxhash (pypi: xxhash) over xxhash # (pypi: no equivalent) if pypi_name not in python_packages or pypi_name != dep.name: python_packages[pypi_name] = dep.version # treat conda packages as both locked and installed for name, version in python_packages.items(): for repo in (locked, installed): repo.add_package(Package(name=name, version=version)) # treat pip packages as locked only for spec in pip_locked.values(): locked.add_package(get_package(spec)) if verbose: io = ConsoleIO() io.set_verbosity(VERY_VERBOSE) else: io = NullIO() s = Solver( dummy_package, pool=pool, installed=installed, locked=locked, io=io, ) to_update = list({spec.name for spec in pip_locked.values() }.intersection(use_latest)) env = PlatformEnv(python_version, platform) # find platform-specific solution (e.g. dependencies conditioned on markers) with s.use_environment(env): result = s.solve(use_latest=to_update) chooser = Chooser(pool, env=env) # Extract distributions from Poetry package plan, ignoring uninstalls # (usually: conda package with no pypi equivalent) and skipped ops # (already installed) requirements: List[src_parser.LockedDependency] = [] for op in result: if not isinstance(op, Uninstall) and not op.skipped: # Take direct references verbatim source: Optional[src_parser.DependencySource] = None if op.package.source_type == "url": url, fragment = urldefrag(op.package.source_url) hash_type, hash = fragment.split("=") hash = src_parser.HashModel(**{hash_type: hash}) source = src_parser.DependencySource(type="url", url=op.package.source_url) # Choose the most specific distribution for the target else: link = chooser.choose_for(op.package) url = link.url_without_fragment hash = src_parser.HashModel(**{link.hash_name: link.hash}) requirements.append( src_parser.LockedDependency( name=op.package.name, version=str(op.package.version), manager="pip", source=source, platform=platform, dependencies={ dep.name: str(dep.constraint) for dep in op.package.requires }, url=url, hash=hash, )) # use PyPI names of conda packages to walking the dependency tree and propagate # categories from explicit to transitive dependencies planned = { **{dep.name: dep for dep in requirements}, # prefer conda packages so add them afterwards } for conda_name, dep in conda_locked.items(): try: pypi_name = conda_name_to_pypi_name(conda_name).lower() except KeyError: # no conda-name found, assuming conda packages do NOT intersect with the pip package continue planned[pypi_name] = dep src_parser._apply_categories(requested=pip_specs, planned=planned) return {dep.name: dep for dep in requirements}