or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-functions.mddistribution-classes.mdentry-points.mdindex.mdpath-file-management.md

distribution-classes.mddocs/

0

# Distribution Classes

1

2

Distribution classes provide object-oriented access to package metadata, including abstract base classes and concrete implementations for different package formats. The Distribution system forms the core of importlib_metadata's architecture.

3

4

## Capabilities

5

6

### Abstract Distribution Base Class

7

8

The base Distribution class defines the interface for accessing package metadata and provides common functionality.

9

10

```python { .api }

11

class Distribution(metaclass=abc.ABCMeta):

12

"""

13

An abstract Python distribution package.

14

15

Custom providers may derive from this class and define the abstract methods

16

to provide a concrete implementation for their environment.

17

"""

18

19

@abc.abstractmethod

20

def read_text(self, filename) -> str | None:

21

"""

22

Attempt to load metadata file given by the name.

23

24

Parameters:

25

- filename: The name of the file in the distribution info

26

27

Returns:

28

str | None: The text if found, otherwise None

29

"""

30

31

@abc.abstractmethod

32

def locate_file(self, path: str | os.PathLike[str]) -> SimplePath:

33

"""

34

Given a path to a file in this distribution, return a SimplePath to it.

35

36

Parameters:

37

- path: Path to a file in this distribution

38

39

Returns:

40

SimplePath: Path object for the file

41

42

Raises:

43

NotImplementedError: If provider doesn't support file location

44

"""

45

46

@classmethod

47

def from_name(cls, name: str) -> Distribution:

48

"""

49

Return the Distribution for the given package name.

50

51

Parameters:

52

- name: The name of the distribution package to search for

53

54

Returns:

55

Distribution: The Distribution instance for the named package

56

57

Raises:

58

PackageNotFoundError: When the named package's distribution metadata cannot be found

59

ValueError: When an invalid value is supplied for name

60

"""

61

62

@classmethod

63

def discover(cls, *, context: DistributionFinder.Context | None = None, **kwargs) -> Iterable[Distribution]:

64

"""

65

Return an iterable of Distribution objects for all packages.

66

67

Pass a context or pass keyword arguments for constructing a context.

68

69

Parameters:

70

- context: A DistributionFinder.Context object (optional)

71

- **kwargs: Keyword arguments for constructing a context

72

73

Returns:

74

Iterable[Distribution]: Iterable of Distribution objects for packages matching the context

75

76

Raises:

77

ValueError: If both context and kwargs are provided

78

"""

79

80

@staticmethod

81

def at(path: str | os.PathLike[str]) -> Distribution:

82

"""

83

Return a Distribution for the indicated metadata path.

84

85

Parameters:

86

- path: A string or path-like object to the metadata directory

87

88

Returns:

89

Distribution: A concrete Distribution instance for the path

90

"""

91

92

@staticmethod

93

def _discover_resolvers():

94

"""

95

Search the meta_path for resolvers (MetadataPathFinders).

96

97

Returns:

98

Iterator: Iterator of find_distributions methods from MetaPathFinders

99

"""

100

101

@staticmethod

102

def _prefer_valid(dists: Iterable[Distribution]) -> Iterable[Distribution]:

103

"""

104

Prefer (move to the front) distributions that have metadata.

105

106

This optimization addresses cases where multiple distributions

107

may be found but some lack proper metadata.

108

109

Parameters:

110

- dists: Iterable of Distribution instances

111

112

Returns:

113

Iterable[Distribution]: Distributions with valid metadata prioritized

114

"""

115

```

116

117

### Distribution Properties

118

119

Access to distribution metadata through properties:

120

121

```python { .api }

122

class Distribution:

123

@property

124

def metadata(self) -> PackageMetadata | None:

125

"""

126

Return the parsed metadata for this Distribution.

127

128

The returned object will have keys that name the various bits of metadata

129

per the Core metadata specifications.

130

"""

131

132

@property

133

def name(self) -> str:

134

"""Return the 'Name' metadata for the distribution package."""

135

136

@property

137

def version(self) -> str:

138

"""Return the 'Version' metadata for the distribution package."""

139

140

@property

141

def entry_points(self) -> EntryPoints:

142

"""Return EntryPoints for this distribution."""

143

144

@property

145

def files(self) -> list[PackagePath] | None:

146

"""

147

Files in this distribution.

148

149

Returns:

150

list[PackagePath] | None: List of PackagePath for this distribution or None

151

if the metadata file that enumerates files is missing

152

"""

153

154

@property

155

def requires(self) -> list[str] | None:

156

"""Generated requirements specified for this Distribution."""

157

158

@property

159

def origin(self):

160

"""

161

Return the origin metadata from direct_url.json.

162

163

This provides information about how the package was installed,

164

including VCS information, local paths, or archive URLs.

165

166

Returns:

167

SimpleNamespace | None: Origin metadata object or None if not available

168

"""

169

170

@property

171

def _normalized_name(self):

172

"""

173

Return a normalized version of the name.

174

175

Used internally for consistent name comparisons and lookups.

176

177

Returns:

178

str: Normalized package name

179

"""

180

```

181

182

#### Usage Examples

183

184

