• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

smythi93 / Tests4Py / 30040549735

23 Jul 2026 08:04PM UTC coverage: 23.663% (-21.5%) from 45.174%
30040549735

push

github

web-flow
Merge pull request #106 from smythi93/dev

Release 1.0.0 — complete benchmark coverage (328/328 reproducible bugs)

11882 of 64778 new or added lines in 1205 files covered. (18.34%)

46 existing lines in 14 files now uncovered.

18085 of 76426 relevant lines covered (23.66%)

0.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.44
/src/tests4py/grammars/python.py
1
import ast
1✔
2
import random
1✔
3
import string
1✔
4
from ast import *
1✔
5
from typing import Optional, Union
1✔
6

7
from tests4py.grammars.fuzzer import GrammarFuzzer, Grammar, srange, is_valid_grammar
1✔
8
from tests4py.grammars.tree import ComplexDerivationTree
1✔
9
from tests4py.grammars.utils import GrammarVisitor, Generator
1✔
10

11

12
class PythonVisitor(GrammarVisitor):
1✔
13
    pass
1✔
14

15

16
# noinspection PyMethodMayBeStatic,PyUnusedLocal
17
class ToASTVisitor(PythonVisitor):
1✔
18
    def generic_visit(self, node: ComplexDerivationTree) -> AST:
1✔
19
        return self.visit(node.children[0])
1✔
20

21
    def visit_Module(self, node: ComplexDerivationTree) -> Module:
1✔
22
        return Module(
1✔
23
            body=self.visit(node.children[1]),
24
            type_ignores=self.visit(node.children[3]),
25
        )
26

27
    def visit_Interactive(self, node: ComplexDerivationTree) -> Interactive:
1✔
28
        return Interactive(body=self.visit(node.children[1]))
×
29

30
    def visit_Expression(self, node: ComplexDerivationTree) -> Expression:
1✔
31
        return Expression(body=self.visit(node.children[1]))
×
32

33
    def visit_FunctionType(self, node: ComplexDerivationTree) -> FunctionType:
1✔
34
        return FunctionType(
×
35
            argtypes=self.visit(node.children[1]),
36
            returns=self.visit(node.children[3]),
37
        )
38

39
    def visit_FunctionDef(self, node: ComplexDerivationTree) -> FunctionDef:
1✔
40
        return FunctionDef(
1✔
41
            name=self.visit(node.children[1]),
42
            args=self.visit(node.children[3]),
43
            body=self.visit(node.children[5]),
44
            decorator_list=self.visit(node.children[7]),
45
            returns=self.visit(node.children[9]),
46
            type_comment=self.visit(node.children[11]),
47
            lineno=0,
48
        )
49

50
    def visit_AsyncFunctionDef(self, node: ComplexDerivationTree) -> AsyncFunctionDef:
1✔
51
        return AsyncFunctionDef(
×
52
            name=self.visit(node.children[1]),
53
            args=self.visit(node.children[3]),
54
            body=self.visit(node.children[5]),
55
            decorator_list=self.visit(node.children[7]),
56
            returns=self.visit(node.children[9]),
57
            type_comment=self.visit(node.children[11]),
58
            lineno=0,
59
        )
60

61
    def visit_ClassDef(self, node: ComplexDerivationTree) -> ClassDef:
1✔
62
        return ClassDef(
1✔
63
            name=self.visit(node.children[1]),
64
            bases=self.visit(node.children[3]),
65
            keywords=self.visit(node.children[5]),
66
            body=self.visit(node.children[7]),
67
            decorator_list=self.visit(node.children[9]),
68
        )
69

70
    def visit_Return(self, node: ComplexDerivationTree) -> Return:
1✔
71
        return Return(
1✔
72
            value=self.visit(node.children[1]),
73
        )
74

75
    def visit_Delete(self, node: ComplexDerivationTree) -> Delete:
1✔
76
        return Delete(
1✔
77
            targets=self.visit(node.children[1]),
78
        )
79

80
    def visit_Assign(self, node: ComplexDerivationTree) -> Assign:
1✔
81
        return Assign(
1✔
82
            targets=self.visit(node.children[1]),
83
            value=self.visit(node.children[3]),
84
            type_comment=self.visit(node.children[5]),
85
            lineno=0,
86
        )
87

88
    def visit_AugAssign(self, node: ComplexDerivationTree) -> AugAssign:
1✔
89
        return AugAssign(
1✔
90
            target=self.visit(node.children[1]),
91
            op=self.visit(node.children[3]),
92
            value=self.visit(node.children[5]),
93
        )
94

95
    def visit_AnnAssign(self, node: ComplexDerivationTree) -> AnnAssign:
1✔
96
        return AnnAssign(
1✔
97
            target=self.visit(node.children[1]),
98
            annotation=self.visit(node.children[3]),
99
            value=self.visit(node.children[5]),
100
            simple=self.visit(node.children[7]),
101
        )
102

103
    def visit_For(self, node: ComplexDerivationTree) -> For:
1✔
104
        return For(
1✔
105
            target=self.visit(node.children[1]),
106
            iter=self.visit(node.children[3]),
107
            body=self.visit(node.children[5]),
108
            orelse=self.visit(node.children[7]),
109
            type_comment=self.visit(node.children[9]),
110
            lineno=0,
111
        )
112

113
    def visit_AsyncFor(self, node: ComplexDerivationTree) -> AsyncFor:
1✔
114
        return AsyncFor(
×
115
            target=self.visit(node.children[1]),
116
            iter=self.visit(node.children[3]),
117
            body=self.visit(node.children[5]),
118
            orelse=self.visit(node.children[7]),
119
            type_comment=self.visit(node.children[9]),
120
            lineno=0,
121
        )
122

123
    def visit_While(self, node: ComplexDerivationTree) -> While:
1✔
124
        return While(
1✔
125
            test=self.visit(node.children[1]),
126
            body=self.visit(node.children[3]),
127
            orelse=self.visit(node.children[5]),
128
        )
129

130
    def visit_If(self, node: ComplexDerivationTree) -> If:
1✔
131
        return If(
1✔
132
            test=self.visit(node.children[1]),
133
            body=self.visit(node.children[3]),
134
            orelse=self.visit(node.children[5]),
135
        )
136

137
    def visit_With(self, node: ComplexDerivationTree) -> With:
1✔
138
        return With(
1✔
139
            items=self.visit(node.children[1]),
140
            body=self.visit(node.children[3]),
141
            type_comment=self.visit(node.children[5]),
142
            lineno=0,
143
        )
144

145
    def visit_AsyncWith(self, node: ComplexDerivationTree) -> AsyncWith:
1✔
146
        return AsyncWith(
×
147
            items=self.visit(node.children[1]),
148
            body=self.visit(node.children[3]),
149
            type_comment=self.visit(node.children[5]),
150
            lineno=0,
151
        )
152

153
    def visit_Match(self, node: ComplexDerivationTree) -> Match:
1✔
154
        return Match(
1✔
155
            subject=self.visit(node.children[1]),
156
            cases=self.visit(node.children[3]),
157
        )
158

159
    def visit_Raise(self, node: ComplexDerivationTree) -> Raise:
1✔
160
        return Raise(
1✔
161
            exc=self.visit(node.children[1]),
162
            cause=self.visit(node.children[3]),
163
        )
164

165
    def visit_Try(self, node: ComplexDerivationTree) -> Try:
1✔
166
        return Try(
1✔
167
            body=self.visit(node.children[1]),
168
            handlers=self.visit(node.children[3]),
169
            orelse=self.visit(node.children[5]),
170
            finalbody=self.visit(node.children[7]),
171
        )
172

173
    # def visit_TryStar(self, node: DerivationTree) -> TryStar:
174
    #     return TryStar(
175
    #         body=self.visit(node.children[1]),
176
    #         handlers=self.visit(node.children[3]),
177
    #         orelse=self.visit(node.children[5]),
178
    #         finalbody=self.visit(node.children[7]),
179
    #     )
180

181
    def visit_Assert(self, node: ComplexDerivationTree) -> Assert:
1✔
182
        return Assert(
1✔
183
            test=self.visit(node.children[1]),
184
            msg=self.visit(node.children[3]),
185
        )
186

187
    def visit_Import(self, node: ComplexDerivationTree) -> Import:
1✔
188
        return Import(
1✔
189
            names=self.visit(node.children[1]),
190
        )
191

192
    def visit_ImportFrom(self, node: ComplexDerivationTree) -> ImportFrom:
1✔
193
        return ImportFrom(
1✔
194
            module=self.visit(node.children[1]),
195
            names=self.visit(node.children[3]),
196
            level=self.visit(node.children[5]),
197
        )
198

199
    def visit_Global(self, node: ComplexDerivationTree) -> Global:
1✔
200
        return Global(
1✔
201
            names=self.visit(node.children[1]),
202
        )
203

204
    def visit_Nonlocal(self, node: ComplexDerivationTree) -> Nonlocal:
1✔
205
        return Nonlocal(
×
206
            names=self.visit(node.children[1]),
207
        )
208

209
    def visit_Expr(self, node: ComplexDerivationTree) -> Expr:
1✔
210
        return Expr(
1✔
211
            value=self.visit(node.children[1]),
212
        )
213

214
    def visit_Pass(self, node: ComplexDerivationTree) -> Pass:
1✔
215
        return Pass()
1✔
216

217
    def visit_Break(self, node: ComplexDerivationTree) -> Break:
1✔
218
        return Break()
1✔
219

220
    def visit_Continue(self, node: ComplexDerivationTree) -> Continue:
1✔
221
        return Continue()
1✔
222

223
    def visit_BoolOp(self, node: ComplexDerivationTree) -> BoolOp:
1✔
224
        return BoolOp(
×
225
            op=self.visit(node.children[1]),
226
            values=self.visit(node.children[3]),
227
        )
228

229
    def visit_NamedExpr(self, node: ComplexDerivationTree) -> NamedExpr:
1✔
230
        return NamedExpr(
×
231
            target=self.visit(node.children[1]),
232
            value=self.visit(node.children[3]),
233
        )
234

235
    def visit_BinOp(self, node: ComplexDerivationTree) -> BinOp:
1✔
236
        return BinOp(
1✔
237
            left=self.visit(node.children[1]),
238
            op=self.visit(node.children[3]),
239
            right=self.visit(node.children[5]),
240
        )
241

242
    def visit_UnaryOp(self, node: ComplexDerivationTree) -> UnaryOp:
1✔
243
        return UnaryOp(
1✔
244
            op=self.visit(node.children[1]),
245
            operand=self.visit(node.children[3]),
246
        )
247

248
    def visit_Lambda(self, node: ComplexDerivationTree) -> Lambda:
1✔
249
        return Lambda(
×
250
            args=self.visit(node.children[1]),
251
            body=self.visit(node.children[3]),
252
        )
253

254
    def visit_IfExp(self, node: ComplexDerivationTree) -> IfExp:
