Registry / workflow / resolvelib

resolvelib

JSON →
library1.2.1pypypi✓ verified 27d ago

Resolvelib is a Python library that provides a generic dependency resolution algorithm. It allows you to resolve abstract dependencies into concrete ones by implementing a custom 'Provider' interface that defines how packages, requirements, and candidates interact. The current version is 1.2.1, and it maintains an active release cadence with several updates per year, indicating ongoing development and support.

pip install resolvelib
INSTALL
IMPORT
SIG · RESOLVELIB
R
resolvelib
workflowpythonv1.2.1
Install
1.6s avg
Import
17ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v1.2.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.018s · 17.9MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.6s · import 0.016s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Resolver
from resolvelib import Resolver
The Resolver class is the core component for initiating the dependency resolution process.
BaseReporter
from resolvelib.reporters import BaseReporter
BaseReporter provides a default implementation for reporting resolution progress. Custom reporters can inherit from this class.
Provider (interface)
import resolvelib.providers
While not directly imported as a class, the provider interface needs to be implemented by a custom class. Referencing `resolvelib.providers` reminds users where the interface specification is described.

This quickstart demonstrates the core usage of `resolvelib`. It involves defining custom `Package` and `Requirement` objects, then implementing a `Provider` class to teach the resolver how to find candidates, handle dependencies, and determine preferences. Finally, a `Resolver` instance is created and used to find a consistent set of packages based on the initial requirements.

