or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

chooser.mdcommand-line.mdconfiguration.mddiff-utilities.mdfile-utilities.mdformatters.mdgit-integration.mdindex.mdmain-functions.mdpreprocessors.mdverification.md

verification.mddocs/

0

# AST Verification

1

2

AST verification utilities for ensuring code transformations preserve semantic equivalence. These functions validate that reformatting doesn't change the abstract syntax tree structure of Python code.

3

4

## Capabilities

5

6

### AST Verification Classes

7

8

Core classes for verifying AST equivalence between original and reformatted code.

9

10

```python { .api }

11

class ASTVerifier:

12

"""

13

Verify if reformatted TextDocument is AST-equivalent to baseline.

14

15

Keeps in-memory data about previous comparisons to improve performance.

16

"""

17

18

def __init__(self, baseline: TextDocument) -> None:

19

"""

20

Initialize verifier with baseline document.

21

22

Parameters:

23

- baseline: The baseline document to compare against

24

"""

25

26

def is_equivalent_to_baseline(self, document: TextDocument) -> bool:

27

"""

28

Returns true if document is AST-equivalent to baseline.

29

30

Parameters:

31

- document: Document to compare against baseline

32

33

Returns:

34

True if documents are AST-equivalent, False otherwise

35

"""

36

37

class BinarySearch:

38

"""

39

Effectively search the first index for which a condition is True.

40

41

Used for finding the minimal change that breaks AST equivalence.

42

"""

43

44

def __init__(self, low: int, high: int) -> None:

45

"""

46

Initialize binary search with range bounds.

47

48

Parameters:

49

- low: Lower bound of search range

50

- high: Upper bound of search range

51

"""

52

53

def get_next(self) -> int:

54

"""Get the next integer index to try."""

55

56

def respond(self, value: bool) -> None:

57

"""

58

Provide a False or True answer for the current integer index.

59

60

Parameters:

61

- value: Response for current index

62

"""

63

64

@property

65

def found(self) -> bool:

66

"""Return True if the lowest True response index has been found."""

67

68

@property

69

def result(self) -> int:

70

"""Return the lowest index with a True response."""

71

```

72

73

### AST Parsing and Comparison

74

75

Functions for parsing and comparing Python ASTs with error handling.

76

77

```python { .api }

78

def parse_ast(src: str) -> ast.AST:

79

"""

80

Parse source code with fallback for type comments.

81

82

This function tries multiple Python version feature sets

83

and handles both type comments and syntax variations.

84

85

Parameters:

86

- src: Python source code to parse

87

88

Returns:

89

Parsed AST node

90

91

Raises:

92

SyntaxError: If source cannot be parsed with any supported syntax

93

"""

94

95

def stringify_ast(node: ast.AST) -> Iterator[str]:

96

"""

97

Generate strings to compare ASTs by content using a simple visitor.

98

99

Parameters:

100

- node: Root AST node to stringify

101

102

Yields:

103

String representations of AST nodes for comparison

104

"""

105

```

106

107

### Exception Types

108

109

Exceptions specific to AST verification operations.

110

111

```python { .api }

112

class NotEquivalentError(Exception):

113

"""Exception to raise if two ASTs being compared are not equivalent."""

114

```

115

116

## Usage Examples

117

118

### Basic AST Verification

119

120

```python

121

from darker.verification import ASTVerifier

122

from darkgraylib.utils import TextDocument

123

124

# Set up verification with baseline code

125

original_code = TextDocument.from_str('''

126

def hello(name):

127

print(f"Hello, {name}!")

128

''')

129

130

verifier = ASTVerifier(original_code)

131

132

# Check if reformatted code is equivalent

133

formatted_code = TextDocument.from_str('''

134

def hello(name):

135

print(f"Hello, {name}!")

136

''')

137

138

is_equivalent = verifier.is_equivalent_to_baseline(formatted_code)

139

print(f"Code is AST-equivalent: {is_equivalent}")

140

```

141

142

### Binary Search for Error Location

143

144

```python

145

from darker.verification import BinarySearch

146

147

# Find first line where condition becomes true

148

search = BinarySearch(0, 100)

149

150

while not search.found:

151

line_num = search.get_next()

152

# Test some condition on line_num

153

condition_met = some_test_function(line_num)

154

search.respond(condition_met)

155

156

print(f"First line where condition is true: {search.result}")

157

```

158

159

### Custom AST Parsing

160

161

```python

162

from darker.verification import parse_ast, stringify_ast

163

164

try:

165

source = '''

166

def example() -> None:

167

x: int = 42

168

return None

169

'''

170

171

ast_tree = parse_ast(source)

172

ast_strings = list(stringify_ast(ast_tree))

173

174

print("AST structure:")

175

for line in ast_strings[:10]: # Show first 10 lines

176

print(line)

177

178

except SyntaxError as e:

179

print(f"Could not parse source: {e}")

180

```