```python

185

import importlib_metadata

186

187

# Get distribution and access properties

188

dist = importlib_metadata.Distribution.from_name('requests')

189

print(f"Name: {dist.name}")

190

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

191

192

# Access metadata

193

metadata = dist.metadata

194

if metadata:

195

print(f"Summary: {metadata['Summary']}")

196

print(f"Author: {metadata['Author']}")

197

198

# Get entry points for this distribution

199

eps = dist.entry_points

200

console_scripts = eps.select(group='console_scripts')

201

for ep in console_scripts:

202

print(f"Script: {ep.name}")

203

204

# Get files

205

files = dist.files

206

if files:

207

print(f"Distribution has {len(files)} files")

208

```

209

210

### PathDistribution Implementation

211

212

Concrete implementation for filesystem-based distributions:

213

214

```python { .api }

215

class PathDistribution(Distribution):

216

"""Concrete Distribution implementation for filesystem paths."""

217

218

def __init__(self, path: SimplePath) -> None:

219

"""

220

Construct a distribution.

221

222

Parameters:

223

- path: SimplePath indicating the metadata directory

224

"""

225

226

def read_text(self, filename: str | os.PathLike[str]) -> str | None:

227

"""Read text from a file in the distribution metadata."""

228

229

def locate_file(self, path: str | os.PathLike[str]) -> SimplePath:

230

"""Locate a file relative to the distribution."""

231

```

232

233

#### Usage Examples

234

235

```python

236

import importlib_metadata

237

from pathlib import Path

238

239

# Create distribution from path

240

metadata_path = Path('/path/to/package-1.0.dist-info')

241

dist = importlib_metadata.PathDistribution(metadata_path)

242

243

# Use like any other distribution

244

print(f"Package: {dist.name}")

245

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

246

```

247

248

### Distribution Discovery

249

250

The DistributionFinder system enables pluggable package discovery:

251

252

```python { .api }

253

class DistributionFinder(MetaPathFinder):

254

"""

255

A MetaPathFinder capable of discovering installed distributions.

256

257

Custom providers should implement this interface in order to supply metadata.

258

"""

259

260

class Context:

261

"""

262

Keyword arguments presented by the caller to distributions() or

263

Distribution.discover() to narrow the scope of a search for distributions.

264

"""

265

266

name = None # Specific name for which a distribution finder should match

267

268

def __init__(self, **kwargs):

269

"""

270

Initialize context with keyword arguments.

271

272

Parameters:

273

- **kwargs: Context parameters for filtering distributions

274

"""

275

276

@property

277

def path(self) -> list[str]:

278

"""

279

The sequence of directory paths that a distribution finder should search.

280

Typically refers to Python installed package paths such as "site-packages"

281

directories and defaults to sys.path.

282

283

Returns:

284

list[str]: List of directory paths to search

285

"""

286

287

@abc.abstractmethod

288

def find_distributions(self, context=Context()) -> Iterable[Distribution]:

289

"""

290

Find distributions.

291

292

Parameters:

293

- context: DistributionFinder.Context instance for filtering

294

295

Returns:

296

Iterable[Distribution]: Iterable of all Distribution instances capable of

297

loading the metadata for packages matching the context

298

"""

299

```

300

301

### MetadataPathFinder Implementation

302

303

Concrete implementation of DistributionFinder for filesystem-based package discovery:

304

305

```python { .api }

306

class MetadataPathFinder(DistributionFinder):

307

"""

308

A degenerate finder for distribution packages on the file system.

309

310

This finder supplies only a find_distributions() method for versions

311

of Python that do not have a PathFinder find_distributions().

312

"""

313

314

@classmethod

315

def find_distributions(cls, context=DistributionFinder.Context()) -> Iterable[PathDistribution]:

316

"""

317

Find distributions.

318

319

Return an iterable of all Distribution instances capable of

320

loading the metadata for packages matching context.name

321

(or all names if None indicated) along the paths in the list

322

of directories context.path.

323

324

Parameters:

325

- context: DistributionFinder.Context instance for filtering

326

327

Returns:

328

Iterable[PathDistribution]: PathDistribution instances for found packages

329

"""

330

331

@classmethod

332

def invalidate_caches(cls) -> None:

333

"""Invalidate internal caches used for distribution discovery."""

334

```

335

336

#### Usage Examples

337

338

```python

339

import importlib_metadata

340

341

# Discover all distributions

342

all_dists = list(importlib_metadata.Distribution.discover())

343

print(f"Found {len(all_dists)} distributions")

344

345

# Discover with context

346

context = importlib_metadata.DistributionFinder.Context(name='requests')

347

matching_dists = list(importlib_metadata.Distribution.discover(context=context))

348

349

# Discover with kwargs

350

specific_dists = list(importlib_metadata.Distribution.discover(name='requests'))

351

```

352

353

## Error Handling

354

355

Distribution classes raise specific exceptions for various error conditions:

356

357

```python

358

import importlib_metadata

359

360

try:

361

dist = importlib_metadata.Distribution.from_name('nonexistent')

362

except importlib_metadata.PackageNotFoundError:

363

print("Package not found")

364

365

try:

366

dist = importlib_metadata.Distribution.from_name('')

367

except ValueError:

368

print("Invalid distribution name")

369

```