Skip to content

Commit 5fa503f

Browse files
committed
Relint
Signed-off-by: Mihai Criveti <[email protected]>
1 parent b45e5be commit 5fa503f

38 files changed

+262
-301
lines changed

async_testing/async_validator.py

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
"""
23
Validate async code patterns and detect common pitfalls.
34
"""
@@ -10,116 +11,116 @@
1011

1112
class AsyncCodeValidator:
1213
"""Validate async code for common patterns and pitfalls."""
13-
14+
1415
def __init__(self):
1516
self.issues = []
1617
self.suggestions = []
17-
18+
1819
def validate_directory(self, source_dir: Path) -> Dict[str, Any]:
1920
"""Validate all Python files in directory."""
20-
21+
2122
validation_results = {
2223
'files_checked': 0,
2324
'issues_found': 0,
2425
'suggestions': 0,
2526
'details': []
2627
}
27-
28+
2829
python_files = list(source_dir.rglob("*.py"))
29-
30+
3031
for file_path in python_files:
3132
if self._should_skip_file(file_path):
3233
continue
33-
34+
3435
file_results = self._validate_file(file_path)
3536
validation_results['details'].append(file_results)
3637
validation_results['files_checked'] += 1
3738
validation_results['issues_found'] += len(file_results['issues'])
3839
validation_results['suggestions'] += len(file_results['suggestions'])
39-
40+
4041
return validation_results
41-
42+
4243
def _validate_file(self, file_path: Path) -> Dict[str, Any]:
4344
"""Validate a single Python file."""
44-
45+
4546
file_results = {
4647
'file': str(file_path),
4748
'issues': [],
4849
'suggestions': []
4950
}
50-
51+
5152
try:
5253
with open(file_path, 'r', encoding='utf-8') as f:
5354
source_code = f.read()
54-
55+
5556
tree = ast.parse(source_code, filename=str(file_path))
56-
57+
5758
# Analyze AST for async patterns
5859
validator = AsyncPatternVisitor(file_path)
5960
validator.visit(tree)
60-
61+
6162
file_results['issues'] = validator.issues
6263
file_results['suggestions'] = validator.suggestions
63-
64+
6465
except Exception as e:
6566
file_results['issues'].append({
6667
'type': 'parse_error',
6768
'message': f"Failed to parse file: {str(e)}",
6869
'line': 0
6970
})
70-
71+
7172
return file_results
72-
73-
73+
74+
7475
def _should_skip_file(self, file_path: Path) -> bool:
7576
"""Determine if a file should be skipped (e.g., __init__.py files)."""
7677
return file_path.name == "__init__.py"
77-
78+
7879
class AsyncPatternVisitor(ast.NodeVisitor):
7980
"""AST visitor to detect async patterns and issues."""
80-
81+
8182
def __init__(self, file_path: Path):
8283
self.file_path = file_path
8384
self.issues = []
8485
self.suggestions = []
8586
self.in_async_function = False
86-
87+
8788
def visit_AsyncFunctionDef(self, node):
8889
"""Visit async function definitions."""
89-
90+
9091
self.in_async_function = True
91-
92+
9293
# Check for blocking operations in async functions
9394
self._check_blocking_operations(node)
94-
95+
9596
# Check for proper error handling
9697
self._check_error_handling(node)
97-
98+
9899
self.generic_visit(node)
99100
self.in_async_function = False
100-
101+
101102
def visit_Call(self, node):
102103
"""Visit function calls."""
103-
104+
104105
if self.in_async_function:
105106
# Check for potentially unawaited async calls
106107
self._check_unawaited_calls(node)
107-
108+
108109
# Check for blocking I/O operations
109110
self._check_blocking_io(node)
110-
111+
111112
self.generic_visit(node)
112-
113+
113114
def _check_blocking_operations(self, node):
114115
"""Check for blocking operations in async functions."""
115-
116+
116117
blocking_patterns = [
117118
'time.sleep',
118119
'requests.get', 'requests.post',
119120
'subprocess.run', 'subprocess.call',
120121
'open' # File I/O without async
121122
]
122-
123+
123124
for child in ast.walk(node):
124125
if isinstance(child, ast.Call):
125126
call_name = self._get_call_name(child)
@@ -130,18 +131,18 @@ def _check_blocking_operations(self, node):
130131
'line': child.lineno,
131132
'suggestion': f"Use async equivalent of {call_name}"
132133
})
133-
134+
134135
def _check_unawaited_calls(self, node):
135136
"""Check for potentially unawaited async calls."""
136-
137+
137138
# Look for calls that might return coroutines
138139
async_patterns = [
139140
'aiohttp', 'asyncio', 'asyncpg',
140141
'websockets', 'motor' # Common async libraries
141142
]
142-
143+
143144
call_name = self._get_call_name(node)
144-
145+
145146
for pattern in async_patterns:
146147
if pattern in call_name:
147148
# Check if this call is awaited
@@ -153,10 +154,10 @@ def _check_unawaited_calls(self, node):
153154
'line': node.lineno
154155
})
155156
break
156-
157+
157158
def _get_call_name(self, node):
158159
"""Extract the name of a function call."""
159-
160+
160161
if isinstance(node.func, ast.Name):
161162
return node.func.id
162163
elif isinstance(node.func, ast.Attribute):
@@ -165,19 +166,19 @@ def _get_call_name(self, node):
165166
else:
166167
return node.func.attr
167168
return "unknown"
168-
169+
169170

