or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# Executing

1

2

Get information about what a frame is currently doing, particularly the AST node being executed. This mini-library enables Python developers to determine which AST node is currently executing in a frame, obtain the source code of that node, and get the qualname of the current function. Designed for debugging tools, development utilities, and introspection libraries.

3

4

## Package Information

5

6

- **Package Name**: executing

7

- **Package Type**: pypi

8

- **Language**: Python

9

- **Installation**: `pip install executing`

10

11

## Core Imports

12

13

```python

14

import executing

15

```

16

17

For pytest compatibility checking:

18

19

```python

20

from executing import is_pytest_compatible

21

```

22

23

## Basic Usage

24

25

```python

26

import executing

27

import inspect

28

29

def example_function():

30

# Get the currently executing AST node

31

frame = inspect.currentframe()

32

node = executing.Source.executing(frame).node

33

34

if node:

35

# Get the source code of the executing node

36

source_text = executing.Source.executing(frame).text()

37

print(f"Currently executing: {source_text}")

38

39

# Get the qualified name of the current function

40

qualname = executing.Source.executing(frame).code_qualname()

41

print(f"Function qualname: {qualname}")

42

else:

43

print("Could not identify the executing node")

44

45

# Usage with traceback objects

46

try:

47

some_function()

48

except Exception:

49

import sys

50

tb = sys.exc_info()[2]

51

node = executing.Source.executing(tb).node

52

if node:

53

print(f"Exception occurred at: {executing.Source.executing(tb).text()}")

54

```

55

56

## Architecture

57

58

The executing library works by analyzing bytecode instructions and matching them to AST nodes through compilation tricks:

59

60

- **Source**: Manages source code files and their AST representations, caching instances by filename

61

- **Executing**: Represents information about what operation a frame is currently executing

62

- **Node Matching**: Uses bytecode analysis with sentinel transformations to identify which AST node corresponds to the current instruction

63

- **AST Enhancement**: Adds parent references to AST nodes for navigation and analysis

64

65

The library supports identifying Call, Attribute, Subscript, BinOp, UnaryOp, and Compare AST node types through clever bytecode inspection and AST modification techniques.

66

67

## Capabilities

68

69

### Frame Analysis

70

71

Get information about what a frame is currently executing, including the AST node being executed and associated metadata.

72

73

```python { .api }

74

class Source:

75

@classmethod

76

def executing(cls, frame_or_tb) -> "Executing":

77

"""

78

Returns an Executing object representing the operation

79

currently executing in the given frame or traceback object.

80

81

Parameters:

82

- frame_or_tb: types.FrameType or types.TracebackType

83

84

Returns:

85

Executing object with node, source, and metadata

86

"""

87

88

@classmethod

89

def for_frame(cls, frame, use_cache=True) -> "Source":

90

"""

91

Returns the Source object corresponding to the file the frame is executing in.

92

93

Parameters:

94

- frame: types.FrameType - the frame to analyze

95

- use_cache: bool - whether to use cached Source instances

96

97

Returns:

98

Source object for the frame's file

99

"""

100

101

@classmethod

102

def for_filename(cls, filename, module_globals=None, use_cache=True) -> "Source":

103

"""

104

Returns Source object for a specific filename.

105

106

Parameters:

107

- filename: str or Path - path to the source file

108

- module_globals: dict, optional - module globals for linecache

109

- use_cache: bool - whether to use cached instances

110

111

Returns:

112

Source object for the specified file

113

"""

114

```

115

116

### Source Code Analysis

117

118

Analyze source files and extract information about AST nodes, statements, and code structure.

119

120

```python { .api }

121

class Source:

122

def statements_at_line(self, lineno) -> Set[ast.stmt]:

123

"""

124

Returns the statement nodes overlapping the given line.

125

126

Parameters:

127

- lineno: int - line number to analyze

128

129

Returns:

130

Set of AST statement nodes at the specified line

131

"""

132

133

def asttokens(self) -> "ASTTokens":

134

"""

135

Returns an ASTTokens object for getting the source of specific AST nodes.

136

Requires asttokens library to be installed separately.

137

138

Returns:

139

ASTTokens object for source code analysis

140

"""

141

142

def asttext(self) -> "ASTText":

143

"""

144

Returns an ASTText object for getting the source of specific AST nodes.

145

Requires asttokens library to be installed separately.

146

147

Returns:

148

ASTText object for source code analysis

149

"""

150

151

def code_qualname(self, code) -> str:

152

"""

153

Imitates the __qualname__ attribute of functions for code objects.

154

155

Parameters:

156

- code: types.CodeType - code object to analyze

157

158

Returns:

159

Qualified name string for the code object

160

"""

161

```

162

163

### Execution Information

164

165

Access detailed information about the currently executing operation, including source text and qualified names.

166

167