1✔
255
        return IfExp(
×
256
            test=self.visit(node.children[1]),
257
            body=self.visit(node.children[3]),
258
            orelse=self.visit(node.children[5]),
259
        )
260

261
    def visit_Dict(self, node: ComplexDerivationTree) -> Dict:
1✔
262
        return Dict(
1✔
263
            keys=self.visit(node.children[1]),
264
            values=self.visit(node.children[3]),
265
        )
266

267
    def visit_Set(self, node: ComplexDerivationTree) -> Set:
1✔
268
        return Set(
×
269
            elts=self.visit(node.children[1]),
270
        )
271

272
    def visit_ListComp(self, node: ComplexDerivationTree) -> ListComp:
1✔
273
        return ListComp(
×
274
            elt=self.visit(node.children[1]),
275
            generators=self.visit(node.children[3]),
276
        )
277

278
    def visit_SetComp(self, node: ComplexDerivationTree) -> SetComp:
1✔
279
        return SetComp(
×
280
            elt=self.visit(node.children[1]),
281
            generators=self.visit(node.children[3]),
282
        )
283

284
    def visit_DictComp(self, node: ComplexDerivationTree) -> DictComp:
1✔
285
        return DictComp(
×
286
            key=self.visit(node.children[1]),
287
            value=self.visit(node.children[3]),
288
            generators=self.visit(node.children[5]),
289
        )
290

291
    def visit_GeneratorExp(self, node: ComplexDerivationTree) -> GeneratorExp:
1✔
292
        return GeneratorExp(
×
293
            elt=self.visit(node.children[1]),
294
            generators=self.visit(node.children[3]),
295
        )
296

297
    def visit_Await(self, node: ComplexDerivationTree) -> Await:
1✔
298
        return Await(
×
299
            value=self.visit(node.children[1]),
300
        )
301

302
    def visit_Yield(self, node: ComplexDerivationTree) -> Yield:
1✔
303
        return Yield(
×
304
            value=self.visit(node.children[1]),
305
        )
306

307
    def visit_YieldFrom(self, node: ComplexDerivationTree) -> YieldFrom:
1✔
308
        return YieldFrom(
×
309
            value=self.visit(node.children[1]),
310
        )
311

312
    def visit_Compare(self, node: ComplexDerivationTree) -> Compare:
1✔
313
        return Compare(
1✔
314
            left=self.visit(node.children[1]),
315
            ops=self.visit(node.children[3]),
316
            comparators=self.visit(node.children[5]),
317
        )
318

319
    def visit_Call(self, node: ComplexDerivationTree) -> Call:
1✔
320
        return Call(
1✔
321
            func=self.visit(node.children[1]),
322
            args=self.visit(node.children[3]),
323
            keywords=self.visit(node.children[5]),
324
        )
325

326
    def visit_FormattedValue(self, node: ComplexDerivationTree) -> FormattedValue:
1✔
327
        return FormattedValue(
×
328
            value=self.visit(node.children[1]),
329
            conversion=self.visit(node.children[3]),
330
            format_spec=self.visit(node.children[5]),
331
        )
332

333
    def visit_JoinedStr(self, node: ComplexDerivationTree) -> JoinedStr:
1✔
334
        return JoinedStr(
×
335
            values=self.visit(node.children[1]),
336
        )
337

338
    def visit_Constant(self, node: ComplexDerivationTree) -> Constant:
1✔
339
        return Constant(
1✔
340
            value=self.visit(node.children[1]),
341
            kind=self.visit(node.children[3]),
342
        )
343

344
    def visit_Attribute(self, node: ComplexDerivationTree) -> Attribute:
1✔
345
        return Attribute(
1✔
346
            value=self.visit(node.children[1]),
347
            attr=self.visit(node.children[3]),
348
        )
349

350
    def visit_Subscript(self, node: ComplexDerivationTree) -> Subscript:
1✔
351
        return Subscript(
1✔
352
            value=self.visit(node.children[1]),
353
            slice=self.visit(node.children[3]),
354
        )
355

356
    def visit_Starred(self, node: ComplexDerivationTree) -> Starred:
1✔
357
        return Starred(
×
358
            value=self.visit(node.children[1]),
359
        )
360

361
    def visit_Name(self, node: ComplexDerivationTree) -> Name:
1✔
362
        return Name(
1✔
363
            id=self.visit(node.children[1]),
364
        )
365

366
    def visit_List(self, node: ComplexDerivationTree) -> List:
1✔
367
        return List(
1✔
368
            elts=self.visit(node.children[1]),
369
        )
370

371
    def visit_Tuple(self, node: ComplexDerivationTree) -> Tuple:
1✔
372
        return Tuple(
1✔
373
            elts=self.visit(node.children[1]),
374
        )
375

376
    def visit_Slice(self, node: ComplexDerivationTree) -> Slice:
1✔
377
        return Slice(
1✔
378
            lower=self.visit(node.children[1]),
379
            upper=self.visit(node.children[3]),
380
            step=self.visit(node.children[5]),
381
        )
382

383
    def visit_And(self, node: ComplexDerivationTree) -> And:
1✔
384
        return And()
×
385

386
    def visit_Or(self, node: ComplexDerivationTree) -> Or:
1✔
387
        return Or()
×
388

389
    def visit_Add(self, node: ComplexDerivationTree) -> Add:
1✔
390
        return Add()
1✔
391

392
    def visit_Sub(self, node: ComplexDerivationTree) -> Sub:
1✔
393
        return Sub()
×
394

395
    def visit_Mult(self, node: ComplexDerivationTree) -> Mult:
1✔
396
        return Mult()
×
397

398
    def visit_MatMult(self, node: ComplexDerivationTree) -> MatMult:
1✔
399
        return MatMult()
×
400

401
    def visit_Div(self, node: ComplexDerivationTree) -> Div:
1✔
402
        return Div()
×
403

404
    def visit_Mod(self, node: ComplexDerivationTree) -> Mod:
1✔
405
        return Mod()
×
406

407
    def visit_Pow(self, node: ComplexDerivationTree) -> Pow:
1✔
408
        return Pow()
×
409

410
    def visit_LShift(self, node: ComplexDerivationTree) -> LShift:
1✔
411
        return LShift()
×
412

413
    def visit_RShift(self, node: ComplexDerivationTree) -> RShift:
1✔
414
        return RShift()
×
415

416
    def visit_BitOr(self, node: ComplexDerivationTree) -> BitOr:
1✔
417
        return BitOr()
×
418

419
    def visit_BitXor(self, node: ComplexDerivationTree) -> BitXor:
1✔
420
        return BitXor()
1✔
421

422
    def visit_BitAnd(self, node: ComplexDerivationTree) -> BitAnd:
1✔
423
        return BitAnd()
1✔
424

425
    def visit_FloorDiv(self, node: ComplexDerivationTree) -> FloorDiv:
1✔
426
        return FloorDiv()
×
427

428
    def visit_Invert(self, node: ComplexDerivationTree) -> Invert:
1✔
429
        return Invert()
×
430

431
    def visit_Not(self, node: ComplexDerivationTree) -> Not:
1✔
432
        return Not()
×
433

434
    def visit_UAdd(self, node: ComplexDerivationTree) -> UAdd:
1✔
435
        return UAdd()
×
436

437
    def visit_USub(self, node: ComplexDerivationTree) -> USub:
1✔
438
        return USub()
1✔
439

440
    def visit_Eq(self, node: ComplexDerivationTree) -> Eq:
1✔
441
        return Eq()
1✔
442

443
    def visit_NotEq(self, node: ComplexDerivationTree) -> NotEq:
1✔
444
        return NotEq()
×
445

446
    def visit_Lt(self, node: ComplexDerivationTree) -> Lt:
1✔
447
        return Lt()
1✔
448

449
    def visit_LtE(self, node: ComplexDerivationTree) -> LtE:
1✔
450
        return LtE()
×
451

452
    def visit_Gt(self, node: ComplexDerivationTree) -> Gt:
1✔
453
        return Gt()
×
454

455
    def visit_GtE(self, node: ComplexDerivationTree) -> GtE:
1✔
456
        return GtE()
×
457

458
    def visit_Is(self, node: ComplexDerivationTree) -> Is:
1✔
459
        return Is()
×
460

461
    def visit_IsNot(self, node: ComplexDerivationTree) -> IsNot:
1✔
462
        return IsNot()
×
463

464
    def visit_In(self, node: ComplexDerivationTree) -> In:
1✔
465
        return In()
×
466

467
    def visit_NotIn(self, node: ComplexDerivationTree) -> NotIn:
1✔
468
        return NotIn()
×
469

470
    def visit_comprehension(self, node: ComplexDerivationTree) -> comprehension:
1✔
471
        return comprehension(
×
472
            target=self.visit(node.children[1]),
473
            iter=self.visit(node.children[3]),
474
            ifs=self.visit(node.children[5]),
475
            is_async=self.visit(node.children[7]),
476
        )
477

478
    def visit_ExceptHandler(self, node: ComplexDerivationTree) -> ExceptHandler:
1✔
479
        return ExceptHandler(
1✔
480
            type=self.visit(node.children[1]),
481
            name=self.visit(node.children[3]),
482
            body=self.visit(node.children[5]),
483
        )
484

485
    def visit_arguments(self, node: ComplexDerivationTree) -> arguments:
1✔
486
        return arguments(
1✔
487
            posonlyargs=self.visit(node.children[1]),
488
            args=self.visit(node.children[3]),
489
            vararg=self.visit(node.children[5]),
490
            kwonlyargs=self.visit(node.children[7]),
491
            kw_defaults=self.visit(node.children[9]),
492
            kwarg=self.visit(node.children[11]),
493
            defaults=self.visit(node.children[13]),
494
        )
495

496
    def visit_arg(self, node: ComplexDerivationTree) -> arg:
1✔
497
        return arg(
1✔
498
            arg=self.visit(node.children[1]),
499
            annotation=self.visit(node.children[3]),
500
            type_comment=self.visit(node.children[5]),
501
        )
502

503
    def visit_keyword(self, node: ComplexDerivationTree) -> keyword:
1✔
504
        return keyword(
×
505
            arg=self.visit(node.children[1]),
506
            value=self.visit(node.children[3]),
507
        )
508

509
    def visit_alias(self, node: ComplexDerivationTree) -> alias:
1✔
510
        return alias(
1✔
511
            name=self.visit(node.children[1]),
512
            asname=self.visit(node.children[3]),
513
        )
514

515
    def visit_withitem(self, node: ComplexDerivationTree) -> withitem:
1✔
516
        return withitem(
1✔
517
            context_expr=self.visit(node.children[1]),
518
            optional_vars=self.visit(node.children[3]),
519
        )
520

521
    def visit_match_case(self, node: ComplexDerivationTree) -> match_case:
1✔
522
        return match_case(
1✔
523
            pattern=self.visit(node.children[1]),
524
            guard=self.visit(node.children[3]),
525
            body=self.visit(node.children[5]),
526
        )
527

528
    def visit_MatchValue(self, node: ComplexDerivationTree) -> MatchValue:
1✔
529
        return MatchValue(
1✔
530
            value=self.visit(node.children[1]),
531
        )
532

533
    def visit_MatchSingleton(self, node: ComplexDerivationTree) -> MatchSingleton:
1✔
534
        return MatchSingleton(
×
535
            value=self.visit(node.children[1]),
536
        )
537

538
    def visit_MatchSequence(self, node: ComplexDerivationTree) -> MatchSequence:
1✔
539
        return MatchSequence(
×
540
            patterns=self.visit(node.children[1]),
541
        )
542

543
    def visit_MatchMapping(self, node: ComplexDerivationTree) -> MatchMapping:
1✔
544
        return MatchMapping(
×
545
            keys=self.visit(node.children[1]),
546
            patterns=self.visit(node.children[3]),
547
            rest=self.visit(node.children[5]),
548
        )
549

550
    def visit_MatchClass(self, node: ComplexDerivationTree) -> MatchClass:
1✔
551
        return MatchClass(
×
552
            cls=self.visit(node.children[1]),
553
            patterns=self.visit(node.children[3]),
554
            kwd_attrs=self.visit(node.children[5]),
555
            kwd_patterns=self.visit(node.children[7]),
556
        )
557

558
    def visit_MatchStar(self, node: ComplexDerivationTree) -> MatchStar:
1✔
559
        return MatchStar(
×
560
            name=self.visit(node.children[1]),
561
        )
562

563
    def visit_MatchAs(self, node: ComplexDerivationTree) -> MatchAs:
1✔
564
        return MatchAs(
1✔
565
            pattern=self.visit(node.children[1]),
566
            name=self.visit(node.children[3]),
567
        )
568

569
    def visit_MatchOr(self, node: ComplexDerivationTree) -> MatchOr:
1✔
570
        return MatchOr(
×
571
            patterns=self.visit(node.children[1]),
572
        )
573

574
    def visit_TypeIgnore(self, node: ComplexDerivationTree) -> TypeIgnore:
1✔
575
        return TypeIgnore(
×
576
            lineno=self.visit(node.children[1]),
577
            tag=self.visit(node.children[3]),
578
        )
579

580
    def visit_list(self, node: ComplexDerivationTree) -> list:
1✔
581
        if len(node.children) > 1:
1✔
582
            return self.visit(node.children[1])
1✔
583
        else:
584
            return list()
1✔
585

586
    def visit_elts(self, node: ComplexDerivationTree) -> list:
1✔
587
        if len(node.children) == 1:
1✔
588
            return [self.visit(node.children[0])]
1✔
589
        else:
590
            return self.visit(node.children[0]) + [self.visit(node.children[2])]
1✔
591

592
    def visit_stmt_list(self, node: ComplexDerivationTree) -> list:
1✔
593
        return self.visit_list(node)
1✔
594

595
    def visit_stmts(self, node: ComplexDerivationTree) -> list:
1✔
596
        return self.visit_elts(node)
1✔
597

598
    def visit_expr_list(self, node: ComplexDerivationTree) -> list:
1✔
599
        return self.visit_list(node)
1✔
600

601
    def visit_exprs(self, node: ComplexDerivationTree) -> list:
1✔
602
        return self.visit_elts(node)
1✔
603

604
    def visit_type_ignore_list(self, node: ComplexDerivationTree) -> list:
1✔
605
        return self.visit_list(node)
1✔
606

607
    def visit_type_ignores(self, node: ComplexDerivationTree) -> list:
1✔
608
        return self.visit_elts(node)
×
609

610
    def visit_keyword_list(self, node: ComplexDerivationTree) -> list:
1✔
611
        return self.visit_list(node)
1✔
612

613
    def visit_keywords(self, node: ComplexDerivationTree) -> list:
1✔
614
        return self.visit_elts(node)
×
615

616
    def visit_withitem_list(self, node: ComplexDerivationTree) -> list:
1✔
617
        return self.visit_list(node)
1✔
618

619
    def visit_withitems(self, node: ComplexDerivationTree) -> list:
1✔
620
        return self.visit_elts(node)
1✔
621

622
    def visit_match_case_list(self, node: ComplexDerivationTree) -> list:
1✔
623
        return self.visit_list(node)
1✔
624

625
    def visit_match_cases(self, node: ComplexDerivationTree) -> list:
1✔
626
        return self.visit_elts(node)
1✔
627

628
    def visit_excepthandler_list(self, node: ComplexDerivationTree) -> list:
1✔
629
        return self.visit_list(node)
1✔
630

631
    def visit_excepthandlers(self, node: ComplexDerivationTree) -> list:
1✔
632
        return self.visit_elts(node)
1✔
633

634
    def visit_alias_list(self, node: ComplexDerivationTree) -> list:
1✔
635
        return self.visit_list(node)
1✔
636

637
    def visit_aliases(self, node: ComplexDerivationTree) -> list:
1✔
638
        return self.visit_elts(node)
1✔
639

640
    def visit_identifier_list(self, node: ComplexDerivationTree) -> list:
1✔
641
        return self.visit_list(node)
1✔
642

643
    def visit_identifiers(self, node: ComplexDerivationTree) -> list:
1✔
644
        return self.visit_elts(node)
1✔
645

646
    def visit_comprehension_list(self, node: ComplexDerivationTree) -> list:
1✔
647
        return self.visit_list(node)
×
648

649
    def visit_comprehensions(self, node: ComplexDerivationTree) -> list:
1✔
650
        return self.visit_elts(node)
×
651

652
    def visit_cmpop_list(self, node: ComplexDerivationTree) -> list:
1✔
653
        return self.visit_list(node)
1✔
654

655
    def visit_cmpops(self, node: ComplexDerivationTree) -> list:
1✔
656
        return self.visit_elts(node)
1✔
657

658
    def visit_arg_list(self, node: ComplexDerivationTree) -> list:
1✔
659
        return self.visit_list(node)
1✔
660

661
    def visit_args(self, node: ComplexDerivationTree) -> list:
1✔
662
        return self.visit_elts(node)
1✔
663

664
    def visit_pattern_list(self, node: ComplexDerivationTree) -> list:
1✔
665
        return self.visit_list(node)
×
666

667
    def visit_patterns(self, node: ComplexDerivationTree) -> list:
1✔
668
        return self.visit_elts(node)
×
669

670
    def visit_optional(self, node: ComplexDerivationTree) -> Optional[AST]:
1✔
671
        if node.children:
1✔
672
            return self.visit(node.children[0])
1✔
673
        else:
674
            return None
1✔
675

676
    def visit_optional_expr(self, node: ComplexDerivationTree) -> Optional[AST]:
1✔
677
        return self.visit_optional(node)
1✔
678

679
    def visit_optional_string(self, node: ComplexDerivationTree) -> Optional[AST]:
1✔
680
        return self.visit_optional(node)
1✔
681

682
    def visit_optional_identifier(self, node: ComplexDerivationTree) -> Optional[AST]:
1✔
683
        return self.visit_optional(node)
1✔
684

685
    def visit_optional_int(self, node: ComplexDerivationTree) -> Optional[AST]:
1✔
686
        return self.visit_optional(node)
1✔
687

688
    def visit_optional_arg(self, node: ComplexDerivationTree) -> Optional[AST]:
1✔
689
        return self.visit_optional(node)
1✔
690

691
    def visit_optional_pattern(self, node: ComplexDerivationTree) -> Optional[AST]:
1✔
692
        return self.visit_optional(node)
1✔
693

694
    def visit_int(self, node: ComplexDerivationTree) -> int:
1✔
695
        return int(node.to_string())
1✔
696

697
    def visit_string(self, node: ComplexDerivationTree) -> str:
1✔
698
        return node.children[0].to_string()
×
699

700
    def visit_identifier(self, node: ComplexDerivationTree) -> str:
1✔
701
        return node.to_string()
1✔
702

703

704
# noinspection PyTypeChecker
705
class ToGrammarVisitor(NodeVisitor):
1✔
706
    def visit_list(self, elements, visit=True):
1✔
707
        if visit:
1✔
708
            return f'[{",".join(self.visit(e) for e in elements)}]'.replace(" ", "")
1✔
709
        else:
710
            return f'[{",".join(elements)}]'.replace(" ", "")
1✔
711

712
    def visit_Module(self, node: Module) -> str:
1✔
713
        return (
1✔
714
            f"Module({self.visit_list(node.body)},"
715
            f"{self.visit_list(node.type_ignores)})"
716
        )
717

718
    def visit_Interactive(self, node: Interactive) -> str:
1✔
719
        return f"Interactive({self.visit_list(node.body)})"
×
720

721
    def visit_Expression(self, node: Expression) -> str:
1✔
722
        return f"Expression({self.visit(node.body)})"
×
723

724
    def visit_FunctionType(self, node: FunctionType) -> str:
1✔
725
        return (
×
726
            f"FunctionType({self.visit_list(node.argtypes)},"
727
            f"{self.visit(node.returns)})"
728
        )
729

730
    def visit_FunctionDef(self, node: FunctionDef) -> str:
1✔
731
        return (
1✔
732
            f"FunctionDef({node.name},"
733
            f"{self.visit(node.args)},"
734
            f"{self.visit_list(node.body)},"
735
            f"{self.visit_list(node.decorator_list)},"
736
            f'{"" if node.returns is None else self.visit(node.returns)},'
737
            f'{"" if node.type_comment is None else self.visit(node.type_comment)})'
738
        )
739

740
    def visit_AsyncFunctionDef(self, node: AsyncFunctionDef) -> str:
1✔
741
        return (
×
742
            f"AsyncFunctionDef({node.name},"
743
            f"{self.visit(node.args)},"
744
            f"{self.visit_list(node.body)},"
745
            f"{self.visit_list(node.decorator_list)},"
746
            f'{"" if node.returns is None else self.visit(node.returns)},'
747
            f'{"" if node.type_comment is None else self.visit(node.type_comment)})'
748
        )
749

750
    def visit_ClassDef(self, node: ClassDef) -> str:
1✔
751
        return (
1✔
752
            f"ClassDef({node.name},"
753
            f"{self.visit_list(node.bases)},"
754
            f"{self.visit_list(node.keywords)},"
755
            f"{self.visit_list(node.body)},"
756
            f"{self.visit_list(node.decorator_list)})"
757
        )
758

759
    def visit_Return(self, node: Return) -> str:
1✔
760
        return f'Return({"" if node.value is None else self.visit(node.value)})'
1✔
761

762
    def visit_Delete(self, node: Delete) -> str:
1✔
763
        return f"Delete({self.visit_list(node.targets)})"
1✔
764

765
    def visit_Assign(self, node: Assign) -> str:
