{"library":"resolvelib","title":"resolvelib","description":"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.","status":"active","version":"1.2.1","language":"en","source_language":"en","source_url":"https://github.com/sarugaku/resolvelib","tags":["dependency resolution","packaging","resolver","algorithms"],"install":[{"cmd":"pip install resolvelib","lang":"bash","label":"Install stable version"}],"dependencies":[],"imports":[{"note":"The Resolver class is the core component for initiating the dependency resolution process.","symbol":"Resolver","correct":"from resolvelib import Resolver"},{"note":"BaseReporter provides a default implementation for reporting resolution progress. Custom reporters can inherit from this class.","symbol":"BaseReporter","correct":"from resolvelib.reporters import BaseReporter"},{"note":"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.","symbol":"Provider (interface)","correct":"import resolvelib.providers"}],"quickstart":{"code":"import resolvelib\nfrom resolvelib.reporters import BaseReporter\nimport os\n\n# Define simple data structures for our 'packages' and 'requirements'\n# In a real scenario, these would be richer objects (e.g., Package(name, version), Requirement(package_name, specifier))\nclass MyPackage:\n    def __init__(self, name, version):\n        self.name = name\n        self.version = version\n\n    def __repr__(self):\n        return f'{self.name}=={self.version}'\n\n    def __hash__(self):\n        return hash((self.name, self.version))\n\n    def __eq__(self, other):\n        return isinstance(other, MyPackage) and self.name == other.name and self.version == other.version\n\nclass MyRequirement:\n    def __init__(self, name, specifier):\n        self.name = name\n        self.specifier = specifier # e.g., '>=1.0', '<2.0'\n\n    def __repr__(self):\n        return f'{self.name}{self.specifier}'\n\n    def __hash__(self):\n        return hash((self.name, self.specifier))\n\n    def __eq__(self, other):\n        return isinstance(other, MyRequirement) and self.name == other.name and self.specifier == other.specifier\n\n# Implement the Provider interface\nclass MyProvider:\n    def get_base_requirement(self, identifier):\n        # For this simple example, we assume identifier is the package name\n        # and we don't have a 'base' requirement beyond the initial ones.\n        return None\n\n    def identify(self, requirement_or_candidate):\n        return requirement_or_candidate.name\n\n    def get_preference(self, identifier, resolutions, candidates, information):\n        # Prefer higher versions\n        return len(candidates) + 1 # Dummy preference, real logic would sort candidates\n\n    def get_dependencies(self, candidate):\n        # Define dependencies for candidates\n        if candidate.name == 'A' and candidate.version == '1.0':\n            return [MyRequirement('B', '>=1.0')]\n        if candidate.name == 'B' and candidate.version == '1.0':\n            return [MyRequirement('C', '>=1.0')]\n        return []\n\n    def get_candidates(self, requirement):\n        # Return available candidates for a given requirement\n        if requirement.name == 'A':\n            yield MyPackage('A', '1.0')\n            yield MyPackage('A', '2.0')\n        elif requirement.name == 'B':\n            yield MyPackage('B', '1.0')\n            yield MyPackage('B', '1.1')\n        elif requirement.name == 'C':\n            yield MyPackage('C', '1.0')\n            yield MyPackage('C', '1.2')\n        else:\n            return []\n\n    def is_satisfied_by(self, requirement, candidate):\n        # In a real scenario, this would check if candidate.version satisfies requirement.specifier\n        # For simplicity, we assume any candidate with the correct name satisfies a basic requirement\n        return requirement.name == candidate.name\n\n# Create an instance of the provider and reporter\nprovider = MyProvider()\nreporter = BaseReporter()\n\n# Create the resolver\nresolver = resolvelib.Resolver(provider, reporter)\n\n# Define the initial requirements\nrequirements = [MyRequirement('A', '>=1.0')]\n\n# Kick off the resolution process\ntry:\n    result = resolver.resolve(requirements)\n    print(\"Resolution successful:\")\n    for candidate in result.graph.iter_network_linear():\n        if isinstance(candidate, MyPackage):\n            print(f\"  - {candidate}\")\nexcept resolvelib.ResolutionImpossible as e:\n    print(f\"Resolution failed: {e}\")\n\n# Example of getting an auth key, though not directly used by resolvelib\napi_key = os.environ.get('RESOLVELIB_API_KEY', 'your_default_or_mock_key')\nif api_key == 'your_default_or_mock_key':\n    print(\"\\nNote: For real-world use with external registries, an API key might be passed via Provider.\")\nelse:\n    print(f\"\\nUsing API Key (first 5 chars): {api_key[:5]}...\")\n","lang":"python","description":"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."},"warnings":[{"fix":"Review the `resolvelib` documentation and changelog for 0.7.0 to identify the updated `Provider` methods and adjust your implementation accordingly.","message":"Version 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.","severity":"breaking","affected_versions":"<0.7.0 to >=0.7.0"},{"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.","message":"Version 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.","severity":"breaking","affected_versions":"<1.0.0 to >=1.0.0"},{"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.","message":"Complex 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.","severity":"gotcha","affected_versions":"All versions, more pronounced in highly complex scenarios or older `pip` versions."},{"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`.","message":"`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.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-05T00:00:00.000Z","next_check":"2026-07-04T00:00:00.000Z"}