Command line utility to show dependency tree of packages.
—
Core classes for representing packages, requirements, and dependency relationships in a hierarchical dependency tree structure.
Abstract base class for all package wrapper objects.
class Package(ABC):
"""Abstract class for wrappers around objects that pip returns."""
UNKNOWN_LICENSE_STR = "(Unknown license)"
def __init__(self, project_name: str) -> None: ...
def licenses(self) -> str:
"""
Get license information for the package.
Returns:
License string in format "(license1, license2)" or "(Unknown license)"
"""
@abstractmethod
def render_as_root(self, *, frozen: bool) -> str: ...
@abstractmethod
def render_as_branch(self, *, frozen: bool) -> str: ...
@abstractmethod
def as_dict(self) -> dict[str, str]: ...
def render(
self,
parent: DistPackage | ReqPackage | None = None,
*,
frozen: bool = False,
) -> str: ...Wrapper for installed distribution packages with full metadata access.
class DistPackage(Package):
"""
Wrapper class for importlib.metadata.Distribution instances.
Parameters:
- obj: importlib.metadata.Distribution to wrap over
- req: optional ReqPackage object for reverse tree display
"""
def __init__(self, obj: Distribution, req: ReqPackage | None = None) -> None: ...
def requires(self) -> Iterator[Requirement]:
"""
Return an iterator of the distribution's required dependencies.
Yields:
Requirement objects for dependencies that apply to current environment
Raises:
InvalidRequirementError: If metadata contains invalid requirement strings
"""
@property
def version(self) -> str:
"""The installed version of the package."""
def unwrap(self) -> Distribution:
"""Exposes the internal importlib.metadata.Distribution object."""
def as_requirement(self) -> ReqPackage:
"""Return a ReqPackage representation of this DistPackage."""
def as_parent_of(self, req: ReqPackage | None) -> DistPackage:
"""
Return a DistPackage instance associated to a requirement.
This association is necessary for reversing the PackageDAG.
"""
def as_dict(self) -> dict[str, str]:
"""
Returns:
Dictionary with keys: key, package_name, installed_version
"""Wrapper for requirement packages with version constraint information.
class ReqPackage(Package):
"""
Wrapper class for Requirement instance.
Parameters:
- obj: The Requirement instance to wrap over
- dist: optional importlib.metadata.Distribution instance for this requirement
"""
UNKNOWN_VERSION = "?"
def __init__(self, obj: Requirement, dist: DistPackage | None = None) -> None: ...
@property
def version_spec(self) -> str | None:
"""
Version specification string from requirement.
Returns:
Comma-joined version specifiers (e.g., ">=1.0,<2.0") or None
"""
@property
def installed_version(self) -> str:
"""
Currently installed version of the package.
Returns:
Version string or "?" if unknown/missing
"""
def is_conflicting(self) -> bool:
"""
Check if installed version conflicts with required version.
Returns:
True if installed version doesn't satisfy requirement or is missing
"""
@property
def is_missing(self) -> bool:
"""Check if package is missing (installed_version == "?")."""
def as_dict(self) -> dict[str, str]:
"""
Returns:
Dictionary with keys: key, package_name, installed_version, required_version
"""Directed acyclic graph representing package dependencies using a mapping structure.
class PackageDAG(Mapping[DistPackage, list[ReqPackage]]):
"""
Representation of Package dependencies as directed acyclic graph.
The internal structure maps each package to its list of requirements:
{package_a: [req_b, req_c],
package_b: [req_d],
package_c: [req_d, req_e],
package_d: [req_e],
package_e: []}
"""
@classmethod
def from_pkgs(cls, pkgs: list[Distribution]) -> PackageDAG:
"""
Create PackageDAG from list of Distribution objects.
Parameters:
- pkgs: List of importlib.metadata.Distribution objects
Returns:
PackageDAG instance with dependency relationships mapped
"""
def __init__(self, m: dict[DistPackage, list[ReqPackage]]) -> None: ...
def filter_nodes(
self,
include: list[str] | None,
exclude: set[str] | None,
exclude_deps: bool = False
):
"""
Filter the dependency tree to include/exclude specific packages.
Parameters:
- include: List of package patterns to include (supports wildcards)
- exclude: Set of package patterns to exclude (supports wildcards)
- exclude_deps: Whether to also exclude dependencies of excluded packages
Returns:
Filtered PackageDAG
Raises:
IncludeExcludeOverlapError: If include and exclude sets overlap
IncludePatternNotFoundError: If include patterns not found
"""
def reverse(self) -> ReversedPackageDAG:
"""
Create reversed view showing which packages depend on each package.
Returns:
ReversedPackageDAG with inverted dependency relationships
"""
def get_node_as_parent(self, key: str) -> DistPackage | None:
"""Get a package node by its canonical key."""
# Standard Mapping interface methods
def __getitem__(self, key: DistPackage) -> list[ReqPackage]: ...
def __iter__(self) -> Iterator[DistPackage]: ...
def __len__(self) -> int: ...Inverted view of the dependency graph showing reverse dependencies.
class ReversedPackageDAG(Mapping[ReqPackage, list[DistPackage]]):
"""
Reversed representation where each requirement maps to packages that depend on it.
"""from pipdeptree._discovery import get_installed_distributions
from pipdeptree._models import PackageDAG
# Get installed packages and create dependency tree
distributions = get_installed_distributions()
tree = PackageDAG.from_pkgs(distributions)
# Filter to show only specific packages
filtered_tree = tree.filter_nodes(
include=['django', 'requests*'],
exclude=None
)
# Create reverse dependency view
reverse_tree = tree.reverse()
# Iterate through dependencies
for package, requirements in tree.items():
print(f"{package.project_name}=={package.version}")
for req in requirements:
print(f" requires {req.project_name} {req.version_spec}")from pipdeptree._models import DistPackage, ReqPackage
# Access package information
for package, requirements in tree.items():
# Get package metadata
print(f"Package: {package.project_name}")
print(f"Version: {package.version}")
print(f"License: {package.licenses()}")
# Check requirements
for req in requirements:
if req.is_conflicting():
print(f"CONFLICT: {req.project_name}")
print(f" Required: {req.version_spec}")
print(f" Installed: {req.installed_version}")class InvalidRequirementError(ValueError):
"""
An invalid requirement string was found.
When raising an exception, this should provide just the problem requirement string.
"""
class IncludeExcludeOverlapError(Exception):
"""Include and exclude sets passed as input violate mutual exclusivity requirement."""
class IncludePatternNotFoundError(Exception):
"""Include patterns weren't found when filtering a PackageDAG."""# Common type aliases used in the models
from importlib.metadata import Distribution, Requirement
from collections.abc import Iterator, Mapping
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Iterator
from importlib.metadata import DistributionInstall with Tessl CLI
npx tessl i tessl/pypi-pipdeptree