import resolvelib from resolvelib.reporters import BaseReporter import os # Define simple data structures for our 'packages' and 'requirements' # In a real scenario, these would be richer objects (e.g., Package(name, version), Requirement(package_name, specifier)) class MyPackage: def __init__(self, name, version): self.name = name self.version = version def __repr__(self): return f'{self.name}=={self.version}' def __hash__(self): return hash((self.name, self.version)) def __eq__(self, other): return isinstance(other, MyPackage) and self.name == other.name and self.version == other.version class MyRequirement: def __init__(self, name, specifier): self.name = name self.specifier = specifier # e.g., '>=1.0', '<2.0' def __repr__(self): return f'{self.name}{self.specifier}' def __hash__(self): return hash((self.name, self.specifier)) def __eq__(self, other): return isinstance(other, MyRequirement) and self.name == other.name and self.specifier == other.specifier # Implement the Provider interface class MyProvider: def get_base_requirement(self, identifier): # For this simple example, we assume identifier is the package name # and we don't have a 'base' requirement beyond the initial ones. return None def identify(self, requirement_or_candidate): return requirement_or_candidate.name def get_preference(self, identifier, resolutions, candidates, information): # Prefer higher versions return len(candidates) + 1 # Dummy preference, real logic would sort candidates def get_dependencies(self, candidate): # Define dependencies for candidates if candidate.name == 'A' and candidate.version == '1.0': return [MyRequirement('B', '>=1.0')] if candidate.name == 'B' and candidate.version == '1.0': return [MyRequirement('C', '>=1.0')] return [] def get_candidates(self, requirement): # Return available candidates for a given requirement if requirement.name == 'A': yield MyPackage('A', '1.0') yield MyPackage('A', '2.0') elif requirement.name == 'B': yield MyPackage('B', '1.0') yield MyPackage('B', '1.1') elif requirement.name == 'C': yield MyPackage('C', '1.0') yield MyPackage('C', '1.2') else: return [] def is_satisfied_by(self, requirement, candidate): # In a real scenario, this would check if candidate.version satisfies requirement.specifier # For simplicity, we assume any candidate with the correct name satisfies a basic requirement return requirement.name == candidate.name # Create an instance of the provider and reporter provider = MyProvider() reporter = BaseReporter() # Create the resolver resolver = resolvelib.Resolver(provider, reporter) # Define the initial requirements requirements = [MyRequirement('A', '>=1.0')] # Kick off the resolution process try: result = resolver.resolve(requirements) print("Resolution successful:") for candidate in result.graph.iter_network_linear(): if isinstance(candidate, MyPackage): print(f" - {candidate}") except resolvelib.ResolutionImpossible as e: print(f"Resolution failed: {e}") # Example of getting an auth key, though not directly used by resolvelib api_key = os.environ.get('RESOLVELIB_API_KEY', 'your_default_or_mock_key') if api_key == 'your_default_or_mock_key': print("\nNote: For real-world use with external registries, an API key might be passed via Provider.") else: print(f"\nUsing API Key (first 5 chars): {api_key[:5]}...")
Debug
Known issues
breakingVersion 0.7.0 (April 2021) introduced breaking changes to the `Provider` interface. Users upgrading from versions prior to 0.7.0 will likely need to update their custom Provider implementations.
fix
Review the `resolvelib` documentation and changelog for 0.7.0 to identify the updated `Provider` methods and adjust your implementation accordingly.
affects: <0.7.0 to >=0.7.0
breakingVersion 1.0.0 (March 2023) changed the return type of `Resolver.resolve()`. It now returns a `namedtuple` with public attributes instead of an internal `Resolution` object. Code directly accessing internal attributes of the `Resolution` object will break.
fix
Update code to access the new public attributes of the returned `namedtuple` from `Resolver.resolve()`. Consult the changelog or examples for the correct attribute names.
affects: <1.0.0 to >=1.0.0
gotchaComplex dependency graphs can sometimes lead to `pip._vendor.resolvelib.resolvers.ResolutionTooDeep: 200000` errors or extremely long resolution times, especially when `resolvelib` is vendored within tools like `pip`. This can be due to intricate backtracking logic and optimization issues within the resolver.
fix
Simplify your dependency constraints, ensure your `pip` is up-to-date (which often includes `resolvelib` fixes), and, if providing a custom `Provider`, consider optimizing `get_preference` and dependency reporting to reduce the search space.
affects: All versions, more pronounced in highly complex scenarios or older `pip` versions.
gotcha`resolvelib` is a low-level building block. It requires users to implement a custom `Provider` interface to define how it interacts with their specific package ecosystem (e.g., how to find candidates, determine dependencies, and evaluate satisfaction). It's not an out-of-the-box solution for a specific package manager.
fix
Thoroughly understand the `Provider` interface documented in `resolvelib`'s source or examples. Your custom `Provider` must correctly implement methods like `identify`, `get_candidates`, `get_dependencies`, and `is_satisfied_by`.
affects: All versions
Errors
Common errors & fixes
resolvelib.resolvers.ResolutionImpossible: There are conflicting requirements:
The set of requirements provided to the resolver contains dependencies that cannot be simultaneously satisfied by any available candidate packages.
fix
Examine the detailed conflict message provided by the exception to identify the specific packages and versions causing the conflict, then adjust the initial requirements or available candidates accordingly.
TypeError: 'NoneType' object is not iterable
A custom `Provider` method (e.g., `get_dependencies`, `find_matches`) incorrectly returned `None` when an empty iterable (like an empty list `[]` or tuple `()`) was expected.
fix
Ensure all methods in the custom `Provider` that are expected to return collections (like dependencies or matches) return an empty list `[]` or another empty iterable, rather than `None`, when there are no items to return.
NotImplementedError: Method 'get_dependencies' must be implemented in a subclass.
The custom `Provider` class inheriting from `resolvelib.AbstractProvider` has not provided an implementation for one of its abstract methods.
fix
Implement all abstract methods (e.g., `get_base_requirement`, `identify_requirement`, `identify_candidate`, `get_preference`, `find_matches`, `is_satisfied_by`, `get_dependencies`) in your custom `Provider` subclass.
ModuleNotFoundError: No module named 'resolvelib'
The `resolvelib` library is not installed in the Python environment where the code is being executed, or the environment is not correctly activated.
fix
Install the package using pip: `pip install resolvelib`. If using a virtual environment, ensure it is activated before installation.
Upgrade
Version history
1.2.1latest on PyPI · released Oct 11, 2025
Audit
Dependencies

No dependency data recorded yet.

Agent activity
37 hits · last 30 days
node
34
OpenAI (training)
1
Resources
resolvelib — pip install resolvelib · libregistry