or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-interface.mddata-models.mdenvironment-detection.mdindex.mdoutput-rendering.mdpackage-discovery.mdvalidation.mdwarning-system.md

data-models.mddocs/

0

# Data Models

1

2

Core classes for representing packages, requirements, and dependency relationships in a hierarchical dependency tree structure.

3

4

## Capabilities

5

6

### Package Base Class

7

8

Abstract base class for all package wrapper objects.

9

10

```python { .api }

11

class Package(ABC):

12

"""Abstract class for wrappers around objects that pip returns."""

13

14

UNKNOWN_LICENSE_STR = "(Unknown license)"

15

16

def __init__(self, project_name: str) -> None: ...

17

18

def licenses(self) -> str:

19

"""

20

Get license information for the package.

21

22

Returns:

23

License string in format "(license1, license2)" or "(Unknown license)"

24

"""

25

26

@abstractmethod

27

def render_as_root(self, *, frozen: bool) -> str: ...

28

29

@abstractmethod

30

def render_as_branch(self, *, frozen: bool) -> str: ...

31

32

@abstractmethod

33

def as_dict(self) -> dict[str, str]: ...

34

35

def render(

36

self,

37

parent: DistPackage | ReqPackage | None = None,

38

*,

39

frozen: bool = False,

40

) -> str: ...

41

```

42

43

### DistPackage Class

44

45

Wrapper for installed distribution packages with full metadata access.

46

47

```python { .api }

48

class DistPackage(Package):

49

"""

50

Wrapper class for importlib.metadata.Distribution instances.

51

52

Parameters:

53

- obj: importlib.metadata.Distribution to wrap over

54

- req: optional ReqPackage object for reverse tree display

55

"""

56

57

def __init__(self, obj: Distribution, req: ReqPackage | None = None) -> None: ...

58

59

def requires(self) -> Iterator[Requirement]:

60

"""

61

Return an iterator of the distribution's required dependencies.

62

63

Yields:

64

Requirement objects for dependencies that apply to current environment

65

66

Raises:

67

InvalidRequirementError: If metadata contains invalid requirement strings

68

"""

69

70

@property

71

def version(self) -> str:

72

"""The installed version of the package."""

73

74

def unwrap(self) -> Distribution:

75

"""Exposes the internal importlib.metadata.Distribution object."""

76

77

def as_requirement(self) -> ReqPackage:

78

"""Return a ReqPackage representation of this DistPackage."""

79

80

def as_parent_of(self, req: ReqPackage | None) -> DistPackage:

81

"""

82

Return a DistPackage instance associated to a requirement.

83

84

This association is necessary for reversing the PackageDAG.

85

"""

86

87

def as_dict(self) -> dict[str, str]:

88

"""

89

Returns:

90

Dictionary with keys: key, package_name, installed_version

91

"""

92

```

93

94

### ReqPackage Class

95

96

Wrapper for requirement packages with version constraint information.

97

98

```python { .api }

99

class ReqPackage(Package):

100

"""

101

Wrapper class for Requirement instance.

102

103

Parameters:

104

- obj: The Requirement instance to wrap over

105

- dist: optional importlib.metadata.Distribution instance for this requirement

106

"""

107

108

UNKNOWN_VERSION = "?"

109

110

def __init__(self, obj: Requirement, dist: DistPackage | None = None) -> None: ...

111

112

@property

113

def version_spec(self) -> str | None:

114

"""

115

Version specification string from requirement.

116

117

Returns:

118

Comma-joined version specifiers (e.g., ">=1.0,<2.0") or None

119

"""

120

121

@property

122

def installed_version(self) -> str:

123

"""

124

Currently installed version of the package.

125

126

Returns:

127

Version string or "?" if unknown/missing

128

"""

129

130

def is_conflicting(self) -> bool:

131

"""

132

Check if installed version conflicts with required version.

133

134

Returns:

135

True if installed version doesn't satisfy requirement or is missing

136

"""

137

138

@property

139

def is_missing(self) -> bool:

140

"""Check if package is missing (installed_version == "?")."""

141

142

def as_dict(self) -> dict[str, str]:

143

"""

144

Returns:

145

Dictionary with keys: key, package_name, installed_version, required_version

146

"""

147

```

148

149

### PackageDAG Class

150

151

Directed acyclic graph representing package dependencies using a mapping structure.

152

153