1✔
766
        return (
1✔
767
            f"Assign({self.visit_list(node.targets)},"
768
            f"{self.visit(node.value)},"
769
            f'{"" if node.type_comment is None else self.visit(node.type_comment)})'
770
        )
771

772
    def visit_AugAssign(self, node: AugAssign) -> str:
1✔
773
        return (
1✔
774
            f"AugAssign({self.visit(node.target)},"
775
            f"{self.visit(node.op)},"
776
            f"{self.visit(node.value)})"
777
        )
778

779
    def visit_AnnAssign(self, node: AnnAssign) -> str:
1✔
780
        return (
1✔
781
            f"AnnAssign({self.visit(node.target)},"
782
            f"{self.visit(node.annotation)},"
783
            f'{"" if node.value is None else self.visit(node.value)},'
784
            f"{node.simple})"
785
        )
786

787
    def visit_For(self, node: For) -> str:
1✔
788
        return (
1✔
789
            f"For({self.visit(node.target)},"
790
            f"{self.visit(node.iter)},"
791
            f"{self.visit_list(node.body)},"
792
            f"{self.visit_list(node.orelse)},"
793
            f'{"" if node.type_comment is None else self.visit(node.type_comment)})'
794
        )
795

796
    def visit_AsyncFor(self, node: AsyncFor) -> str:
1✔
797
        return (
×
798
            f"AsyncFor({self.visit(node.target)},"
799
            f"{self.visit(node.iter)},"
800
            f"{self.visit_list(node.body)},"
801
            f"{self.visit_list(node.orelse)},"
802
            f'{"" if node.type_comment is None else self.visit(node.type_comment)})'
803
        )
804

805
    def visit_While(self, node: While) -> str:
1✔
806
        return (
1✔
807
            f"While({self.visit(node.test)},"
808
            f"{self.visit_list(node.body)},"
809
            f"{self.visit_list(node.orelse)})"
810
        )
811

812
    def visit_If(self, node: If) -> str:
1✔
813
        return (
1✔
814
            f"If({self.visit(node.test)},"
815
            f"{self.visit_list(node.body)},"
816
            f"{self.visit_list(node.orelse)})"
817
        )
818

819
    def visit_With(self, node: With) -> str:
1✔
820
        return (
1✔
821
            f"With({self.visit_list(node.items)},"
822
            f"{self.visit_list(node.body)},"
823
            f'{"" if node.type_comment is None else self.visit(node.type_comment)})'
824
        )
825

826
    def visit_AsyncWith(self, node: AsyncWith) -> str:
1✔
827
        return (
×
828
            f"AsyncWith({self.visit_list(node.items)},"
829
            f"{self.visit_list(node.body)},"
830
            f'{"" if node.type_comment is None else self.visit(node.type_comment)})'
831
        )
832

833
    def visit_Match(self, node: Match) -> str:
1✔
834
        return f"Match({self.visit(node.subject)}," f"{self.visit_list(node.cases)})"
1✔
835

836
    def visit_Raise(self, node: Raise) -> str:
1✔
837
        return (
1✔
838
            f'Raise({"" if node.exc is None else self.visit(node.exc)},'
839
            f'{"" if node.cause is None else self.visit(node.cause)})'
840
        )
841

842
    def visit_Try(self, node: Try) -> str:
1✔
843
        return (
1✔
844
            f"Try({self.visit_list(node.body)},"
845
            f"{self.visit_list(node.handlers)},"
846
            f"{self.visit_list(node.orelse)},"
847
            f"{self.visit_list(node.finalbody)})"
848
        )
849

850
    def visit_Assert(self, node: Assert) -> str:
1✔
851
        return (
1✔
852
            f"Assert({self.visit(node.test)},"
853
            f'{"" if node.msg is None else self.visit(node.msg)})'
854
        )
855

856
    def visit_Import(self, node: Import) -> str:
1✔
857
        return f"Import({self.visit_list(node.names)})"
1✔
858

859
    def visit_ImportFrom(self, node: ImportFrom) -> str:
1✔
860
        return (
1✔
861
            f'ImportFrom({"" if node.module is None else node.module},'
862
            f"{self.visit_list(node.names)},"
863
            f'{"" if node.level is None else node.level})'
864
        )
865

866
    def visit_Global(self, node: Global) -> str:
1✔
867
        return f"Global({self.visit_list(node.names, visit=False)})"
1✔
868

869
    def visit_Nonlocal(self, node: Nonlocal) -> str:
1✔
870
        return f"Nonlocal({self.visit_list(node.names)})"
×
871

872
    def visit_Expr(self, node: Expr) -> str:
1✔
873
        return f"Expr({self.visit(node.value)})"
1✔
874

875
    def visit_Pass(self, node: Pass) -> str:
1✔
876
        return f"Pass()"
1✔
877

878
    def visit_Break(self, node: Break) -> str:
1✔
879
        return f"Break()"
1✔
880

881
    def visit_Continue(self, node: Continue) -> str:
1✔
882
        return f"Continue()"
1✔
883

884
    def visit_BoolOp(self, node: BoolOp) -> str:
1✔
885
        return f"BoolOp({self.visit(node.op)}," f"{self.visit_list(node.values)})"
×
886

887
    def visit_NamedExpr(self, node: NamedExpr) -> str:
1✔
888
        return f"NamedExpr({self.visit(node.target)}," f"{self.visit(node.value)})"
×
889

890
    def visit_BinOp(self, node: BinOp) -> str:
1✔
891
        return (
1✔
892
            f"BinOp({self.visit(node.left)},"
893
            f"{self.visit(node.op)},"
894
            f"{self.visit(node.right)})"
895
        )
896

897
    def visit_UnaryOp(self, node: UnaryOp) -> str:
1✔
898
        return f"UnaryOp({self.visit(node.op)}," f"{self.visit(node.operand)})"
1✔
899

900
    def visit_Lambda(self, node: Lambda) -> str:
1✔
901
        return f"Lambda({self.visit(node.args)}," f"{self.visit(node.body)})"
×
902

903
    def visit_IfExp(self, node: IfExp) -> str:
1✔
904
        return (
×
905
            f"IfExp({self.visit(node.test)},"
906
            f"{self.visit(node.body)},"
907
            f"{self.visit(node.orelse)})"
908
        )
909

910
    def visit_Dict(self, node: Dict) -> str:
1✔
911
        return f"Dict({self.visit_list(node.keys)}," f"{self.visit_list(node.values)})"
1✔
912

913
    def visit_Set(self, node: Set) -> str:
1✔
914
        return f"Set({self.visit_list(node.elts)})"
×
915

916
    def visit_ListComp(self, node: ListComp) -> str:
1✔
917
        return (
×
918
            f"ListComp({self.visit(node.elt)}," f"{self.visit_list(node.generators)})"
919
        )
920

921
    def visit_SetComp(self, node: SetComp) -> str:
1✔
922
        return f"SetComp({self.visit(node.elt)}," f"{self.visit_list(node.generators)})"
×
923

924
    def visit_DictComp(self, node: DictComp) -> str:
1✔
925
        return (
×
926
            f"ListComp({self.visit(node.key)},"
927
            f"{self.visit(node.value)},"
928
            f"{self.visit_list(node.generators)})"
929
        )
930

931
    def visit_GeneratorExp(self, node: GeneratorExp) -> str:
1✔
932
        return (
×
933
            f"GeneratorExp({self.visit(node.elt)},"
934
            f"{self.visit_list(node.generators)})"
935
        )
936

937
    def visit_Await(self, node: Await) -> str:
1✔
938
        return f"Await({self.visit(node.value)})"
×
939

940
    def visit_Yield(self, node: Yield) -> str:
1✔
941
        return f'Yield({"" if node.value is None else self.visit(node.value)})'
×
942

943
    def visit_YieldFrom(self, node: YieldFrom) -> str:
1✔
944
        return f"YieldFrom({self.visit(node.value)})"
×
945

946
    def visit_Compare(self, node: Compare) -> str:
1✔
947
        return (
1✔
948
            f"Compare({self.visit(node.left)},"
949
            f"{self.visit_list(node.ops)},"
950
            f"{self.visit_list(node.comparators)})"
951
        )
952

953
    def visit_Call(self, node: Call) -> str:
1✔
954
        return (
1✔
955
            f"Call({self.visit(node.func)},"
956
            f"{self.visit_list(node.args)},"
957
            f"{self.visit_list(node.keywords)})"
958
        )
959

960
    def visit_FormattedValue(self, node: FormattedValue) -> str:
1✔
961
        return (
×
962
            f"FormattedValue({self.visit(node.value)},"
963
            f"{node.conversion},"
964
            f'{"" if node.format_spec is None else self.visit(node.format_spec)})'
965
        )
966

967
    def visit_JoinedStr(self, node: JoinedStr) -> str:
1✔
968
        return f"JoinedStr({self.visit_list(node.values)})"
×
969

970
    def visit_Constant(self, node: Constant) -> str:
1✔
971
        return (
1✔
972
            f"Constant({repr(node.value)}," f'{"" if node.kind is None else node.kind})'
973
        )
974

975
    def visit_Attribute(self, node: Attribute) -> str:
1✔
976
        return f"Attribute({self.visit(node.value)}," f"{node.attr})"
1✔
977

978
    def visit_Subscript(self, node: Subscript) -> str:
1✔
979
        return f"Subscript({self.visit(node.value)}," f"{self.visit(node.slice)})"
1✔
980

981
    def visit_Starred(self, node: Starred) -> str:
1✔
982
        return f"Starred({self.visit(node.value)}," f"{self.visit(node.ctx)})"
×
983

984
    def visit_Name(self, node: Name) -> str:
1✔
985
        return f"Name({node.id})"
1✔
986

987
    def visit_List(self, node: List) -> str:
1✔
988
        return f"List({self.visit_list(node.elts)})"
1✔
989

990
    def visit_Tuple(self, node: Tuple) -> str:
1✔
991
        return f"Tuple({self.visit_list(node.elts)})"
1✔
992

993
    def visit_Slice(self, node: Slice) -> str:
1✔
994
        return (
1✔
995
            f'Slice({"" if node.lower is None else self.visit(node.lower)},'
996
            f'{"" if node.upper is None else self.visit(node.upper)},'
997
            f'{"" if node.step is None else self.visit(node.step)})'
998
        )
999

1000
    # def visit_Load(self, node: Load) -> str:
1001
    #     return 'Load()'
1002
    #
1003
    # def visit_Store(self, node: Store) -> str:
1004
    #     return 'Store()'
1005

1006
    def visit_Del(self, node: Del) -> str:
1✔
1007
        return "Del()"
×
1008

1009
    def visit_And(self, node: And) -> str:
1✔
1010
        return "And()"
×
1011

1012
    def visit_Or(self, node: Or) -> str:
1✔
1013
        return "Or()"
×
1014