```python { .api }

168

class Executing:

169

def code_qualname(self) -> str:

170

"""

171

Returns the qualified name of the function being executed.

172

173

Returns:

174

String representing the function's qualified name

175

"""

176

177

def text(self) -> str:

178

"""

179

Returns the source code text of the executing node.

180

Requires asttokens library to be installed separately.

181

182

Returns:

183

Source code string of the executing AST node

184

"""

185

186

def text_range(self) -> Tuple[int, int]:

187

"""

188

Returns the character range of the executing node in the source.

189

Requires asttokens library to be installed separately.

190

191

Returns:

192

Tuple of (start_pos, end_pos) character positions

193

"""

194

```

195

196

### Utility Functions

197

198

Helper functions for working with iterables and checking compatibility with testing frameworks.

199

200

```python { .api }

201

def only(it: Iterable[T]) -> T:

202

"""

203

Extract single value from iterable, raising NotOneValueFound if not exactly one.

204

205

Parameters:

206

- it: Iterable[T] - iterable to extract value from

207

208

Returns:

209

T - The single value from the iterable

210

211

Raises:

212

NotOneValueFound - if iterable contains zero or multiple values

213

"""

214

215

def is_pytest_compatible() -> bool:

216

"""

217

Returns True if executing can be used for expressions inside assert statements

218

which are rewritten by pytest. Requires Python 3.11+ and pytest 8.3.4+.

219

220

Returns:

221

Boolean indicating pytest compatibility

222

"""

223

224

cache = lru_cache(maxsize=None)

225

"""LRU cache with no size limit for performance optimization."""

226

227

future_flags: int

228

"""

229

Sum of all __future__ compiler flags.

230

231

This is calculated as:

232

sum(getattr(__future__, fname).compiler_flag for fname in __future__.all_feature_names)

233

234

Used internally for compiling code with the same future imports as the original code.

235

"""

236

```

237

238

### Source Utilities

239

240

Static methods for handling source code encoding and text processing.

241

242

```python { .api }

243

class Source:

244

@staticmethod

245

def decode_source(source) -> str:

246

"""

247

Decode source code from bytes or return string as-is.

248

249

Parameters:

250

- source: str or bytes - source code to decode

251

252

Returns:

253

Decoded source code as string

254

"""

255

256

@staticmethod

257

def detect_encoding(source) -> str:

258

"""

259

Detect encoding of source code bytes.

260

261

Parameters:

262

- source: bytes - source code bytes

263

264

Returns:

265

Encoding name as string

266

"""

267

```

268

269

## Types

270

271

```python { .api }

272

class Executing:

273

"""

274

Information about the operation a frame is currently executing.

275

276

Attributes:

277

- frame: types.FrameType - the frame being analyzed

278

- source: Source - Source object for the frame's file

279

- node: ast.AST or None - AST node being executed

280

- statements: Set[ast.stmt] - set of statement nodes

281

- decorator: ast.AST or None - decorator expression being called (if applicable)

282

"""

283

284

class Source:

285

"""

286

The source code of a single file and associated metadata.

287

288

Attributes:

289

- filename: str - source filename

290

- text: str - complete source text

291

- lines: List[str] - list of source lines

292

- tree: ast.Module or None - AST parsed from text (None if invalid Python)

293

"""

294

295

class NotOneValueFound(Exception):

296

"""

297

Raised when expected exactly one value but got zero or multiple.

298

299

Attributes:

300

- values: Sequence - values found when multiple (empty when zero)

301

"""

302

303

class KnownIssue(Exception):

304

"""

305

Raised in case of a known problem, mostly because of CPython bugs.

306

Executing.node gets set to None in this case.

307

"""

308

309

class VerifierFailure(Exception):

310

"""

311

Thrown for an unexpected mapping from instruction to AST node.

312

Executing.node gets set to None in this case.

313

314

Attributes:

315

- node: object - the AST node that failed verification

316

- instruction: object - the bytecode instruction that failed verification

317

"""

318

```

319

320

## Error Handling

321

322

The executing library handles various edge cases and potential issues:

323

324

- **Invalid Python code**: Returns `None` for `tree` attribute in Source objects

325

- **Unidentifiable nodes**: Returns `None` for `node` attribute in Executing objects

326

- **Missing dependencies**: Methods requiring `asttokens` will raise ImportError if not installed

327

- **Bytecode analysis failures**: Gracefully handles cases where AST-to-bytecode matching fails

328

329

Always check if the returned `node` is not `None` before using it, as node identification may fail in complex cases or with certain bytecode optimizations.

330

331

## Supported AST Node Types

332

333

The executing library can currently identify these AST node types:

334

335

- **Call**: Function and method calls (e.g., `func()`, `obj.method()`)

336

- **Attribute**: Attribute access (e.g., `obj.attr`)

337

- **Subscript**: Indexing and slicing (e.g., `lst[0]`, `dict['key']`)

338

- **BinOp**: Binary operations (e.g., `x + y`, `a * b`) - excludes `and`/`or`

339

- **UnaryOp**: Unary operations (e.g., `-x`, `not condition`) - `not` has limited support

340

- **Compare**: Comparison operations (e.g., `a < b`, `x == y`) - excludes chained comparisons

341

342

The library works by modifying AST nodes with sentinel values and analyzing the resulting bytecode changes to determine which node corresponds to the current instruction.