```python { .api }

154

class PackageDAG(Mapping[DistPackage, list[ReqPackage]]):

155

"""

156

Representation of Package dependencies as directed acyclic graph.

157

158

The internal structure maps each package to its list of requirements:

159

{package_a: [req_b, req_c],

160

package_b: [req_d],

161

package_c: [req_d, req_e],

162

package_d: [req_e],

163

package_e: []}

164

"""

165

166

@classmethod

167

def from_pkgs(cls, pkgs: list[Distribution]) -> PackageDAG:

168

"""

169

Create PackageDAG from list of Distribution objects.

170

171

Parameters:

172

- pkgs: List of importlib.metadata.Distribution objects

173

174

Returns:

175

PackageDAG instance with dependency relationships mapped

176

"""

177

178

def __init__(self, m: dict[DistPackage, list[ReqPackage]]) -> None: ...

179

180

def filter_nodes(

181

self,

182

include: list[str] | None,

183

exclude: set[str] | None,

184

exclude_deps: bool = False

185

):

186

"""

187

Filter the dependency tree to include/exclude specific packages.

188

189

Parameters:

190

- include: List of package patterns to include (supports wildcards)

191

- exclude: Set of package patterns to exclude (supports wildcards)

192

- exclude_deps: Whether to also exclude dependencies of excluded packages

193

194

Returns:

195

Filtered PackageDAG

196

197

Raises:

198

IncludeExcludeOverlapError: If include and exclude sets overlap

199

IncludePatternNotFoundError: If include patterns not found

200

"""

201

202

def reverse(self) -> ReversedPackageDAG:

203

"""

204

Create reversed view showing which packages depend on each package.

205

206

Returns:

207

ReversedPackageDAG with inverted dependency relationships

208

"""

209

210

def get_node_as_parent(self, key: str) -> DistPackage | None:

211

"""Get a package node by its canonical key."""

212

213

# Standard Mapping interface methods

214

def __getitem__(self, key: DistPackage) -> list[ReqPackage]: ...

215

def __iter__(self) -> Iterator[DistPackage]: ...

216

def __len__(self) -> int: ...

217

```

218

219

### ReversedPackageDAG Class

220

221

Inverted view of the dependency graph showing reverse dependencies.

222

223

```python { .api }

224

class ReversedPackageDAG(Mapping[ReqPackage, list[DistPackage]]):

225

"""

226

Reversed representation where each requirement maps to packages that depend on it.

227

"""

228

```

229

230

## Usage Examples

231

232

### Creating and Working with PackageDAG

233

234

```python

235

from pipdeptree._discovery import get_installed_distributions

236

from pipdeptree._models import PackageDAG

237

238

# Get installed packages and create dependency tree

239

distributions = get_installed_distributions()

240

tree = PackageDAG.from_pkgs(distributions)

241

242

# Filter to show only specific packages

243

filtered_tree = tree.filter_nodes(

244

include=['django', 'requests*'],

245

exclude=None

246

)

247

248

# Create reverse dependency view

249

reverse_tree = tree.reverse()

250

251

# Iterate through dependencies

252

for package, requirements in tree.items():

253

print(f"{package.project_name}=={package.version}")

254

for req in requirements:

255

print(f" requires {req.project_name} {req.version_spec}")

256

```

257

258

### Working with Individual Packages

259

260

```python

261

from pipdeptree._models import DistPackage, ReqPackage

262

263

# Access package information

264

for package, requirements in tree.items():

265

# Get package metadata

266

print(f"Package: {package.project_name}")

267

print(f"Version: {package.version}")

268

print(f"License: {package.licenses()}")

269

270

# Check requirements

271

for req in requirements:

272

if req.is_conflicting():

273

print(f"CONFLICT: {req.project_name}")

274

print(f" Required: {req.version_spec}")

275

print(f" Installed: {req.installed_version}")

276

```

277

278

## Exceptions

279

280

```python { .api }

281

class InvalidRequirementError(ValueError):

282

"""

283

An invalid requirement string was found.

284

285

When raising an exception, this should provide just the problem requirement string.

286

"""

287

288

class IncludeExcludeOverlapError(Exception):

289

"""Include and exclude sets passed as input violate mutual exclusivity requirement."""

290

291

class IncludePatternNotFoundError(Exception):

292

"""Include patterns weren't found when filtering a PackageDAG."""

293

```

294

295

## Type Definitions

296

297

```python { .api }

298

# Common type aliases used in the models

299

from importlib.metadata import Distribution, Requirement

300

from collections.abc import Iterator, Mapping

301

from typing import TYPE_CHECKING

302

303

if TYPE_CHECKING:

304

from collections.abc import Iterator

305

from importlib.metadata import Distribution

306

```