1015
    def visit_Add(self, node: Add) -> str:
1✔
1016
        return "Add()"
1✔
1017

1018
    def visit_Sub(self, node: Sub) -> str:
1✔
1019
        return "Sub()"
×
1020

1021
    def visit_Mult(self, node: Mult) -> str:
1✔
1022
        return "Mult()"
×
1023

1024
    def visit_MatMult(self, node: MatMult) -> str:
1✔
1025
        return "MatMult()"
×
1026

1027
    def visit_Div(self, node: Div) -> str:
1✔
1028
        return "Div()"
×
1029

1030
    def visit_Mod(self, node: Mod) -> str:
1✔
1031
        return "Mod()"
×
1032

1033
    def visit_Pow(self, node: Pow) -> str:
1✔
1034
        return "Pow()"
×
1035

1036
    def visit_LShift(self, node: LShift) -> str:
1✔
1037
        return "LShift()"
×
1038

1039
    def visit_RShift(self, node: RShift) -> str:
1✔
1040
        return "RShift()"
×
1041

1042
    def visit_BitOr(self, node: BitOr) -> str:
1✔
1043
        return "BitOr()"
×
1044

1045
    def visit_BitXor(self, node: BitXor) -> str:
1✔
1046
        return "BitXor()"
1✔
1047

1048
    def visit_BitAnd(self, node: BitAnd) -> str:
1✔
1049
        return "BitAnd()"
1✔
1050

1051
    def visit_FloorDiv(self, node: FloorDiv) -> str:
1✔
1052
        return "FloorDiv()"
×
1053

1054
    def visit_Invert(self, node: Invert) -> str:
1✔
1055
        return "Invert()"
×
1056

1057
    def visit_Not(self, node: Not) -> str:
1✔
1058
        return "Not()"
×
1059

1060
    def visit_UAdd(self, node: UAdd) -> str:
1✔
1061
        return "UAdd()"
×
1062

1063
    def visit_USub(self, node: USub) -> str:
1✔
1064
        return "USub()"
1✔
1065

1066
    def visit_Eq(self, node: Eq) -> str:
1✔
1067
        return "Eq()"
1✔
1068

1069
    def visit_NotEq(self, node: NotEq) -> str:
1✔
1070
        return "NotEq()"
×
1071

1072
    def visit_Lt(self, node: Lt) -> str:
1✔
1073
        return "Lt()"
1✔
1074

1075
    def visit_LtE(self, node: LtE) -> str:
1✔
1076
        return "LtE()"
×
1077

1078
    def visit_Gt(self, node: Gt) -> str:
1✔
1079
        return "Gt()"
×
1080

1081
    def visit_GtE(self, node: GtE) -> str:
1✔
1082
        return "GtE()"
×
1083

1084
    def visit_Is(self, node: Is) -> str:
1✔
1085
        return "Is()"
×
1086

1087
    def visit_IsNot(self, node: IsNot) -> str:
1✔
1088
        return "IsNot()"
×
1089

1090
    def visit_In(self, node: In) -> str:
1✔
1091
        return "In()"
×
1092

1093
    def visit_NotIn(self, node: NotIn) -> str:
1✔
1094
        return "NotIn()"
×
1095

1096
    def visit_comprehension(self, node: comprehension) -> str:
1✔
1097
        return (
×
1098
            f"comprehension({self.visit(node.target)},"
1099
            f"{self.visit(node.iter)},"
1100
            f"{self.visit_list(node.ifs)},"
1101
            f"{node.is_async})"
1102
        )
1103

1104
    def visit_ExceptHandler(self, node: ExceptHandler) -> str:
1✔
1105
        return (
1✔
1106
            f'ExceptHandler({"" if node.type is None else self.visit(node.type)},'
1107
            f'{"" if node.name is None else node.name},'
1108
            f"{self.visit_list(node.body)})"
1109
        )
1110

1111
    def visit_arguments(self, node: arguments) -> str:
1✔
1112
        return (
1✔
1113
            f"arguments({self.visit_list(node.posonlyargs)},"
1114
            f"{self.visit_list(node.args)},"
1115
            f'{"" if node.vararg is None else self.visit(node.vararg)},'
1116
            f"{self.visit_list(node.kwonlyargs)},"
1117
            f"{self.visit_list(node.kw_defaults)},"
1118
            f'{"" if node.kwarg is None else self.visit(node.kwarg)},'
1119
            f"{self.visit_list(node.defaults)})"
1120
        )
1121

1122
    def visit_arg(self, node: arg) -> str:
1✔
1123
        return (
1✔
1124
            f"arg({node.arg},"
1125
            f'{"" if node.annotation is None else self.visit(node.annotation)},'
1126
            f'{"" if node.type_comment is None else self.visit(node.type_comment)})'
1127
        )
1128

1129
    def visit_keyword(self, node: keyword) -> str:
1✔
1130
        return (
×
1131
            f'keyword({"" if node.arg is None else node.arg},'
1132
            f"{self.visit(node.value)})"
1133
        )
1134

1135
    def visit_alias(self, node: alias) -> str:
1✔
1136
        return (
1✔
1137
            f"alias({node.name},"
1138
            f'{"" if node.asname is None else self.visit(node.asname)})'
1139
        )
1140

1141
    def visit_withitem(self, node: withitem) -> str:
1✔
1142
        return (
1✔
1143
            f"withitem({self.visit(node.context_expr)},"
1144
            f'{"" if node.optional_vars is None else self.visit(node.optional_vars)})'
1145
        )
1146

1147
    def visit_match_case(self, node: match_case) -> str:
1✔
1148
        return (
1✔
1149
            f"match_case({self.visit(node.pattern)},"
1150
            f'{"" if node.guard is None else self.visit(node.guard)},'
1151
            f"{self.visit_list(node.body)})"
1152
        )
1153

1154
    def visit_MatchValue(self, node: MatchValue) -> str:
1✔
1155
        return f"MatchValue({self.visit(node.value)})"
1✔
1156

1157
    def visit_MatchSingleton(self, node: MatchSingleton) -> str:
1✔
1158
        return f"MatchSingleton({self.visit(node.value)})"
×
1159

1160
    def visit_MatchSequence(self, node: MatchSequence) -> str:
1✔
1161
        return f"Await({self.visit_list(node.patterns)})"
×
1162

1163
    def visit_MatchMapping(self, node: MatchMapping) -> str:
1✔
1164
        return (
×
1165
            f"MatchMapping({self.visit_list(node.keys)},"
1166
            f"{self.visit_list(node.patterns)},"
1167
            f'{"" if node.rest is None else self.visit(node.rest)})'
1168
        )
1169

1170
    def visit_MatchClass(self, node: MatchClass) -> str:
1✔
1171
        return (
×
1172
            f"Await({self.visit(node.cls)},"
1173
            f"{self.visit_list(node.patterns)},"
1174
            f"{self.visit_list(node.kwd_attrs)},"
1175
            f"{self.visit_list(node.kwd_patterns)})"
1176
        )
1177

1178
    def visit_MatchStar(self, node: MatchStar) -> str:
1✔
1179
        return f'MatchStar({"" if node.name is None else self.visit(node.name)})'
×
1180

1181
    def visit_MatchAs(self, node: MatchAs) -> str:
1✔
1182
        return (
1✔
1183
            f'MatchAs({"" if node.pattern is None else self.visit(node.pattern)},'
1184
            f'{"" if node.name is None else self.visit(node.name)})'
1185
        )
1186

1187
    def visit_MatchOr(self, node: MatchOr) -> str:
1✔
1188
        return f"MatchOr({self.visit_list(node.patterns)})"
×
1189

1190
    @staticmethod
1✔
1191
    def visit_TypeIgnore(node: TypeIgnore) -> str:
1✔
1192
        return f"TypeIgnore({node.lineno}," f'"{node.tag}")'
×
1193

1194

1195
class PythonGenerator(Generator):
1✔
1196
    class Scope:
1✔
1197
        def __init__(self, parent=None):
1✔
1198
            self.variables = set()
1✔
1199
            self.functions = dict()
1✔
1200
            self.parent = parent
1✔
1201

1202
        def enter(self):
1✔
1203
            return PythonGenerator.Scope(self)
1✔
1204

1205
        def exit(self):
1✔
1206
            return self.parent if self.parent else self
1✔
1207

1208
        def add_variable(self, variable: str):
1✔
1209
            self.variables.add(variable)
1✔
1210

1211
        def add_function(self, function: str, args: int):
1✔
1212
            self.functions[function] = args
1✔
1213

1214
        def get_variables(self) -> set:
1✔
1215
            return (
1✔
1216
                self.variables.union(self.parent.get_variables())
1217
                if self.parent
1218
                else self.variables
1219
            )
1220

1221
        def get_variable(self) -> Optional[str]:
1✔
1222
            variables = self.get_variables()
1✔
1223
            if variables:
1✔
1224
                return random.choice(tuple(variables))
1✔
1225
            else:
1226
                return None
1✔
1227

1228
        def get_functions(self) -> dict:
1✔
1229
            if self.parent:
1✔
1230
                functions = self.parent.get_functions()
1✔
1231
                functions.update(self.functions)
1✔
1232
                return functions
1✔
1233
            else:
1234
                return dict(self.functions)
1✔
1235

1236
        def get_function(self) -> tuple[Optional[str], int]:
1✔
1237
            functions = self.get_functions()
1✔
1238
            if functions:
1✔
1239
                selection = random.choice(tuple(functions.keys()))
1✔
1240
                return selection, functions[selection]
1✔
1241
            else:
1242
                return None, 0
1✔
1243

1244
        def get_args(self, function: str) -> Optional[int]:
1✔
1245
            functions = self.get_functions()
×
1246
            if function in functions:
×
1247
                return functions[function]
×
1248
            else:
1249
                return None
×
1250

1251
    def __init__(
1✔
1252
        self,
1253
        limit_stmt_per_block=10,
1254
        limit_stmt_depth=4,
1255
        limit_expr_depth=4,
1256
        limit_args_per_function=4,
1257
        limit_assign_target=1,
1258
    ):
1259
        self.limit_expr_depth = limit_expr_depth
1✔
1260
        self.limit_stmt_depth = limit_stmt_depth
1✔
1261
        self.limit_assign_target = limit_assign_target
1✔
1262
        self.limit_stmt_per_block = limit_stmt_per_block
1✔
1263
        self.limit_args_per_function = limit_args_per_function
1✔
1264
        self.is_in_function = False
1✔
1265
        self.stmt_depth = 0
1✔
1266
        self.expr_depth = 0
1✔
1267
        self.scope = PythonGenerator.Scope()
1✔
1268
        self.identifier_fuzzer = GrammarFuzzer(
1✔
1269
            GENERATIVE_GRAMMAR, start_symbol="<identifier>"
1270
        )
1271

1272
    def reset(self):
1✔
1273
        self.scope = PythonGenerator.Scope()
