{"id":"a68ca9a42b3edc94","repo":"pypa/pip","slug":"expected-str-requirement-or-distribution","errorCode":null,"errorMessage":"Expected str, Requirement, or Distribution","messagePattern":"Expected str, Requirement, or Distribution","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/pkg_resources/__init__.py","lineNumber":543,"sourceCode":"        return True\n\n    # XXX Linux and other platforms' special cases should go here\n    return False\n\n\n@overload\ndef get_distribution(dist: _DistributionT) -> _DistributionT: ...\n@overload\ndef get_distribution(dist: _PkgReqType) -> Distribution: ...\ndef get_distribution(dist: Distribution | _PkgReqType) -> Distribution:\n    \"\"\"Return a current distribution object for a Requirement or string\"\"\"\n    if isinstance(dist, str):\n        dist = Requirement.parse(dist)\n    if isinstance(dist, Requirement):\n        # Bad type narrowing, dist has to be a Requirement here, so get_provider has to return Distribution\n        dist = get_provider(dist)  # type: ignore[assignment]\n    if not isinstance(dist, Distribution):\n        raise TypeError(\"Expected str, Requirement, or Distribution\", dist)\n    return dist\n\n\ndef load_entry_point(dist: _EPDistType, group: str, name: str) -> _ResolvedEntryPoint:\n    \"\"\"Return `name` entry point of `group` for `dist` or raise ImportError\"\"\"\n    return get_distribution(dist).load_entry_point(group, name)\n\n\n@overload\ndef get_entry_map(\n    dist: _EPDistType, group: None = None\n) -> dict[str, dict[str, EntryPoint]]: ...\n@overload\ndef get_entry_map(dist: _EPDistType, group: str) -> dict[str, EntryPoint]: ...\ndef get_entry_map(dist: _EPDistType, group: str | None = None):\n    \"\"\"Return the entry point map for `group`, or the full entry map\"\"\"\n    return get_distribution(dist).get_entry_map(group)\n","sourceCodeStart":525,"sourceCodeEnd":561,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/pkg_resources/__init__.py#L525-L561","documentation":"Raised by the module-level get_distribution() when, after converting a string to a Requirement and resolving it via get_provider(), the result is not a Distribution instance. get_provider() returns an IResourceProvider for plain modules and a Distribution only for installed distributions; if you pass a module name that resolves to a resource provider but not a real distribution, the final isinstance check fails and TypeError is raised. The accepted inputs are str, Requirement, or an already-built Distribution.","triggerScenarios":"Calling pkg_resources.get_distribution('some.module') where 'some.module' is importable as code but is not backed by installed dist metadata (e.g. a namespace package, a module added to sys.path directly, a PEP 660 editable install without proper metadata, or a module whose loader type was only registered with a plain provider). Also when passing a Distribution subclass instance whose type is not recognized by get_provider's registry.","commonSituations":"Querying metadata for a project installed in development/editable mode without a proper .egg-info/.dist-info, a namespace package, or a module living in a flat directory on sys.path. Also after a partially-failed uninstall that left code but removed metadata.","solutions":["Pass a Distribution you already hold, or pass a project name string (e.g. 'requests') rather than an importable module dotted-path, so Requirement parsing + working_set lookup succeeds.","Reinstall the target project with proper metadata (pip install -e . or pip install <pkg>) so an .egg-info/.dist-info directory exists and get_provider returns a Distribution.","Catch TypeError around get_distribution and fall back to importlib.metadata.metadata() or importlib.metadata.distribution() for lookups."],"exampleFix":"// before\nimport pkg_resources\ndist = pkg_resources.get_distribution(\"my_namespace.sub\")  # TypeError if not a real dist\n\n// after\nfrom importlib import metadata\ndist = metadata.distribution(\"my-namespace-sub\")  # works for installed dist metadata","handlingStrategy":"type-guard","validationCode":"import pkg_resources\nfrom pkg_resources import Distribution, Requirement\n\ndef safe_get_distribution(dist):\n    if isinstance(dist, Distribution):\n        return dist\n    if isinstance(dist, str):\n        # pass project name, not a dotted module path\n        return pkg_resources.get_distribution(dist)\n    if isinstance(dist, Requirement):\n        return pkg_resources.get_distribution(dist)\n    raise TypeError('pass a str project name, Requirement, or Distribution')","typeGuard":"from pkg_resources import Distribution, Requirement\n\ndef is_distribution_input(x):\n    return isinstance(x, (str, Requirement, Distribution))","tryCatchPattern":"try:\n    dist = pkg_resources.get_distribution(target)\nexcept TypeError as e:\n    if 'Expected str, Requirement, or Distribution' in str(e):\n        # fall back to importlib.metadata for code-only modules\n        from importlib import metadata\n        dist = metadata.distribution(target)\n    else:\n        raise","preventionTips":["Pass project names (e.g. 'requests') rather than importable dotted module paths.","Ensure the target is installed with metadata (pip install) before querying.","Prefer importlib.metadata for new code; it has clearer not-found semantics (PackageNotFoundError)."],"tags":["pkg-resources","distribution","metadata","type-guard","get-distribution"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}