or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-checker.mdcode-analysis.mderror-messages.mdindex.mdreport-generation.md

ast-checker.mddocs/

0

# AST Checker and Analysis Engine

1

2

Core checker functionality providing detailed AST analysis, scope management, and binding tracking. The Checker class is the heart of pyflakes, performing static analysis by parsing Python code into Abstract Syntax Trees and tracking variable usage across different scopes.

3

4

## Capabilities

5

6

### Main Checker Class

7

8

The primary analysis engine that processes AST nodes and manages scope hierarchies to detect various code issues.

9

10

```python { .api }

11

class Checker:

12

"""

13

Main AST checker for Python code analysis.

14

15

Attributes:

16

- nodeDepth: int, current AST traversal depth

17

- offset: tuple[int, int] | None, position offset for error reporting

18

- builtIns: set[str], built-in names to recognize

19

- deadScopes: list[Any], scopes that are no longer active

20

- messages: list[Any], collected analysis messages

21

- filename: str, name of file being analyzed

22

- withDoctest: bool, whether to analyze doctest blocks

23

- scopeStack: list[Scope], stack of active scopes

24

- exceptHandlers: list[Any], active exception handlers

25

- root: ast.AST, root AST node being analyzed

26

"""

27

28

def __init__(

29

self,

30

tree: ast.AST,

31

filename: str = ...,

32

builtins: Iterable[str] | None = ...,

33

withDoctest: bool = ...,

34

file_tokens: tuple[Any, ...] = ...,

35

) -> None:

36

"""

37

Initialize checker with AST tree and configuration.

38

39

Parameters:

40

- tree: ast.AST, parsed AST tree to analyze

41

- filename: str, filename for error reporting

42

- builtins: Iterable[str] | None, additional built-in names

43

- withDoctest: bool, analyze doctest blocks

44

- file_tokens: tuple[Any, ...], tokenized source for advanced analysis

45

"""

46

```

47

48

**Key Methods:**

49

50

```python { .api }

51

def report(self, messageClass: Callable[_P, Message], *args: _P.args, **kwargs: _P.kwargs) -> None: ...

52

def addBinding(self, node: ast.AST, value: Binding) -> None: ...

53

def handleChildren(self, tree: ast.AST, omit: _OmitType = ...) -> None: ...

54

def pushScope(self, scopeClass: type[Scope] = ...) -> None: ...

55

def popScope(self) -> None: ...

56

```

57

58

**Properties:**

59

60

```python { .api }

61

@property

62

def futuresAllowed(self) -> bool:

63

"""Whether __future__ imports are allowed at current position."""

64

65

@property

66

def annotationsFutureEnabled(self) -> bool:

67

"""Whether annotations __future__ import is active."""

68

69

@property

70

def scope(self) -> Scope:

71

"""Current active scope."""

72

```

73

74

### Scope and Binding Management

75

76

#### Binding Classes

77

78

Base classes for tracking name bindings and their usage throughout the code.

79

80

```python { .api }

81

class Binding:

82

"""

83

Base class for name bindings.

84

85

Attributes:

86

- name: str, the bound name

87

- source: ast.AST | None, AST node where binding occurs

88

- used: Literal[False] | tuple[Any, ast.AST], usage tracking

89

"""

90

91

def __init__(self, name: str, source: ast.AST | None) -> None: ...

92

def redefines(self, other: Binding) -> bool:

93

"""Check if this binding redefines another binding."""

94

95

class Definition(Binding):

96

"""Base class for name definitions."""

97

98

class Importation(Definition):

99

"""

100

Import statement binding.

101

102

Attributes:

103

- fullName: str, full module name

104

- redefined: list[Any], names redefined by this import

105

"""

106

107

def __init__(self, name: str, source: ast.AST | None, full_name: str | None = ...) -> None: ...

108

109

@property

110

def source_statement(self) -> str:

111

"""Source import statement text."""

112

```

113

114

#### Scope Classes

115

116

Different types of scopes for tracking variable visibility and lifetime.

117

118