1✔
1274
        self.is_in_function = False
1✔
1275
        self.stmt_depth = 0
1✔
1276
        self.expr_depth = 0
1✔
1277

1278
    def enter_scope(self):
1✔
1279
        self.scope = self.scope.enter()
1✔
1280

1281
    def exit_scope(self):
1✔
1282
        self.scope = self.scope.exit()
1✔
1283

1284
    def generate(self):
1✔
1285
        return ast.unparse(self.generate_ast())
1✔
1286

1287
    def _generate_Module(self) -> Module:
1✔
1288
        return Module(body=self._generate_stmt_list(), type_ignores=[])
1✔
1289

1290
    def _generate_stmt_list(self) -> list[stmt]:
1✔
1291
        stmts = [
1✔
1292
            self._generate_stmt()
1293
            for _ in range(random.randint(0, self.limit_stmt_per_block))
1294
        ]
1295
        if len(stmts) > 0:
1✔
1296
            return stmts
1✔
1297
        else:
1298
            return [self._generate_Pass()]
1✔
1299

1300
    def _generate_stmt(self) -> stmt:
1✔
1301
        choices = [
1✔
1302
            self._generate_Assign,
1303
            self._generate_Expr,
1304
            self._generate_Pass,
1305
        ]
1306
        if self.stmt_depth < self.limit_stmt_depth:
1✔
1307
            choices += [
1✔
1308
                self._generate_FunctionDef,
1309
                self._generate_If,
1310
            ]
1311
        if self.is_in_function:
1✔
1312
            choices.append(self._generate_Return)
1✔
1313
        self.stmt_depth += 1
1✔
1314
        stmt_ = random.choice(choices)()
1✔
1315
        self.stmt_depth -= 1
1✔
1316
        return stmt_
1✔
1317

1318
    def _generate_FunctionDef(self, num_args: Optional[int] = None) -> FunctionDef:
1✔
1319
        name = self._generate_identifier()
1✔
1320
        self.enter_scope()
1✔
1321
        args = self._generate_arguments(num_args)
1✔
1322
        prev = self.is_in_function
1✔
1323
        self.is_in_function = True
1✔
1324
        body = self._generate_stmt_list()
1✔
1325
        self.is_in_function = prev
1✔
1326
        return_ = self._generate_Return()
1✔
1327
        self.exit_scope()
1✔
1328
        self.scope.add_function(name, len(args.args))
1✔
1329
        return FunctionDef(
1✔
1330
            name=name,
1331
            args=args,
1332
            body=body + [return_],
1333
            decorator_list=[],
1334
            lineno=0,
1335
        )
1336

1337
    def _generate_If(self) -> If:
1✔
1338
        self.enter_scope()
1✔
1339
        body = self._generate_stmt_list()
1✔
1340
        self.exit_scope()
1✔
1341
        self.enter_scope()
1✔
1342
        orelse = self._generate_stmt_list()
1✔
1343
        self.exit_scope()
1✔
1344
        return If(
1✔
1345
            test=self._generate_expr(),
1346
            body=body,
1347
            orelse=orelse,
1348
        )
1349

1350
    def _generate_Assign(self) -> Assign:
1✔
1351
        targets = self._generate_targets()
1✔
1352
        if len(targets) > 1:
1✔
1353
            value = Tuple(elts=[self._generate_expr() for _ in range(len(targets))])
×
1354
        else:
1355
            value = self._generate_expr()
1✔
1356
        return Assign(
1✔
1357
            targets=targets,
1358
            value=value,
1359
            lineno=0,
1360
        )
1361

1362
    def _generate_Expr(self) -> Expr:
1✔
1363
        return Expr(value=self._generate_expr())
1✔
1364

1365
    @staticmethod
1✔
1366
    def _generate_Pass() -> Pass:
1✔
1367
        return Pass()
1✔
1368

1369
    def _generate_Return(self) -> Return:
1✔
1370
        return Return(value=self._generate_expr())
1✔
1371

1372
    def _generate_identifier(self) -> str:
1✔
1373
        identifier = self.identifier_fuzzer.fuzz()
1✔
1374
        while identifier in [
1✔
1375
            "as",
1376
            "def",
1377
            "in",
1378
            "is",
1379
            "not",
1380
            "if",
1381
            "match",
1382
            "case",
1383
            "class",
1384
            "while",
1385
            "for",
1386
            "else",
1387
            "try",
1388
            "finally",
1389
            "except",
1390
            "or",
1391
            "and",
1392
        ]:
1393
            identifier = self.identifier_fuzzer.fuzz()
×
1394
        return identifier
1✔
1395

1396
    def _generate_arguments(self, num_args: Optional[int] = None) -> arguments:
1✔
1397
        return arguments(
1✔
1398
            args=[
1399
                self._generate_arg()
1400
                for _ in range(
1401
                    random.randint(0, self.limit_args_per_function)
1402
                    if num_args is None
1403
                    else num_args
1404
                )
1405
            ],
1406
            posonlyargs=[],
1407
            defaults=[],
1408
            kwonlyargs=[],
1409
            kw_defaults=[],
1410
        )
1411

1412
    def _generate_expr(self) -> expr:
1✔
1413
        choices = [
1✔
1414
            self._generate_Constant,
1415
            self._generate_Name,
1416
        ]
1417
        if self.expr_depth < self.limit_expr_depth:
1✔
1418
            choices += [
1✔
1419
                self._generate_BoolOp,
1420
                self._generate_BinOp,
1421
                self._generate_UnaryOp,
1422
                self._generate_Compare,
1423
                self._generate_Call,
1424
            ]
1425
        self.expr_depth += 1
1✔
1426
        expr_ = random.choice(choices)()
1✔
1427
        self.expr_depth -= 1
1✔
1428
        return expr_
1✔
1429

1430
    def _generate_targets(self) -> list[Name]:
1✔
1431
        return [
1✔
1432
            Name(id=self._generate_identifier())
1433
            for _ in range(0, 1 + random.randrange(0, self.limit_assign_target))
1434
        ]
1435

1436
    def _generate_arg(self) -> arg:
1✔
1437
        identifier = self._generate_identifier()
1✔
1438
        while identifier in self.scope.variables:
1✔
UNCOV
1439
            identifier = self._generate_identifier()
×
1440
        self.scope.add_variable(identifier)
1✔
1441
        return arg(arg=identifier)
1✔
1442

1443
    def _generate_BoolOp(self) -> BoolOp:
1✔
1444
        return BoolOp(
1✔
1445
            op=random.choice((And(), Or())),
1446
            values=[self._generate_expr(), self._generate_expr()],
1447
        )
1448

1449
    def _generate_BinOp(self) -> BinOp:
1✔
1450
        return BinOp(
1✔
1451
            left=self._generate_expr(),
1452
            op=random.choice((Add(), Sub(), Mult())),
1453
            right=self._generate_expr(),
1454
        )
1455

1456
    def _generate_UnaryOp(self) -> UnaryOp:
1✔
1457
        return UnaryOp(
1✔
1458
            op=random.choice((Not(), UAdd(), USub())), operand=self._generate_expr()
1459
        )
1460

1461
    def _generate_Compare(self) -> Compare:
1✔
1462
        return Compare(
1✔
1463
            left=self._generate_expr(),
1464
            ops=[random.choice((Eq(), NotEq(), Lt(), LtE(), Gt(), GtE()))],
1465
            comparators=[self._generate_expr()],
1466
        )
1467

1468
    def _generate_Call(self, function: Optional[str] = None) -> Union[Call | expr]:
1✔
1469
        num_args = None
1✔
1470
        if function:
1✔
1471
            num_args = self.scope.get_args(function)
×
1472
        if num_args is None:
1✔
1473
            function, num_args = self.scope.get_function()
1✔
1474
        if function:
1✔
1475
            return Call(
1✔
1476
                func=Name(id=function),
1477
                args=[self._generate_expr() for _ in range(num_args)],
1478
                keywords=[],
1479
            )
1480
        else:
1481
            return self._generate_expr()
1✔
1482

1483
    @staticmethod
1✔
1484
    def _generate_Constant() -> Constant:
1✔
1485
        return Constant(value=random.randint(0, 10))
1✔
1486

1487
    def _generate_Name(self) -> Union[Name | Constant]:
1✔
1488
        variable = self.scope.get_variable()
1✔
1489
        if variable:
1✔
1490
            return Name(id=variable)
1✔
1491
        else:
1492
            return self._generate_Constant()
1✔
1493

1494
    def generate_ast(self) -> AST:
1✔
1495
        return self._generate_Module()
1✔
1496

1497

