or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-tools.mdconfiguration.mdcore-analysis.mdindex.mdmodule-loading.mdpyi-parsing.mdpytd-system.md

module-loading.mddocs/

0

# Module Loading

1

2

Infrastructure for loading and resolving Python modules, PyTD files, and type information with support for custom import mappings and pickled type data. The module loading system enables PyType to analyze complex projects with intricate dependency structures.

3

4

## Capabilities

5

6

### Loader Creation

7

8

Create configured loaders for different analysis scenarios, providing the foundation for module resolution and type information loading.

9

10

```python { .api }

11

def create_loader(options, missing_modules=()):

12

"""

13

Create PyTD loader with specified configuration.

14

15

Parameters:

16

- options (Options): Configuration options including Python paths,

17

import mappings, and module resolution settings

18

- missing_modules (tuple): Modules to treat as missing/unavailable

19

20

Returns:

21

Loader: Configured loader instance for module resolution

22

23

Raises:

24

ImportError: If loader configuration fails

25

"""

26

```

27

28

Example usage:

29

30

```python

31

from pytype import config, load_pytd

32

33

# Create options with custom Python path

34

options = config.Options.create()

35

options.pythonpath = ["/my/project/src", "/my/project/lib"]

36

options.imports_map = "/my/project/.pytype/imports.txt"

37

38

# Create loader with known missing modules

39

loader = load_pytd.create_loader(

40

options,

41

missing_modules=("unavailable_dep", "optional_package")

42

)

43

```

44

45

### Loader Class

46

47

Main loader class providing comprehensive module resolution and type information loading capabilities.

48

49

```python { .api }

50

class Loader:

51

"""

52

Main loader for PyTD modules and type information.

53

54

Handles module resolution, import mapping, caching, and provides

55

the core infrastructure for PyType's analysis process.

56

"""

57

58

def __init__(self, python_version, python_exe, module_utils):

59

"""

60

Initialize loader with environment configuration.

61

62

Parameters:

63

- python_version (tuple): Target Python version

64

- python_exe (str): Path to Python executable

65

- module_utils: Module resolution utilities

66

"""

67

68

def load_file(self, module_name, filename):

69

"""

70

Load module from specific file path.

71

72

Parameters:

73

- module_name (str): Module name for loading

74

- filename (str): Path to module file

75

76

Returns:

77

Module: Loaded module with type information

78

"""

79

80

def import_name(self, module_name):

81

"""

82

Import module by name with full resolution.

83

84

Parameters:

85

- module_name (str): Fully qualified module name

86

87

Returns:

88

Module: Loaded module with resolved dependencies

89

90

Raises:

91

ImportError: If module cannot be resolved or loaded

92

"""

93

94

def lookup_builtin(self, name):

95

"""

96

Look up built-in type or function.

97

98

Parameters:

99

- name (str): Built-in name to resolve

100

101

Returns:

102

Type information for built-in, or None if not found

103

"""

104

105

def has_module(self, module_name):

106

"""

107

Check if module is available for loading.

108

109

Parameters:

110

- module_name (str): Module name to check

111

112

Returns:

113

bool: True if module can be loaded

114

"""

115

```

116

117

Example usage:

118

119

```python

120

from pytype import load_pytd, config

121

122

# Create and use loader

123

options = config.Options.create()

124

loader = load_pytd.create_loader(options)

125

126

# Load specific modules

127

try:

128

os_module = loader.import_name("os")

129

json_module = loader.import_name("json")

130

131

# Check module availability

132

if loader.has_module("requests"):

133

requests_module = loader.import_name("requests")

134

135

except ImportError as e:

136

print(f"Failed to load module: {e}")

137

```

138

139

### Module Representation

140

141

Classes for representing loaded modules and their metadata.

142

143

```python { .api }

144

class Module:

145

"""

146

Represents a parsed and loaded Python module.

147

148

Contains the PyTD AST representation along with metadata

149

about the module's source and dependencies.

150

"""

151

152

def __init__(self, ast, filename=None, module_name=None):

153

"""

154

Initialize module representation.

155

156

Parameters:

157

- ast (TypeDeclUnit): PyTD AST for the module

158

- filename (str, optional): Source file path

159

- module_name (str, optional): Fully qualified module name

160

"""

161

162

class ResolvedModule:

163

"""

164

Dataclass containing resolved module information.

165

166

Provides complete information about a successfully resolved

167

module including its location, type, and metadata.

168

"""

169

170

def __init__(self, module_name, filename, ast):

171

"""

172

Initialize resolved module information.

173

174

Parameters:

175

- module_name (str): Fully qualified module name

176

- filename (str): Path to module source

177

- ast (TypeDeclUnit): Parsed PyTD AST

178

"""

179

```

180

181

### Pickled PyI Loader

182

183

Specialized loader for working with pickled .pyi files, enabling faster loading of pre-processed type information.

184

185

```python { .api }

186

class PickledPyiLoader:

187

"""

188

Loader for pickled .pyi files.

189

190

Provides optimized loading of pre-processed type stub files,

191

significantly improving analysis performance for large projects.

192

"""

193

194

def __init__(self, python_version, module_utils):

195

"""

196

Initialize pickled .pyi loader.

197

198

Parameters:

199

- python_version (tuple): Target Python version

200

- module_utils: Module resolution utilities

201

"""

202

203

def load_from_pickle(self, filename):

204

"""

205

Load PyTD AST from pickled file.

206

207

Parameters:

208

- filename (str): Path to pickled .pyi file

209

210

Returns:

211

TypeDeclUnit: Loaded PyTD AST

212

213

Raises:

214

IOError: If file cannot be read or unpickled

215

"""

216

217

def save_to_pickle(self, ast, filename):

218

"""

219

Save PyTD AST to pickled file.

220

221

Parameters:

222

- ast (TypeDeclUnit): PyTD AST to pickle

223

- filename (str): Output pickle file path

224

"""

225

```