```python { .api }

119

class Scope(dict[str, Binding]):

120

"""

121

Base scope class mapping names to bindings.

122

123

Attributes:

124

- importStarred: bool, whether scope has star imports

125

"""

126

127

class ModuleScope(Scope):

128

"""Module-level scope."""

129

130

class FunctionScope(Scope):

131

"""

132

Function scope with additional function-specific tracking.

133

134

Attributes:

135

- usesLocals: bool, whether function uses locals()

136

- globals: set[str], names declared global

137

- returnValue: Any, return value tracking

138

- isGenerator: bool, whether function is a generator

139

"""

140

141

def __init__(self) -> None: ...

142

def unusedAssignments(self) -> Iterator[tuple[str, Binding]]:

143

"""Iterate over unused assignments in this scope."""

144

145

class ClassScope(Scope):

146

"""Class scope."""

147

```

148

149

### Core Analysis Methods

150

151

Methods for managing the analysis process, scope handling, and message reporting.

152

153

```python { .api }

154

def report(self, messageClass: Callable[_P, Message], *args: _P.args, **kwargs: _P.kwargs) -> None:

155

"""

156

Report an analysis message.

157

158

Parameters:

159

- messageClass: Message class to instantiate

160

- args: Positional arguments for message

161

- kwargs: Keyword arguments for message

162

"""

163

164

def addBinding(self, node: ast.AST, value: Binding) -> None:

165

"""

166

Add a name binding to current scope.

167

168

Parameters:

169

- node: AST node where binding occurs

170

- value: Binding object representing the name

171

"""

172

173

def pushScope(self, scopeClass: type[Scope] = ...) -> None:

174

"""

175

Push new scope onto scope stack.

176

177

Parameters:

178

- scopeClass: Type of scope to create

179

"""

180

181

def popScope(self) -> None:

182

"""Pop current scope from scope stack."""

183

```

184

185

### Deferred Processing

186

187

Methods for handling analysis that must be delayed until after initial AST traversal.

188

189

```python { .api }

190

def deferFunction(self, callable: _AnyFunction) -> None:

191

"""

192

Defer function analysis until after initial pass.

193

194

Parameters:

195

- callable: Function to call during deferred processing

196

"""

197

198

def deferAssignment(self, callable: _AnyFunction) -> None:

199

"""

200

Defer assignment analysis for complex cases.

201

202

Parameters:

203

- callable: Function to call during deferred processing

204

"""

205

206

def runDeferred(self, deferred: _AnyFunction) -> None:

207

"""

208

Execute deferred analysis function.

209

210

Parameters:

211

- deferred: Previously deferred function to execute

212

"""

213

```

214

215

### Scope and Binding Management

216

217

#### Binding Classes

218

219

Base classes for tracking name bindings and their usage throughout the code.

220

221

```python { .api }

222

class Binding:

223

"""

224

Base class for name bindings.

225

226

Attributes:

227

- name: str, the bound name

228

- source: ast.AST | None, AST node where binding occurs

229

- used: Literal[False] | tuple[Any, ast.AST], usage tracking

230

"""

231

232

def __init__(self, name: str, source: ast.AST | None) -> None: ...

233

def redefines(self, other: Binding) -> bool:

234

"""Check if this binding redefines another binding."""

235

236

class Definition(Binding):

237

"""Base class for name definitions."""

238

239

class Builtin(Definition):

240

"""Built-in name binding."""

241

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

242

```

243

244

#### Import Bindings

245

246

Specialized binding classes for different types of import statements.

247

248

```python { .api }

249

class Importation(Definition):

250

"""

251

Import statement binding.

252

253

Attributes:

254

- fullName: str, full module name

255

- redefined: list[Any], names redefined by this import

256

"""

257

258

def __init__(self, name: str, source: ast.AST | None, full_name: str | None = ...) -> None: ...

259

260

@property

261

def source_statement(self) -> str:

262

"""Source import statement text."""

263

264

class ImportationFrom(Importation):

265

"""

266

From-import binding.

267

268

Attributes:

269

- module: str, source module name

270

- real_name: str, actual imported name

271

"""

272

273

def __init__(self, name: str, source: ast.AST, module: str, real_name: str | None = ...) -> None: ...

274

275

class StarImportation(Importation):

276

"""Star import binding (from module import *)."""

277

def __init__(self, name: str, source: ast.AST) -> None: ...

278

279

class FutureImportation(ImportationFrom):

280

"""

281

Future import binding.

282

283

Attributes:

284

- used: tuple[Any, ast.AST], always marked as used

285

"""

286

def __init__(self, name: str, source: ast.AST, scope) -> None: ...

287

```

288

289

#### Other Binding Types

290

291