170171
if __name__ == "__main__":
171172
parser = argparse.ArgumentParser(description="Validate async code patterns and detect common pitfalls.")
172173
parser.add_argument("--source", type=Path, required=True, help="Source directory to validate.")
173174
parser.add_argument("--report", type=Path, required=True, help="Path to the output validation report.")
174-
175+
175176
args = parser.parse_args()
176-
177+
177178
validator = AsyncCodeValidator()
178179
results = validator.validate_directory(args.source)
179-
180+
180181
with open(args.report, 'w') as f:
181182
json.dump(results, f, indent=4)
182-
183-
print(f"Validation report saved to {args.report}")
183+
184+
print(f"Validation report saved to {args.report}")

async_testing/benchmarks.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
"""
23
Run async performance benchmarks and output results.
34
"""
@@ -10,63 +11,63 @@
1011

1112
class AsyncBenchmark:
1213
"""Run async performance benchmarks."""
13-
14+
1415
def __init__(self, iterations: int):
1516
self.iterations = iterations
1617
self.results: Dict[str, Any] = {
1718
'iterations': self.iterations,
1819
'benchmarks': []
1920
}
20-
21+
2122
async def run_benchmarks(self) -> None:
2223
"""Run all benchmarks."""
23-
24+
2425
# Example benchmarks
2526
await self._benchmark_example("Example Benchmark 1", self.example_benchmark_1)
2627
await self._benchmark_example("Example Benchmark 2", self.example_benchmark_2)
27-
28+
2829
async def _benchmark_example(self, name: str, benchmark_func) -> None:
2930
"""Run a single benchmark and record its performance."""
30-
31+
3132
start_time = time.perf_counter()
32-
33+
3334
for _ in range(self.iterations):
3435
await benchmark_func()
35-
36+
3637
end_time = time.perf_counter()
3738
total_time = end_time - start_time
3839
avg_time = total_time / self.iterations
39-
40+
4041
self.results['benchmarks'].append({
4142
'name': name,
4243
'total_time': total_time,
4344
'average_time': avg_time
4445
})
45-
46+
4647
async def example_benchmark_1(self) -> None:
4748
"""An example async benchmark function."""
4849
await asyncio.sleep(0.001)
49-
50+
5051
async def example_benchmark_2(self) -> None:
5152
"""Another example async benchmark function."""
5253
await asyncio.sleep(0.002)
53-
54+
5455
def save_results(self, output_path: Path) -> None:
5556
"""Save benchmark results to a file."""
56-
57+
5758
with open(output_path, 'w') as f:
5859
json.dump(self.results, f, indent=4)
59-
60+
6061
print(f"Benchmark results saved to {output_path}")
6162

6263

6364
if __name__ == "__main__":
6465
parser = argparse.ArgumentParser(description="Run async performance benchmarks.")
6566
parser.add_argument("--output", type=Path, required=True, help="Path to the output benchmark results file.")
6667
parser.add_argument("--iterations", type=int, default=1000, help="Number of iterations to run each benchmark.")
67-
68+
6869
args = parser.parse_args()
69-
70+
7071
benchmark = AsyncBenchmark(args.iterations)
7172
asyncio.run(benchmark.run_benchmarks())
72-
benchmark.save_results(args.output)
73+
benchmark.save_results(args.output)

0 commit comments

Comments
 (0)