1498
GRAMMAR: Grammar = {
1✔
1499
    "<start>": ["<mod>"],
1500
    "<mod>": ["<Module>", "<Interactive>", "<Expression>", "<FunctionType>"],
1501
    "<Module>": ["Module(<stmt_list>,<type_ignore_list>)"],
1502
    "<Interactive>": ["Interactive(<stmt_list>)"],
1503
    "<Expression>": ["Expression(<expr>)"],
1504
    "<FunctionType>": ["FunctionType(<expr_list>,<expr>)"],
1505
    # Lists
1506
    "<stmt_list>": ["[]", "[<stmts>]"],
1507
    "<stmts>": ["<stmt>", "<stmts>,<stmt>"],
1508
    "<expr_list>": ["[]", "[<exprs>]"],
1509
    "<exprs>": ["<expr>", "<exprs>,<expr>"],
1510
    "<type_ignore_list>": ["[]", "[<type_ignores>]"],
1511
    "<type_ignores>": ["<type_ignore>", "<type_ignores>,<type_ignore>"],
1512
    "<keyword_list>": ["[]", "[<keywords>]"],
1513
    "<keywords>": ["<keyword>", "<keywords>,<keyword>"],
1514
    "<withitem_list>": ["[]", "[<withitems>]"],
1515
    "<withitems>": ["<withitem>", "<withitems>,<withitem>"],
1516
    "<match_case_list>": ["[]", "[<match_cases>]"],
1517
    "<match_cases>": ["<match_case>", "<match_cases>,<match_case>"],
1518
    "<excepthandler_list>": ["[]", "[<excepthandlers>]"],
1519
    "<excepthandlers>": ["<excepthandler>", "<excepthandlers>,<excepthandler>"],
1520
    "<alias_list>": ["[]", "[<aliases>]"],
1521
    "<aliases>": ["<alias>", "<aliases>,<alias>"],
1522
    "<identifier_list>": ["[]", "[<identifiers>]"],
1523
    "<identifiers>": ["<identifier>", "<identifiers>,<identifier>"],
1524
    "<comprehension_list>": ["[]", "[<comprehensions>]"],
1525
    "<comprehensions>": ["<comprehension>", "<comprehensions>,<comprehension>"],
1526
    "<cmpop_list>": ["[]", "[<cmpops>]"],
1527
    "<cmpops>": ["<cmpop>", "<cmpops>,<cmpop>"],
1528
    "<arg_list>": ["[]", "[<args>]"],
1529
    "<args>": ["<arg>", "<args>,<arg>"],
1530
    "<pattern_list>": ["[]", "[<patterns>]"],
1531
    "<patterns>": ["<pattern>", "<patterns>,<pattern>"],
1532
    # Optionals
1533
    "<optional_expr>": ["", "<expr>"],
1534
    "<optional_string>": ["", "<string>"],
1535
    "<optional_identifier>": ["", "<identifier>"],
1536
    "<optional_int>": ["", "<int>"],
1537
    "<optional_arg>": ["", "<arg>"],
1538
    "<optional_pattern>": ["", "<pattern>"],
1539
    # Statements
1540
    "<stmt>": [
1541
        "<FunctionDef>",
1542
        "<AsyncFunctionDef>",
1543
        "<ClassDef>",
1544
        "<Return>",
1545
        "<Delete>",
1546
        "<Assign>",
1547
        "<AugAssign>",
1548
        "<AnnAssign>",
1549
        "<For>",
1550
        "<AsyncFor>",
1551
        "<While>",
1552
        "<If>",
1553
        "<With>",
1554
        "<AsyncWith>",
1555
        "<Match>",
1556
        "<Raise>",
1557
        "<Try>",
1558
        # '<TryStar>',
1559
        "<Assert>",
1560
        "<Import>",
1561
        "<ImportFrom>",
1562
        "<Global>",
1563
        "<Nonlocal>",
1564
        "<Expr>",
1565
        "<Pass>",
1566
        "<Break>",
1567
        "<Continue>",
1568
    ],
1569
    "<FunctionDef>": [
1570
        "FunctionDef(<identifier>,<arguments>,<stmt_list>,<expr_list>,<optional_expr>,<optional_string>)",
1571
    ],
1572
    "<AsyncFunctionDef>": [
1573
        "AsyncFunctionDef(<identifier>,<arguments>,<stmt_list>,<expr_list>,<optional_expr>,<optional_string>)",
1574
    ],
1575
    "<ClassDef>": [
1576
        "ClassDef(<identifier>,<expr_list>,<keyword_list>,<stmt_list>,<expr_list>)",
1577
    ],
1578
    "<Return>": [
1579
        "Return(<optional_expr>)",
1580
    ],
1581
    "<Delete>": [
1582
        "Delete(<expr_list>)",
1583
    ],
1584
    "<Assign>": [
1585
        "Assign(<expr_list>,<expr>,<optional_string>)",
1586
    ],
1587
    "<AugAssign>": [
1588
        "AugAssign(<expr>,<operator>,<expr>)",
1589
    ],
1590
    "<AnnAssign>": [
1591
        "AnnAssign(<expr>,<expr>,<optional_expr>,<int>)",
1592
    ],
1593
    "<For>": [
1594
        "For(<expr>,<expr>,<stmt_list>,<stmt_list>,<optional_string>)",
1595
    ],
1596
    "<AsyncFor>": [
1597
        "AsyncFor(<expr>,<expr>,<stmt_list>,<stmt_list>,<optional_string>)",
1598
    ],
1599
    "<While>": ["While(<expr>,<stmt_list>,<stmt_list>)"],
1600
    "<If>": ["If(<expr>,<stmt_list>,<stmt_list>)"],
1601
    "<With>": [
1602
        "With(<withitem_list>,<stmt_list>,<optional_string>)",
1603
    ],
1604
    "<AsyncWith>": [
1605
        "AsyncWith(<withitem_list>,<stmt_list>,<optional_string>)",
1606
    ],
1607
    "<Match>": ["Match(<expr>,<match_case_list>)"],
1608
    "<Raise>": [
1609
        "Raise(<optional_expr>,<optional_expr>)",
1610
    ],
1611
    "<Try>": ["Try(<stmt_list>,<excepthandler_list>,<stmt_list>,<stmt_list>)"],
1612
    # '<TryStar>': [
1613
    #     'TryStar(<stmt_list>,<excepthandler_list>,<stmt_list>,<stmt_list>)'
1614
    # ],
1615
    "<Assert>": [
1616
        "Assert(<expr>,<optional_expr>)",
1617
    ],
1618
    "<Import>": [
1619
        "Import(<alias_list>)",
1620
    ],
1621
    "<ImportFrom>": [
1622
        "ImportFrom(<optional_identifier>,<alias_list>,<optional_int>)",
1623
    ],
1624
    "<Global>": [
1625
        "Global(<identifier_list>)",
1626
    ],
1627
    "<Nonlocal>": [
1628
        "Nonlocal(<identifier_list>)",
1629
    ],
1630
    "<Expr>": [
1631
        "Expr(<expr>)",
1632
    ],
1633
    "<Pass>": [
1634
        "Pass()",
1635
    ],
1636
    "<Break>": [
1637
        "Break()",
1638
    ],
1639
    "<Continue>": [
1640
        "Continue()",
1641
    ],
1642
    # Expressions
1643
    "<expr>": [
1644
        "<BoolOp>",
1645
        "<NamedExpr>",
1646
        "<BinOp>",
1647
        "<UnaryOp>",
1648
        "<Lambda>",
1649
        "<IfExp>",
1650
        "<Dict>",
1651
        "<Set>",
1652
        "<ListComp>",
1653
        "<SetComp>",
1654
        "<DictComp>",
1655
        "<GeneratorExp>",
1656
        "<Await>",
1657
        "<Yield>",
1658
        "<YieldFrom>",
1659
        "<Compare>",
1660
        "<Call>",
1661
        "<FormattedValue>",
1662
        "<JoinedStr>",
1663
        "<Constant>",
1664
        "<Attribute>",
1665
        "<Subscript>",
1666
        "<Starred>",
1667
        "<Name>",
1668
        "<List>",
1669
        "<Tuple>",
1670
    ],
1671
    "<BoolOp>": ["BoolOp(<boolop>,<expr_list>)"],
1672
    "<NamedExpr>": ["NamedExpr(<expr>,<expr>)"],
1673
    "<BinOp>": ["BinOp(<expr>,<operator>,<expr>)"],
1674
    "<UnaryOp>": ["UnaryOp(<unaryop>,<expr>)"],
1675
    "<Lambda>": ["Lambda(<arguments>,<expr>)"],
1676
    "<IfExp>": ["IfExp(<expr>,<expr>,<expr>)"],
1677
    "<Dict>": ["Dict(<expr_list>,<expr_list>)"],
1678
    "<Set>": ["Set(<expr_list>)"],
1679
    "<ListComp>": ["ListComp(<expr>,<comprehension_list>)"],
1680
    "<SetComp>": ["SetComp(<expr>,<comprehension_list>)"],
1681
    "<DictComp>": ["DictComp(<expr>,<expr>,<comprehension_list>)"],
1682
    "<GeneratorExp>": ["GeneratorExp(<expr>,<comprehension_list>)"],
1683
    "<Await>": ["Await(<expr>)"],
1684
    "<Yield>": [
1685
        "Yield(<optional_expr>)",
1686
    ],
1687
    "<YieldFrom>": [
1688
        "YieldFrom(<optional_expr>)",
1689
    ],
1690
    "<Compare>": ["Compare(<expr>,<cmpop_list>,<expr_list>)"],
1691
    "<Call>": ["Call(<expr>,<expr_list>,<keyword_list>)"],
1692
    "<FormattedValue>": ["FormattedValue(<expr>,<int>,<optional_expr>)"],
1693
    "<JoinedStr>": ["JoinedStr(<expr_list>)"],
1694
    "<Constant>": [
1695
        "Constant(<constant>,<optional_string>)",
1696
    ],
1697
    "<Attribute>": ["Attribute(<expr>,<identifier>)"],
1698
    "<Subscript>": ["Subscript(<expr>,<expr>)", "Subscript(<expr>,<Slice>)"],
1699
    "<Starred>": ["Starred(<expr>)"],
1700
    "<Name>": ["Name(<identifier>)"],
1701
    "<List>": ["List(<expr_list>)"],
1702
    "<Tuple>": ["Tuple(<expr_list>)"],
1703
    "<Slice>": [
1704
        "Slice(<optional_expr>,<optional_expr>,<optional_expr>)",
1705
    ],
1706
    # Contexts
1707
    # '<expr_context>': [
1708
    #    '<Load>',
1709
    #    '<Store>',
1710
    #    '<Del>',
1711
    # ],
1712
    # '<Load>': ['Load()'],
1713
    # '<Store>': ['Store()'],
1714
    # '<Del>': ['Del()'],
1715
    # Operators
1716
    "<boolop>": [
1717
        "<And>",
1718
        "<Or>",
1719
    ],
1720
    "<And>": ["And()"],
1721
    "<Or>": ["Or()"],
1722
    "<operator>": [
1723
        "<Add>",
1724
        "<Sub>",
1725
        "<Mult>",
1726
        "<MatMult>",
1727
        "<Div>",
1728
        "<Mod>",
1729
        "<Pow>",
1730
        "<LShift>",
1731
        "<RShift>",
1732
        "<BitOr>",
1733
        "<BitXor>",
1734
        "<BitAnd>",
1735
        "<FloorDiv>",
1736
    ],
1737
    "<Add>": ["Add()"],
1738
    "<Sub>": ["Sub()"],
1739
    "<Mult>": ["Mult()"],
1740
    "<MatMult>": ["MatMult()"],
1741
    "<Div>": ["Div()"],
1742
    "<Mod>": ["Mod()"],
1743
    "<Pow>": ["Pow()"],
1744
    "<LShift>": ["LShift()"],
1745
    "<RShift>": ["RShift()"],
1746
    "<BitOr>": ["BitOr()"],
1747
    "<BitXor>": ["BitXor()"],
1748
    "<BitAnd>": ["BitAnd()"],
1749
    "<FloorDiv>": ["FloorDiv()"],
1750
    "<unaryop>": [
1751
        "<Invert>",
1752
        "<Not>",
1753
        "<UAdd>",
1754
        "<USub>",
1755
    ],
1756
    "<Invert>": ["Invert()"],
1757
    "<Not>": ["Not()"],
1758
    "<UAdd>": ["UAdd()"],
1759
    "<USub>": ["USub()"],
1760
    "<cmpop>": [
1761
        "<Eq>",
1762
        "<NotEq>",
1763
        "<Lt>",
1764
        "<LtE>",
1765
        "<Gt>",
1766
        "<GtE>",
1767
        "<Is>",
1768
        "<IsNot>",
1769
        "<In>",
1770
        "<NotIn>",
1771
    ],
1772
    "<Eq>": ["Eq()"],
1773
    "<NotEq>": ["NotEq()"],
1774
    "<Lt>": ["Lt()"],
1775
    "<LtE>": ["LtE()"],
1776
    "<Gt>": ["Gt()"],
1777
    "<GtE>": ["GtE()"],
1778
    "<Is>": ["Is()"],
1779
    "<IsNot>": ["IsNot()"],
1780
    "<In>": ["In()"],
1781
    "<NotIn>": ["NotIn()"],
1782
    "<comprehension>": ["<comprehension>(<expr>,<expr>,<expr_list>,<int>)"],
1783
    # Exception Handling
1784
    "<excepthandler>": ["<ExceptHandler>"],
1785
    "<ExceptHandler>": [
1786
        "ExceptHandler(<optional_expr>,<optional_identifier>,<stmt_list>)",
1787
    ],
1788
    # Arguments
1789
    "<arguments>": [
1790
        "arguments(<arg_list>,<arg_list>,<optional_arg>,<arg_list>,<expr_list>,<optional_arg>,<expr_list>)",
1791
    ],
1792
    "<arg>": [
1793
        "arg(<identifier>,<optional_expr>,<optional_string>)",
1794
    ],
1795
    "<keyword>": [
1796
        "keyword(<optional_identifier>,<expr>)",
1797
    ],
1798
    "<alias>": [
1799
        "alias(<identifier>,<optional_identifier>)",
1800
    ],
1801
    "<withitem>": [
1802
        "withitem(<expr>,<optional_expr>)",
1803
    ],
1804
    "<match_case>": [
1805
        "match_case(<pattern>,<optional_expr>,<stmt_list>)",
1806
    ],
1807
    "<pattern>": [
1808
        "<MatchValue>",
1809
        "<MatchSingleton>",
1810
        "<MatchSequence>",
1811
        "<MatchMapping>",
1812
        "<MatchClass>",
1813
        "<MatchStar>",
1814
        "<MatchAs>",
1815
        "<MatchOr>",
1816
    ],
1817
    "<MatchValue>": ["MatchValue(<expr>)"],
1818
    "<MatchSingleton>": ["MatchValue(<constant>)"],
1819
    "<MatchSequence>": ["MatchSequence(<pattern_list>)"],
1820
    "<MatchMapping>": [
1821
        "MatchMapping(<expr_list>,<expr_list>,<optional_identifier>)",
1822
    ],
1823
    "<MatchClass>": [
1824
        "MatchClass(<expr>,<pattern_list>,<identifier_list>,<pattern_list>)"
1825
    ],
1826
    "<MatchStar>": [
1827
        "MatchStar(<optional_identifier>)",
1828
    ],
1829
    "<MatchAs>": [
1830
        "MatchAs(<optional_pattern>,<optional_identifier>)",
1831
    ],
1832
    "<MatchOr>": ["MatchOr(<pattern_list>)"],
1833
    "<type_ignore>": ["<TypeIgnore>"],
1834
    "<TypeIgnore>": ["TypeIgnore(<int>,<string>)"],
1835
    # Basics
1836
    "<int>": [
1837
        "<digits>",
1838
        "-<digits>",
1839
    ],
1840
    "<digits>": [
1841
        "<zeros>",
1842
        "<non_zero_digit>",
1843
        "<non_zero_digit><all_digits>",
1844
    ],
1845
    "<zeros>": [
1846
        "0",
1847
        "0<zeros>",
1848
    ],
1849
    "<all_digits>": [
1850
        "<digit>",
1851
        "<digit><all_digits>",
1852
    ],
1853
    "<digit>": [
1854
        "0",
1855
        "<non_zero_digit>",
1856
    ],
1857
    "<non_zero_digit>": ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
1858
    "<identifier>": ["<id_start><ids>"],
1859
    "<id_start>": srange(string.ascii_letters + "_"),
1860
    "<ids>": ["", "<id><ids>"],
1861
    "<id>": srange(string.ascii_letters + string.digits + "_"),
1862
    "<constant>": [
1863
        "<int>",
1864
        "<string>",
1865
    ],
1866
    "<string>": [
1867
        '"<chars>"',
1868
        "'<chars>'",
1869
    ],
1870
    "<chars>": ["", "<chars><char>"],
1871
    "<char>": (
1872
        srange(string.digits + string.ascii_letters + string.punctuation)
1873
        + [" ", "\\t", "\\n", "\\r", "\\v", "\\f"]
1874
    ),
1875
}
1876