```python { .api }

292

class Argument(Binding):

293

"""Function argument binding."""

294

295

class Assignment(Binding):

296

"""Assignment binding."""

297

298

class Annotation(Binding):

299

"""Type annotation binding."""

300

def redefines(self, other: Binding) -> Literal[False]:

301

"""Annotations never redefine other bindings."""

302

303

class FunctionDefinition(Definition):

304

"""Function definition binding."""

305

306

class ClassDefinition(Definition):

307

"""Class definition binding."""

308

309

class ExportBinding(Binding):

310

"""

311

Export binding for __all__ declarations.

312

313

Attributes:

314

- names: list[str], exported names

315

"""

316

def __init__(self, name: str, source: ast.AST, scope: Scope) -> None: ...

317

```

318

319

### Scope Classes

320

321

Different types of scopes for tracking variable visibility and lifetime.

322

323

```python { .api }

324

class Scope(dict[str, Binding]):

325

"""

326

Base scope class mapping names to bindings.

327

328

Attributes:

329

- importStarred: bool, whether scope has star imports

330

"""

331

332

class ModuleScope(Scope):

333

"""Module-level scope."""

334

335

class FunctionScope(Scope):

336

"""

337

Function scope with additional function-specific tracking.

338

339

Attributes:

340

- usesLocals: bool, whether function uses locals()

341

- alwaysUsed: ClassVar[set[str]], names always considered used

342

- globals: set[str], names declared global

343

- returnValue: Any, return value tracking

344

- isGenerator: bool, whether function is a generator

345

"""

346

347

def __init__(self) -> None: ...

348

def unusedAssignments(self) -> Iterator[tuple[str, Binding]]:

349

"""Iterate over unused assignments in this scope."""

350

351

class ClassScope(Scope):

352

"""Class scope."""

353

354

class GeneratorScope(Scope):

355

"""Generator expression scope."""

356

357

class DoctestScope(ModuleScope):

358

"""Doctest block scope."""

359

```

360

361

### Utility Functions

362

363

Helper functions for AST analysis and format string parsing.

364

365

```python { .api }

366

def getAlternatives(n: ast.If | ast.Try) -> list[ast.AST]:

367

"""Get alternative execution branches from if/try statements."""

368

369

def counter(items: Iterable[_T]) -> dict[_T, int]:

370

"""Count occurrences of items in iterable."""

371

372

def iter_child_nodes(node: ast.AST, omit: _OmitType = ..., _fields_order: _FieldsOrder = ...) -> Iterator[ast.AST]:

373

"""Iterate over child AST nodes with optional field omission."""

374

375

def getNodeName(node: ast.AST) -> str:

376

"""Extract name from AST node."""

377

378

def is_typing_overload(value: Binding, scope_stack) -> bool:

379

"""Check if binding represents a typing.overload decorator."""

380

381

def parse_percent_format(s: str) -> tuple[_PercentFormat, ...]:

382

"""Parse percent-style format strings for validation."""

383

```

384

385

### Constants and Patterns

386

387

```python { .api }

388

# Python version compatibility

389

PY38_PLUS: bool

390

PYPY: bool

391

392

# AST node types

393

FOR_TYPES: tuple[type[ast.For], type[ast.AsyncFor]]

394

395

# Regular expression patterns

396

TYPE_COMMENT_RE: Pattern[str]

397

TYPE_IGNORE_RE: Pattern[str]

398

TYPE_FUNC_RE: Pattern[str]

399

MAPPING_KEY_RE: Pattern[str]

400

CONVERSION_FLAG_RE: Pattern[str]

401

WIDTH_RE: Pattern[str]

402

PRECISION_RE: Pattern[str]

403

LENGTH_RE: Pattern[str]

404

405

# String constants

406

ASCII_NON_ALNUM: str

407

VALID_CONVERSIONS: frozenset[str]

408

TYPING_MODULES: frozenset[Literal["typing", "typing_extensions"]]

409

```

410

411

**Usage Example:**

412

413

```python

414

import ast

415

from pyflakes.checker import Checker

416

from pyflakes.reporter import Reporter

417

import sys

418

419

# Parse Python code

420

code = """

421

import os

422

import sys

423

x = undefined_var

424

"""

425

426

tree = ast.parse(code)

427

reporter = Reporter(sys.stderr, sys.stderr)

428

429

# Create and run checker

430

checker = Checker(tree, "example.py")

431

print(f"Found {len(checker.messages)} issues")

432

433

# Access detailed analysis results

434

for message in checker.messages:

435

print(f"Line {message.lineno}: {message}")

436

```