226

227

Example usage:

228

229

```python

230

from pytype import load_pytd, config

231

from pytype.pytd import pytd_utils

232

233

# Create pickled loader

234

options = config.Options.create()

235

loader = load_pytd.PickledPyiLoader(options.python_version, None)

236

237

# Save AST to pickle for faster loading

238

ast = # ... some PyTD AST

239

loader.save_to_pickle(ast, "mymodule.pkl")

240

241

# Load from pickle

242

cached_ast = loader.load_from_pickle("mymodule.pkl")

243

```

244

245

### Import Resolution

246

247

Advanced import resolution with support for custom mappings and complex project structures.

248

249

```python

250

from pytype import load_pytd, config

251

252

# Configure custom import mappings

253

options = config.Options.create()

254

options.imports_map = "imports.txt" # Custom import mappings

255

256

# imports.txt content:

257

# internal.utils myproject.internal.utils

258

# external_lib /path/to/external/stubs

259

260

loader = load_pytd.create_loader(options)

261

262

# Import resolution uses mappings automatically

263

try:

264

# This will resolve using the mapping

265

utils_module = loader.import_name("internal.utils")

266

267

# This will use the external stub path

268

external_module = loader.import_name("external_lib")

269

270

except ImportError as e:

271

print(f"Import resolution failed: {e}")

272

```

273

274

### Caching and Performance

275

276

The loader system includes comprehensive caching for improved performance:

277

278

```python

279

from pytype import load_pytd, config

280

281

options = config.Options.create()

282

loader = load_pytd.create_loader(options)

283

284

# First load - from source

285

module1 = loader.import_name("collections") # Loads from source

286

287

# Second load - from cache

288

module2 = loader.import_name("collections") # Uses cached version

289

290

assert module1 is module2 # Same object from cache

291

```

292

293

### Error Classes

294

295

```python { .api }

296

class BadDependencyError(Exception):

297

"""Error loading module dependencies."""

298

299

class ImportError(Exception):

300

"""Module import resolution failure."""

301

```

302

303

### Error Handling

304

305

Comprehensive error handling for module loading failures:

306

307

```python

308

from pytype import load_pytd, config

309

310

options = config.Options.create()

311

loader = load_pytd.create_loader(options)

312

313

try:

314

# Attempt to load potentially missing module

315

module = loader.import_name("nonexistent.module")

316

317

except ImportError as e:

318

print(f"Module not found: {e}")

319

320

# Check if module is available before loading

321

if loader.has_module("alternative.module"):

322

alt_module = loader.import_name("alternative.module")

323

else:

324

print("No alternative module available")

325

326

except Exception as e:

327

print(f"Unexpected loading error: {e}")

328

```

329

330

### Integration with Analysis

331

332

The module loading system integrates seamlessly with PyType's analysis workflow:

333

334

```python

335

from pytype import io, config, load_pytd

336

337

# Create configured loader

338

options = config.Options.create()

339

options.pythonpath = ["/my/project"]

340

loader = load_pytd.create_loader(options)

341

342

# Use loader in analysis

343

source_code = '''

344

import json

345

import myproject.utils

346

347

def process_data(data):

348

config = json.loads(data)

349

return myproject.utils.transform(config)

350

'''

351

352

# Analysis uses loader for import resolution

353

result = io.check_py(source_code, options=options, loader=loader)

354

```

355

356

### Custom Module Resolution

357

358

For complex project structures, implement custom module resolution:

359

360

```python

361

from pytype import load_pytd, config

362

363

class CustomLoader(load_pytd.Loader):

364

"""Custom loader with project-specific resolution logic."""

365

366

def import_name(self, module_name):

367

# Custom resolution logic

368

if module_name.startswith("myproject."):

369

# Handle internal modules specially

370

internal_path = self._resolve_internal_module(module_name)

371

return self.load_file(module_name, internal_path)

372

373

# Fall back to standard resolution

374

return super().import_name(module_name)

375

376

def _resolve_internal_module(self, module_name):

377

# Project-specific module resolution

378

parts = module_name.split(".")

379

return f"/project/src/{'/'.join(parts[1:])}.py"

380

381

# Use custom loader

382

options = config.Options.create()

383

loader = CustomLoader(options.python_version, options.python_exe, None)

384

```

385

386

### Bulk Module Loading

387

388

For analyzing projects with many dependencies:

389

390

```python

391

from pytype import load_pytd, config

392

393

def preload_common_modules(loader, modules):

394

"""Preload commonly used modules for better performance."""

395

396

loaded = {}

397

for module_name in modules:

398

try:

399

loaded[module_name] = loader.import_name(module_name)

400

print(f"Preloaded {module_name}")

401

except ImportError:

402

print(f"Skipped {module_name} (not available)")

403

404

return loaded

405

406

# Preload standard library modules

407

options = config.Options.create()

408

loader = load_pytd.create_loader(options)

409

410

common_modules = [

411

"os", "sys", "json", "typing", "collections",

412

"itertools", "functools", "datetime"

413

]

414

415

preloaded = preload_common_modules(loader, common_modules)

416

```