1877
assert is_valid_grammar(GRAMMAR)
1✔
1878

1879
GENERATIVE_GRAMMAR: Grammar = dict(GRAMMAR)
1✔
1880

1881
GENERATIVE_GRAMMAR["<mod>"] = ["<Module>"]
1✔
1882
del GENERATIVE_GRAMMAR["<Interactive>"]
1✔
1883
del GENERATIVE_GRAMMAR["<Expression>"]
1✔
1884
del GENERATIVE_GRAMMAR["<FunctionType>"]
1✔
1885
del GENERATIVE_GRAMMAR["<Yield>"]
1✔
1886
del GENERATIVE_GRAMMAR["<Match>"]
1✔
1887
del GENERATIVE_GRAMMAR["<AugAssign>"]
1✔
1888
del GENERATIVE_GRAMMAR["<YieldFrom>"]
1✔
1889
del GENERATIVE_GRAMMAR["<GeneratorExp>"]
1✔
1890
del GENERATIVE_GRAMMAR["<ListComp>"]
1✔
1891
del GENERATIVE_GRAMMAR["<Try>"]
1✔
1892
del GENERATIVE_GRAMMAR["<DictComp>"]
1✔
1893
del GENERATIVE_GRAMMAR["<AnnAssign>"]
1✔
1894
del GENERATIVE_GRAMMAR["<Break>"]
1✔
1895
del GENERATIVE_GRAMMAR["<With>"]
1✔
1896
del GENERATIVE_GRAMMAR["<Await>"]
1✔
1897
del GENERATIVE_GRAMMAR["<Global>"]
1✔
1898
del GENERATIVE_GRAMMAR["<Lambda>"]
1✔
1899
del GENERATIVE_GRAMMAR["<ClassDef>"]
1✔
1900
del GENERATIVE_GRAMMAR["<Assert>"]
1✔
1901
del GENERATIVE_GRAMMAR["<AsyncWith>"]
1✔
1902
del GENERATIVE_GRAMMAR["<Starred>"]
1✔
1903
# del generative_grammar['<TryStar>']
1904
del GENERATIVE_GRAMMAR["<Raise>"]
1✔
1905
del GENERATIVE_GRAMMAR["<JoinedStr>"]
1✔
1906
del GENERATIVE_GRAMMAR["<Dict>"]
1✔
1907
del GENERATIVE_GRAMMAR["<NamedExpr>"]
1✔
1908
del GENERATIVE_GRAMMAR["<Delete>"]
1✔
1909
del GENERATIVE_GRAMMAR["<AsyncFor>"]
1✔
1910
del GENERATIVE_GRAMMAR["<FormattedValue>"]
1✔
1911
del GENERATIVE_GRAMMAR["<excepthandler_list>"]
1✔
1912
del GENERATIVE_GRAMMAR["<match_case_list>"]
1✔
1913
del GENERATIVE_GRAMMAR["<Set>"]
1✔
1914
del GENERATIVE_GRAMMAR["<Continue>"]
1✔
1915
del GENERATIVE_GRAMMAR["<Nonlocal>"]
1✔
1916
del GENERATIVE_GRAMMAR["<withitem_list>"]
1✔
1917
del GENERATIVE_GRAMMAR["<While>"]
1✔
1918
del GENERATIVE_GRAMMAR["<AsyncFunctionDef>"]
1✔
1919
del GENERATIVE_GRAMMAR["<SetComp>"]
1✔
1920
del GENERATIVE_GRAMMAR["<identifier_list>"]
1✔
1921
del GENERATIVE_GRAMMAR["<MatchSequence>"]
1✔
1922
del GENERATIVE_GRAMMAR["<MatchStar>"]
1✔
1923
del GENERATIVE_GRAMMAR["<ExceptHandler>"]
1✔
1924
del GENERATIVE_GRAMMAR["<pattern>"]
1✔
1925
del GENERATIVE_GRAMMAR["<identifiers>"]
1✔
1926
del GENERATIVE_GRAMMAR["<match_cases>"]
1✔
1927
del GENERATIVE_GRAMMAR["<MatchSingleton>"]
1✔
1928
del GENERATIVE_GRAMMAR["<MatchValue>"]
1✔
1929
del GENERATIVE_GRAMMAR["<comprehension_list>"]
1✔
1930
del GENERATIVE_GRAMMAR["<match_case>"]
1✔
1931
del GENERATIVE_GRAMMAR["<MatchMapping>"]
1✔
1932
del GENERATIVE_GRAMMAR["<MatchOr>"]
1✔
1933
del GENERATIVE_GRAMMAR["<MatchClass>"]
1✔
1934
del GENERATIVE_GRAMMAR["<MatchAs>"]
1✔
1935
del GENERATIVE_GRAMMAR["<pattern_list>"]
1✔
1936
del GENERATIVE_GRAMMAR["<comprehension>"]
1✔
1937
del GENERATIVE_GRAMMAR["<excepthandler>"]
1✔
1938
del GENERATIVE_GRAMMAR["<withitem>"]
1✔
1939
del GENERATIVE_GRAMMAR["<patterns>"]
1✔
1940
del GENERATIVE_GRAMMAR["<withitems>"]
1✔
1941
del GENERATIVE_GRAMMAR["<excepthandlers>"]
1✔
1942
del GENERATIVE_GRAMMAR["<comprehensions>"]
1✔
1943
del GENERATIVE_GRAMMAR["<optional_pattern>"]
1✔
1944
GENERATIVE_GRAMMAR["<stmt>"] = [
1✔
1945
    "<FunctionDef>",
1946
    "<Return>",
1947
    "<Assign>",
1948
    # '<For>',
1949
    "<If>",
1950
    "<Import>",
1951
    "<ImportFrom>",
1952
    "<Expr>",
1953
    "<Pass>",
1954
]
1955
GENERATIVE_GRAMMAR["<expr>"] = [
1✔
1956
    "<BoolOp>",
1957
    "<BinOp>",
1958
    "<UnaryOp>",
1959
    # '<IfExp>',
1960
    "<Compare>",
1961
    "<Call>",
1962
    "<Constant>",
1963
    "<Attribute>",
1964
    # '<Subscript>',
1965
    "<Name>",
1966
    # '<List>',
1967
    "<Tuple>",
1968
]
1969
del GENERATIVE_GRAMMAR["<For>"]
1✔
1970
del GENERATIVE_GRAMMAR["<IfExp>"]
1✔
1971
del GENERATIVE_GRAMMAR["<Subscript>"]
1✔
1972
del GENERATIVE_GRAMMAR["<List>"]
1✔
1973
del GENERATIVE_GRAMMAR["<Slice>"]
1✔
1974

1975
assert is_valid_grammar(GENERATIVE_GRAMMAR)
1✔
1976

1977
GENERATOR = PythonGenerator()
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc