RestrictedPython 8.3__py3-none-any.whl → 8.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,8 +19,12 @@ the parsed python code to create a modified AST for a byte code generation.
19
19
 
20
20
 
21
21
  import ast
22
+ import collections
22
23
  import contextlib
23
24
  import textwrap
25
+ import typing
26
+
27
+ from RestrictedPython._types import T_pos_ast
24
28
 
25
29
 
26
30
  # For AugAssign the operator must be converted to a string.
@@ -111,11 +115,15 @@ INSPECT_ATTRIBUTES = frozenset([
111
115
  "cr_origin",
112
116
  ])
113
117
 
118
+ _T_visit_return: typing.TypeAlias = ast.AST | typing.Iterable[ast.AST] | None
119
+ _T = typing.TypeVar('_T', bound=ast.AST)
114
120
 
115
121
  # When new ast nodes are generated they have no 'lineno', 'end_lineno',
116
122
  # 'col_offset' and 'end_col_offset'. This function copies these fields from the
117
123
  # incoming node:
118
- def copy_locations(new_node, old_node):
124
+
125
+
126
+ def copy_locations(new_node: T_pos_ast, old_node: T_pos_ast) -> None:
119
127
  assert 'lineno' in new_node._attributes
120
128
  new_node.lineno = old_node.lineno
121
129
 
@@ -132,12 +140,12 @@ def copy_locations(new_node, old_node):
132
140
 
133
141
 
134
142
  class PrintInfo:
135
- def __init__(self):
143
+ def __init__(self) -> None:
136
144
  self.print_used = False
137
145
  self.printed_used = False
138
146
 
139
147
  @contextlib.contextmanager
140
- def new_print_scope(self):
148
+ def new_print_scope(self) -> collections.abc.Iterator[None]:
141
149
  old_print_used = self.print_used
142
150
  old_printed_used = self.printed_used
143
151
 
@@ -152,8 +160,14 @@ class PrintInfo:
152
160
 
153
161
 
154
162
  class RestrictingNodeTransformer(ast.NodeTransformer):
155
-
156
- def __init__(self, errors=None, warnings=None, used_names=None):
163
+ errors: list[str]
164
+ warnings: list[str]
165
+ used_names: dict[str, bool]
166
+
167
+ def __init__(self,
168
+ errors: list[str] | None = None,
169
+ warnings: list[str] | None = None,
170
+ used_names: dict[str, bool] | None = None):
157
171
  super().__init__()
158
172
  self.errors = [] if errors is None else errors
159
173
  self.warnings = [] if warnings is None else warnings
@@ -170,26 +184,26 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
170
184
 
171
185
  self.print_info = PrintInfo()
172
186
 
173
- def gen_tmp_name(self):
187
+ def gen_tmp_name(self) -> str:
174
188
  # 'check_name' ensures that no variable is prefixed with '_'.
175
189
  # => Its safe to use '_tmp..' as a temporary variable.
176
190
  name = '_tmp%i' % self._tmp_idx
177
191
  self._tmp_idx += 1
178
192
  return name
179
193
 
180
- def error(self, node, info):
194
+ def error(self, node: ast.AST, info: str) -> None:
181
195
  """Record a security error discovered during transformation."""
182
196
  lineno = getattr(node, 'lineno', None)
183
197
  self.errors.append(
184
198
  f'Line {lineno}: {info}')
185
199
 
186
- def warn(self, node, info):
187
- """Record a security error discovered during transformation."""
200
+ def warn(self, node: ast.AST, info: str) -> None:
201
+ """Record a security warning discovered during transformation."""
188
202
  lineno = getattr(node, 'lineno', None)
189
203
  self.warnings.append(
190
204
  f'Line {lineno}: {info}')
191
205
 
192
- def guard_iter(self, node):
206
+ def guard_iter(self, node: ast.For | ast.comprehension) -> _T_visit_return:
193
207
  """
194
208
  Converts:
195
209
  for x in expr
@@ -220,10 +234,12 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
220
234
  node.iter = new_iter
221
235
  return node
222
236
 
223
- def is_starred(self, ob):
237
+ def is_starred(self, ob: ast.AST) -> typing.TypeGuard[ast.Starred]:
238
+ # TODO: Change Type Annotation to typing.TypeIs[ast.Starred] when
239
+ # Support for Python 3.12 is dropped.
224
240
  return isinstance(ob, ast.Starred)
225
241
 
226
- def gen_unpack_spec(self, tpl):
242
+ def gen_unpack_spec(self, tpl: ast.Tuple) -> ast.Dict:
227
243
  """Generate a specification for 'guarded_unpack_sequence'.
228
244
 
229
245
  This spec is used to protect sequence unpacking.
@@ -271,7 +287,8 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
271
287
  spec = ast.Dict(keys=[], values=[])
272
288
 
273
289
  spec.keys.append(ast.Constant('childs'))
274
- spec.values.append(ast.Tuple([], ast.Load()))
290
+ val0 = ast.Tuple([], ast.Load())
291
+ spec.values.append(val0)
275
292
 
276
293
  # starred elements in a sequence do not contribute into the min_len.
277
294
  # For example a, b, *c = g
@@ -292,21 +309,26 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
292
309
  el = ast.Tuple([], ast.Load())
293
310
  el.elts.append(ast.Constant(idx - offset))
294
311
  el.elts.append(self.gen_unpack_spec(val))
295
- spec.values[0].elts.append(el)
312
+ val0.elts.append(el)
296
313
 
297
314
  spec.keys.append(ast.Constant('min_len'))
298
315
  spec.values.append(ast.Constant(min_len))
299
316
 
300
317
  return spec
301
318
 
302
- def protect_unpack_sequence(self, target, value):
319
+ def protect_unpack_sequence(
320
+ self,
321
+ target: ast.Tuple,
322
+ value: ast.expr) -> ast.Call:
303
323
  spec = self.gen_unpack_spec(target)
304
324
  return ast.Call(
305
325
  func=ast.Name('_unpack_sequence_', ast.Load()),
306
326
  args=[value, spec, ast.Name('_getiter_', ast.Load())],
307
327
  keywords=[])
308
328
 
309
- def gen_unpack_wrapper(self, node, target):
329
+ def gen_unpack_wrapper(self,
330
+ node: ast.stmt,
331
+ target: ast.Tuple) -> tuple[ast.Name, ast.Try]:
310
332
  """Helper function to protect tuple unpacks.
311
333
 
312
334
  node: used to copy the locations for the new nodes.
@@ -342,8 +364,9 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
342
364
  # arg = converter
343
365
  # finally:
344
366
  # del tmp_arg
345
- try_body = [ast.Assign(targets=[target], value=converter)]
346
- finalbody = [self.gen_del_stmt(tmp_name)]
367
+ try_body: list[ast.stmt] = [ast.Assign(
368
+ targets=[target], value=converter)]
369
+ finalbody: list[ast.stmt] = [self.gen_del_stmt(tmp_name)]
347
370
  cleanup = ast.Try(
348
371
  body=try_body, finalbody=finalbody, handlers=[], orelse=[])
349
372
 
@@ -355,13 +378,17 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
355
378
 
356
379
  return (tmp_target, cleanup)
357
380
 
358
- def gen_none_node(self):
381
+ def gen_none_node(self) -> ast.Constant:
359
382
  return ast.Constant(None)
360
383
 
361
- def gen_del_stmt(self, name_to_del):
384
+ def gen_del_stmt(self, name_to_del: str) -> ast.Delete:
362
385
  return ast.Delete(targets=[ast.Name(name_to_del, ast.Del())])
363
386
 
364
- def check_name(self, node, name, allow_magic_methods=False):
387
+ def check_name(
388
+ self,
389
+ node: T_pos_ast,
390
+ name: str | None,
391
+ allow_magic_methods: bool = False) -> None:
365
392
  """Check names if they are allowed.
366
393
 
367
394
  If ``allow_magic_methods is True`` names in `ALLOWED_FUNC_NAMES`
@@ -386,7 +413,9 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
386
413
  elif name in FORBIDDEN_FUNC_NAMES:
387
414
  self.error(node, f'"{name}" is a reserved name.')
388
415
 
389
- def check_function_argument_names(self, node):
416
+ def check_function_argument_names(
417
+ self,
418
+ node: ast.FunctionDef | ast.AsyncFunctionDef | ast.Lambda) -> None:
390
419
  for arg in node.args.posonlyargs:
391
420
  self.check_name(node, arg.arg)
392
421
 
@@ -402,7 +431,7 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
402
431
  for arg in node.args.kwonlyargs:
403
432
  self.check_name(node, arg.arg)
404
433
 
405
- def check_import_names(self, node):
434
+ def check_import_names(self, node: ast.ImportFrom | ast.Import) -> ast.AST:
406
435
  """Check the names being imported.
407
436
 
408
437
  This is a protection against rebinding dunder names like
@@ -419,7 +448,10 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
419
448
 
420
449
  return self.node_contents_visit(node)
421
450
 
422
- def inject_print_collector(self, node, position=0):
451
+ def inject_print_collector(
452
+ self,
453
+ node: ast.Module | ast.FunctionDef,
454
+ position: int = 0) -> None:
423
455
  print_used = self.print_info.print_used
424
456
  printed_used = self.print_info.printed_used
425
457
 
@@ -452,7 +484,8 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
452
484
 
453
485
  # Special Functions for an ast.NodeTransformer
454
486
 
455
- def generic_visit(self, node):
487
+ def generic_visit(self, # type: ignore[override]
488
+ node: ast.AST) -> _T_visit_return:
456
489
  """Reject ast nodes which do not have a corresponding `visit_` method.
457
490
 
458
491
  This is needed to prevent new ast nodes from new Python versions to be
@@ -467,18 +500,18 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
467
500
  )
468
501
  self.not_allowed(node)
469
502
 
470
- def not_allowed(self, node):
503
+ def not_allowed(self, node: ast.AST) -> None:
471
504
  self.error(
472
505
  node,
473
506
  f'{node.__class__.__name__} statements are not allowed.')
474
507
 
475
- def node_contents_visit(self, node):
508
+ def node_contents_visit(self, node: _T) -> _T:
476
509
  """Visit the contents of a node."""
477
- return super().generic_visit(node)
510
+ return super().generic_visit(node) # type: ignore[return-value]
478
511
 
479
512
  # ast for Literals
480
513
 
481
- def visit_Constant(self, node):
514
+ def visit_Constant(self, node: ast.Constant) -> _T_visit_return:
482
515
  """Allow constant literals.
483
516
 
484
517
  Constant replaces Num, Str, Bytes, NameConstant and Ellipsis in
@@ -487,41 +520,46 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
487
520
  """
488
521
  return self.node_contents_visit(node)
489
522
 
490
- def visit_Interactive(self, node):
523
+ def visit_Interactive(self, node: ast.Interactive) -> _T_visit_return:
491
524
  """Allow single mode without restrictions."""
492
525
  return self.node_contents_visit(node)
493
526
 
494
- def visit_List(self, node):
527
+ def visit_List(self, node: ast.List) -> _T_visit_return:
495
528
  """Allow list literals without restrictions."""
496
529
  return self.node_contents_visit(node)
497
530
 
498
- def visit_Tuple(self, node):
531
+ def visit_Tuple(self, node: ast.Tuple) -> _T_visit_return:
499
532
  """Allow tuple literals without restrictions."""
500
533
  return self.node_contents_visit(node)
501
534
 
502
- def visit_Set(self, node):
535
+ def visit_Set(self, node: ast.Set) -> _T_visit_return:
503
536
  """Allow set literals without restrictions."""
504
537
  return self.node_contents_visit(node)
505
538
 
506
- def visit_Dict(self, node):
539
+ def visit_Dict(self, node: ast.Dict) -> _T_visit_return:
507
540
  """Allow dict literals without restrictions."""
508
541
  return self.node_contents_visit(node)
509
542
 
510
- def visit_FormattedValue(self, node):
543
+ def visit_FormattedValue(
544
+ self,
545
+ node: ast.FormattedValue) -> _T_visit_return:
511
546
  """Allow f-strings without restrictions."""
512
547
  return self.node_contents_visit(node)
513
548
 
514
- def visit_TemplateStr(self, node):
549
+ def visit_TemplateStr(self, node: ast.AST) -> _T_visit_return:
515
550
  """Template strings are allowed by default.
516
551
 
517
552
  As Template strings are a very basic template mechanism, that needs
518
553
  additional rendering logic to be useful, they are not blocked by
519
554
  default.
520
555
  Those rendering logic would be affected by RestrictedPython as well.
556
+
557
+ TODO: Change Type Annotation to ast.TemplateStr when
558
+ Support for Python 3.13 is dropped.
521
559
  """
522
560
  return self.node_contents_visit(node)
523
561
 
524
- def visit_Interpolation(self, node):
562
+ def visit_Interpolation(self, node: ast.AST) -> _T_visit_return:
525
563
  """Interpolations are allowed by default.
526
564
 
527
565
  As Interpolations are part of Template Strings, they are needed
@@ -529,16 +567,19 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
529
567
  are allowed. As a user has to provide additional rendering logic
530
568
  to make use of Template Strings, the security implications of
531
569
  Interpolations are limited in the context of RestrictedPython.
570
+
571
+ TODO: Change Type Annotation to ast.Interpolation when
572
+ Support for Python 3.13 is dropped.
532
573
  """
533
574
  return self.node_contents_visit(node)
534
575
 
535
- def visit_JoinedStr(self, node):
576
+ def visit_JoinedStr(self, node: ast.JoinedStr) -> _T_visit_return:
536
577
  """Allow joined string without restrictions."""
537
578
  return self.node_contents_visit(node)
538
579
 
539
580
  # ast for Variables
540
581
 
541
- def visit_Name(self, node):
582
+ def visit_Name(self, node: ast.Name) -> _T_visit_return:
542
583
  """Prevents access to protected names.
543
584
 
544
585
  Converts use of the name 'printed' to this expression: '_print()'
@@ -547,6 +588,7 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
547
588
  node = self.node_contents_visit(node)
548
589
 
549
590
  if isinstance(node.ctx, ast.Load):
591
+ new_node: T_pos_ast
550
592
  if node.id == 'printed':
551
593
  self.print_info.printed_used = True
552
594
  new_node = ast.Call(
@@ -572,25 +614,25 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
572
614
  self.check_name(node, node.id)
573
615
  return node
574
616
 
575
- def visit_Load(self, node):
617
+ def visit_Load(self, node: ast.Load) -> _T_visit_return:
576
618
  """
577
619
 
578
620
  """
579
621
  return self.node_contents_visit(node)
580
622
 
581
- def visit_Store(self, node):
623
+ def visit_Store(self, node: ast.Store) -> _T_visit_return:
582
624
  """
583
625
 
584
626
  """
585
627
  return self.node_contents_visit(node)
586
628
 
587
- def visit_Del(self, node):
629
+ def visit_Del(self, node: ast.Del) -> _T_visit_return:
588
630
  """
589
631
 
590
632
  """
591
633
  return self.node_contents_visit(node)
592
634
 
593
- def visit_Starred(self, node):
635
+ def visit_Starred(self, node: ast.Starred) -> _T_visit_return:
594
636
  """
595
637
 
596
638
  """
@@ -598,18 +640,18 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
598
640
 
599
641
  # Expressions
600
642
 
601
- def visit_Expression(self, node):
643
+ def visit_Expression(self, node: ast.Expression) -> _T_visit_return:
602
644
  """Allow Expression statements without restrictions.
603
645
 
604
646
  They are in the AST when using the `eval` compile mode.
605
647
  """
606
648
  return self.node_contents_visit(node)
607
649
 
608
- def visit_Expr(self, node):
650
+ def visit_Expr(self, node: ast.Expr) -> _T_visit_return:
609
651
  """Allow Expr statements (any expression) without restrictions."""
610
652
  return self.node_contents_visit(node)
611
653
 
612
- def visit_UnaryOp(self, node):
654
+ def visit_UnaryOp(self, node: ast.UnaryOp) -> _T_visit_return:
613
655
  """
614
656
  UnaryOp (Unary Operations) is the overall element for:
615
657
  * Not --> which should be allowed
@@ -618,135 +660,135 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
618
660
  """
619
661
  return self.node_contents_visit(node)
620
662
 
621
- def visit_UAdd(self, node):
663
+ def visit_UAdd(self, node: ast.UAdd) -> _T_visit_return:
622
664
  """Allow positive notation of variables. (e.g. +var)"""
623
665
  return self.node_contents_visit(node)
624
666
 
625
- def visit_USub(self, node):
667
+ def visit_USub(self, node: ast.USub) -> _T_visit_return:
626
668
  """Allow negative notation of variables. (e.g. -var)"""
627
669
  return self.node_contents_visit(node)
628
670
 
629
- def visit_Not(self, node):
671
+ def visit_Not(self, node: ast.Not) -> _T_visit_return:
630
672
  """Allow the `not` operator."""
631
673
  return self.node_contents_visit(node)
632
674
 
633
- def visit_Invert(self, node):
675
+ def visit_Invert(self, node: ast.Invert) -> _T_visit_return:
634
676
  """Allow `~` expressions."""
635
677
  return self.node_contents_visit(node)
636
678
 
637
- def visit_BinOp(self, node):
679
+ def visit_BinOp(self, node: ast.BinOp) -> _T_visit_return:
638
680
  """Allow binary operations."""
639
681
  return self.node_contents_visit(node)
640
682
 
641
- def visit_Add(self, node):
683
+ def visit_Add(self, node: ast.Add) -> _T_visit_return:
642
684
  """Allow `+` expressions."""
643
685
  return self.node_contents_visit(node)
644
686
 
645
- def visit_Sub(self, node):
687
+ def visit_Sub(self, node: ast.Sub) -> _T_visit_return:
646
688
  """Allow `-` expressions."""
647
689
  return self.node_contents_visit(node)
648
690
 
649
- def visit_Mult(self, node):
691
+ def visit_Mult(self, node: ast.Mult) -> _T_visit_return:
650
692
  """Allow `*` expressions."""
651
693
  return self.node_contents_visit(node)
652
694
 
653
- def visit_Div(self, node):
695
+ def visit_Div(self, node: ast.Div) -> _T_visit_return:
654
696
  """Allow `/` expressions."""
655
697
  return self.node_contents_visit(node)
656
698
 
657
- def visit_FloorDiv(self, node):
699
+ def visit_FloorDiv(self, node: ast.FloorDiv) -> _T_visit_return:
658
700
  """Allow `//` expressions."""
659
701
  return self.node_contents_visit(node)
660
702
 
661
- def visit_Mod(self, node):
703
+ def visit_Mod(self, node: ast.Mod) -> _T_visit_return:
662
704
  """Allow `%` expressions."""
663
705
  return self.node_contents_visit(node)
664
706
 
665
- def visit_Pow(self, node):
707
+ def visit_Pow(self, node: ast.Pow) -> _T_visit_return:
666
708
  """Allow `**` expressions."""
667
709
  return self.node_contents_visit(node)
668
710
 
669
- def visit_LShift(self, node):
711
+ def visit_LShift(self, node: ast.LShift) -> _T_visit_return:
670
712
  """Allow `<<` expressions."""
671
713
  return self.node_contents_visit(node)
672
714
 
673
- def visit_RShift(self, node):
715
+ def visit_RShift(self, node: ast.RShift) -> _T_visit_return:
674
716
  """Allow `>>` expressions."""
675
717
  return self.node_contents_visit(node)
676
718
 
677
- def visit_BitOr(self, node):
719
+ def visit_BitOr(self, node: ast.BitOr) -> _T_visit_return:
678
720
  """Allow `|` expressions."""
679
721
  return self.node_contents_visit(node)
680
722
 
681
- def visit_BitXor(self, node):
723
+ def visit_BitXor(self, node: ast.BitXor) -> _T_visit_return:
682
724
  """Allow `^` expressions."""
683
725
  return self.node_contents_visit(node)
684
726
 
685
- def visit_BitAnd(self, node):
727
+ def visit_BitAnd(self, node: ast.BitAnd) -> _T_visit_return:
686
728
  """Allow `&` expressions."""
687
729
  return self.node_contents_visit(node)
688
730
 
689
- def visit_MatMult(self, node):
731
+ def visit_MatMult(self, node: ast.MatMult) -> _T_visit_return:
690
732
  """Allow multiplication (`@`)."""
691
733
  return self.node_contents_visit(node)
692
734
 
693
- def visit_BoolOp(self, node):
735
+ def visit_BoolOp(self, node: ast.BoolOp) -> _T_visit_return:
694
736
  """Allow bool operator without restrictions."""
695
737
  return self.node_contents_visit(node)
696
738
 
697
- def visit_And(self, node):
739
+ def visit_And(self, node: ast.And) -> _T_visit_return:
698
740
  """Allow bool operator `and` without restrictions."""
699
741
  return self.node_contents_visit(node)
700
742
 
701
- def visit_Or(self, node):
743
+ def visit_Or(self, node: ast.Or) -> _T_visit_return:
702
744
  """Allow bool operator `or` without restrictions."""
703
745
  return self.node_contents_visit(node)
704
746
 
705
- def visit_Compare(self, node):
747
+ def visit_Compare(self, node: ast.Compare) -> _T_visit_return:
706
748
  """Allow comparison expressions without restrictions."""
707
749
  return self.node_contents_visit(node)
708
750
 
709
- def visit_Eq(self, node):
751
+ def visit_Eq(self, node: ast.Eq) -> _T_visit_return:
710
752
  """Allow == expressions."""
711
753
  return self.node_contents_visit(node)
712
754
 
713
- def visit_NotEq(self, node):
755
+ def visit_NotEq(self, node: ast.NotEq) -> _T_visit_return:
714
756
  """Allow != expressions."""
715
757
  return self.node_contents_visit(node)
716
758
 
717
- def visit_Lt(self, node):
759
+ def visit_Lt(self, node: ast.Lt) -> _T_visit_return:
718
760
  """Allow < expressions."""
719
761
  return self.node_contents_visit(node)
720
762
 
721
- def visit_LtE(self, node):
763
+ def visit_LtE(self, node: ast.LtE) -> _T_visit_return:
722
764
  """Allow <= expressions."""
723
765
  return self.node_contents_visit(node)
724
766
 
725
- def visit_Gt(self, node):
767
+ def visit_Gt(self, node: ast.Gt) -> _T_visit_return:
726
768
  """Allow > expressions."""
727
769
  return self.node_contents_visit(node)
728
770
 
729
- def visit_GtE(self, node):
771
+ def visit_GtE(self, node: ast.GtE) -> _T_visit_return:
730
772
  """Allow >= expressions."""
731
773
  return self.node_contents_visit(node)
732
774
 
733
- def visit_Is(self, node):
775
+ def visit_Is(self, node: ast.Is) -> _T_visit_return:
734
776
  """Allow `is` expressions."""
735
777
  return self.node_contents_visit(node)
736
778
 
737
- def visit_IsNot(self, node):
779
+ def visit_IsNot(self, node: ast.IsNot) -> _T_visit_return:
738
780
  """Allow `is not` expressions."""
739
781
  return self.node_contents_visit(node)
740
782
 
741
- def visit_In(self, node):
783
+ def visit_In(self, node: ast.In) -> _T_visit_return:
742
784
  """Allow `in` expressions."""
743
785
  return self.node_contents_visit(node)
744
786
 
745
- def visit_NotIn(self, node):
787
+ def visit_NotIn(self, node: ast.NotIn) -> _T_visit_return:
746
788
  """Allow `not in` expressions."""
747
789
  return self.node_contents_visit(node)
748
790
 
749
- def visit_Call(self, node):
791
+ def visit_Call(self, node: ast.Call) -> _T_visit_return:
750
792
  """Checks calls with '*args' and '**kwargs'.
751
793
 
752
794
  Note: The following happens only if '*args' or '**kwargs' is used.
@@ -788,17 +830,17 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
788
830
  copy_locations(node.func, node.args[0])
789
831
  return node
790
832
 
791
- def visit_keyword(self, node):
833
+ def visit_keyword(self, node: ast.keyword) -> _T_visit_return:
792
834
  """
793
835
 
794
836
  """
795
837
  return self.node_contents_visit(node)
796
838
 
797
- def visit_IfExp(self, node):
839
+ def visit_IfExp(self, node: ast.IfExp) -> _T_visit_return:
798
840
  """Allow `if` expressions without restrictions."""
799
841
  return self.node_contents_visit(node)
800
842
 
801
- def visit_Attribute(self, node):
843
+ def visit_Attribute(self, node: ast.Attribute) -> _T_visit_return:
802
844
  """Checks and mutates attribute access/assignment.
803
845
 
804
846
  'a.b' becomes '_getattr_(a, "b")'
@@ -854,7 +896,7 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
854
896
 
855
897
  # Subscripting
856
898
 
857
- def visit_Subscript(self, node):
899
+ def visit_Subscript(self, node: ast.Subscript) -> _T_visit_return:
858
900
  """Transforms all kinds of subscripts.
859
901
 
860
902
  'foo[bar]' becomes '_getitem_(foo, bar)'
@@ -899,7 +941,7 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
899
941
  raise NotImplementedError(
900
942
  f"Unknown ctx type: {type(node.ctx)}")
901
943
 
902
- def visit_Slice(self, node):
944
+ def visit_Slice(self, node: ast.Slice) -> _T_visit_return:
903
945
  """
904
946
 
905
947
  """
@@ -907,31 +949,31 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
907
949
 
908
950
  # Comprehensions
909
951
 
910
- def visit_ListComp(self, node):
952
+ def visit_ListComp(self, node: ast.ListComp) -> _T_visit_return:
911
953
  """
912
954
 
913
955
  """
914
956
  return self.node_contents_visit(node)
915
957
 
916
- def visit_SetComp(self, node):
958
+ def visit_SetComp(self, node: ast.SetComp) -> _T_visit_return:
917
959
  """
918
960
 
919
961
  """
920
962
  return self.node_contents_visit(node)
921
963
 
922
- def visit_GeneratorExp(self, node):
964
+ def visit_GeneratorExp(self, node: ast.GeneratorExp) -> _T_visit_return:
923
965
  """
924
966
 
925
967
  """
926
968
  return self.node_contents_visit(node)
927
969
 
928
- def visit_DictComp(self, node):
970
+ def visit_DictComp(self, node: ast.DictComp) -> _T_visit_return:
929
971
  """
930
972
 
931
973
  """
932
974
  return self.node_contents_visit(node)
933
975
 
934
- def visit_comprehension(self, node):
976
+ def visit_comprehension(self, node: ast.comprehension) -> _T_visit_return:
935
977
  """
936
978
 
937
979
  """
@@ -939,7 +981,7 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
939
981
 
940
982
  # Statements
941
983
 
942
- def visit_Assign(self, node):
984
+ def visit_Assign(self, node: ast.Assign) -> _T_visit_return:
943
985
  """
944
986
 
945
987
  """
@@ -988,7 +1030,7 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
988
1030
 
989
1031
  return new_nodes
990
1032
 
991
- def visit_AugAssign(self, node):
1033
+ def visit_AugAssign(self, node: ast.AugAssign) -> _T_visit_return:
992
1034
  """Forbid certain kinds of AugAssign
993
1035
 
994
1036
  According to the language reference (and ast.c) the following nodes
@@ -1039,75 +1081,79 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
1039
1081
  raise NotImplementedError(
1040
1082
  f"Unknown target type: {type(node.target)}")
1041
1083
 
1042
- def visit_Raise(self, node):
1084
+ def visit_Raise(self, node: ast.Raise) -> _T_visit_return:
1043
1085
  """Allow `raise` statements without restrictions."""
1044
1086
  return self.node_contents_visit(node)
1045
1087
 
1046
- def visit_Assert(self, node):
1088
+ def visit_Assert(self, node: ast.Assert) -> _T_visit_return:
1047
1089
  """Allow assert statements without restrictions."""
1048
1090
  return self.node_contents_visit(node)
1049
1091
 
1050
- def visit_Delete(self, node):
1092
+ def visit_Delete(self, node: ast.Delete) -> _T_visit_return:
1051
1093
  """Allow `del` statements without restrictions."""
1052
1094
  return self.node_contents_visit(node)
1053
1095
 
1054
- def visit_Pass(self, node):
1096
+ def visit_Pass(self, node: ast.Pass) -> _T_visit_return:
1055
1097
  """Allow `pass` statements without restrictions."""
1056
1098
  return self.node_contents_visit(node)
1057
1099
 
1058
1100
  # Imports
1059
1101
 
1060
- def visit_Import(self, node):
1102
+ def visit_Import(self, node: ast.Import) -> _T_visit_return:
1061
1103
  """Allow `import` statements with restrictions.
1062
1104
  See check_import_names."""
1063
1105
  return self.check_import_names(node)
1064
1106
 
1065
- def visit_ImportFrom(self, node):
1107
+ def visit_ImportFrom(self, node: ast.ImportFrom) -> _T_visit_return:
1066
1108
  """Allow `import from` statements with restrictions.
1067
1109
  See check_import_names."""
1068
1110
  return self.check_import_names(node)
1069
1111
 
1070
- def visit_alias(self, node):
1112
+ def visit_alias(self, node: ast.alias) -> _T_visit_return:
1071
1113
  """Allow `as` statements in import and import from statements."""
1072
1114
  return self.node_contents_visit(node)
1073
1115
 
1074
1116
  # Control flow
1075
1117
 
1076
- def visit_If(self, node):
1118
+ def visit_If(self, node: ast.If) -> _T_visit_return:
1077
1119
  """Allow `if` statements without restrictions."""
1078
1120
  return self.node_contents_visit(node)
1079
1121
 
1080
- def visit_For(self, node):
1122
+ def visit_For(self, node: ast.For) -> _T_visit_return:
1081
1123
  """Allow `for` statements with some restrictions."""
1082
1124
  return self.guard_iter(node)
1083
1125
 
1084
- def visit_While(self, node):
1126
+ def visit_While(self, node: ast.While) -> _T_visit_return:
1085
1127
  """Allow `while` statements."""
1086
1128
  return self.node_contents_visit(node)
1087
1129
 
1088
- def visit_Break(self, node):
1130
+ def visit_Break(self, node: ast.Break) -> _T_visit_return:
1089
1131
  """Allow `break` statements without restrictions."""
1090
1132
  return self.node_contents_visit(node)
1091
1133
 
1092
- def visit_Continue(self, node):
1134
+ def visit_Continue(self, node: ast.Continue) -> _T_visit_return:
1093
1135
  """Allow `continue` statements without restrictions."""
1094
1136
  return self.node_contents_visit(node)
1095
1137
 
1096
- def visit_Try(self, node):
1138
+ def visit_Try(self, node: ast.Try) -> _T_visit_return:
1097
1139
  """Allow `try` without restrictions."""
1098
1140
  return self.node_contents_visit(node)
1099
1141
 
1100
- def visit_TryStar(self, node):
1101
- """Disallow `ExceptionGroup` due to a potential sandbox escape."""
1142
+ def visit_TryStar(self, node: ast.AST) -> _T_visit_return:
1143
+ """Disallow `ExceptionGroup` due to a potential sandbox escape.
1144
+
1145
+ TODO: Change Type Annotation to ast.TryStar when
1146
+ Support for Python 3.10 is dropped.
1147
+ """
1102
1148
  self.not_allowed(node)
1103
1149
 
1104
- def visit_ExceptHandler(self, node):
1150
+ def visit_ExceptHandler(self, node: ast.ExceptHandler) -> _T_visit_return:
1105
1151
  """Protect exception handlers."""
1106
1152
  node = self.node_contents_visit(node)
1107
1153
  self.check_name(node, node.name)
1108
1154
  return node
1109
1155
 
1110
- def visit_With(self, node):
1156
+ def visit_With(self, node: ast.With) -> _T_visit_return:
1111
1157
  """Protect tuple unpacking on with statements."""
1112
1158
  node = self.node_contents_visit(node)
1113
1159
 
@@ -1122,13 +1168,13 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
1122
1168
 
1123
1169
  return node
1124
1170
 
1125
- def visit_withitem(self, node):
1171
+ def visit_withitem(self, node: ast.withitem) -> _T_visit_return:
1126
1172
  """Allow `with` statements (context managers) without restrictions."""
1127
1173
  return self.node_contents_visit(node)
1128
1174
 
1129
1175
  # Function and class definitions
1130
1176
 
1131
- def visit_FunctionDef(self, node):
1177
+ def visit_FunctionDef(self, node: ast.FunctionDef) -> _T_visit_return:
1132
1178
  """Allow function definitions (`def`) with some restrictions."""
1133
1179
  self.check_name(node, node.name, allow_magic_methods=True)
1134
1180
  self.check_function_argument_names(node)
@@ -1138,44 +1184,44 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
1138
1184
  self.inject_print_collector(node)
1139
1185
  return node
1140
1186
 
1141
- def visit_Lambda(self, node):
1187
+ def visit_Lambda(self, node: ast.Lambda) -> _T_visit_return:
1142
1188
  """Allow lambda with some restrictions."""
1143
1189
  self.check_function_argument_names(node)
1144
1190
  return self.node_contents_visit(node)
1145
1191
 
1146
- def visit_arguments(self, node):
1192
+ def visit_arguments(self, node: ast.arguments) -> _T_visit_return:
1147
1193
  """
1148
1194
 
1149
1195
  """
1150
1196
  return self.node_contents_visit(node)
1151
1197
 
1152
- def visit_arg(self, node):
1198
+ def visit_arg(self, node: ast.arg) -> _T_visit_return:
1153
1199
  """
1154
1200
 
1155
1201
  """
1156
1202
  return self.node_contents_visit(node)
1157
1203
 
1158
- def visit_Return(self, node):
1204
+ def visit_Return(self, node: ast.Return) -> _T_visit_return:
1159
1205
  """Allow `return` statements without restrictions."""
1160
1206
  return self.node_contents_visit(node)
1161
1207
 
1162
- def visit_Yield(self, node):
1208
+ def visit_Yield(self, node: ast.Yield) -> _T_visit_return:
1163
1209
  """Allow `yield`statements without restrictions."""
1164
1210
  return self.node_contents_visit(node)
1165
1211
 
1166
- def visit_YieldFrom(self, node):
1212
+ def visit_YieldFrom(self, node: ast.YieldFrom) -> _T_visit_return:
1167
1213
  """Allow `yield`statements without restrictions."""
1168
1214
  return self.node_contents_visit(node)
1169
1215
 
1170
- def visit_Global(self, node):
1216
+ def visit_Global(self, node: ast.Global) -> _T_visit_return:
1171
1217
  """Allow `global` statements without restrictions."""
1172
1218
  return self.node_contents_visit(node)
1173
1219
 
1174
- def visit_Nonlocal(self, node):
1220
+ def visit_Nonlocal(self, node: ast.Nonlocal) -> _T_visit_return:
1175
1221
  """Deny `nonlocal` statements."""
1176
1222
  self.not_allowed(node)
1177
1223
 
1178
- def visit_ClassDef(self, node):
1224
+ def visit_ClassDef(self, node: ast.ClassDef) -> _T_visit_return:
1179
1225
  """Check the name of a class definition."""
1180
1226
  self.check_name(node, node.name)
1181
1227
  node = self.node_contents_visit(node)
@@ -1186,13 +1232,14 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
1186
1232
  class {0.name}(metaclass=__metaclass__):
1187
1233
  pass
1188
1234
  '''.format(node))
1189
- new_class_node = ast.parse(CLASS_DEF).body[0]
1235
+ new_class_node = typing.cast(
1236
+ ast.ClassDef, ast.parse(CLASS_DEF).body[0])
1190
1237
  new_class_node.body = node.body
1191
1238
  new_class_node.bases = node.bases
1192
1239
  new_class_node.decorator_list = node.decorator_list
1193
1240
  return new_class_node
1194
1241
 
1195
- def visit_Module(self, node):
1242
+ def visit_Module(self, node: ast.Module) -> _T_visit_return:
1196
1243
  """Add the print_collector (only if print is used) at the top."""
1197
1244
  node = self.node_contents_visit(node)
1198
1245
 
@@ -1210,25 +1257,26 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
1210
1257
 
1211
1258
  # Async und await
1212
1259
 
1213
- def visit_AsyncFunctionDef(self, node):
1260
+ def visit_AsyncFunctionDef(
1261
+ self, node: ast.AsyncFunctionDef) -> _T_visit_return:
1214
1262
  """Deny async functions."""
1215
1263
  self.not_allowed(node)
1216
1264
 
1217
- def visit_Await(self, node):
1265
+ def visit_Await(self, node: ast.Await) -> _T_visit_return:
1218
1266
  """Deny async functionality."""
1219
1267
  self.not_allowed(node)
1220
1268
 
1221
- def visit_AsyncFor(self, node):
1269
+ def visit_AsyncFor(self, node: ast.AsyncFor) -> _T_visit_return:
1222
1270
  """Deny async functionality."""
1223
1271
  self.not_allowed(node)
1224
1272
 
1225
- def visit_AsyncWith(self, node):
1273
+ def visit_AsyncWith(self, node: ast.AsyncWith) -> _T_visit_return:
1226
1274
  """Deny async functionality."""
1227
1275
  self.not_allowed(node)
1228
1276
 
1229
1277
  # Assignment expressions (walrus operator ``:=``)
1230
1278
  # New in 3.8
1231
- def visit_NamedExpr(self, node):
1279
+ def visit_NamedExpr(self, node: ast.NamedExpr) -> _T_visit_return:
1232
1280
  """Allow assignment expressions under some circumstances."""
1233
1281
  # while the grammar requires ``node.target`` to be a ``Name``
1234
1282
  # the abstract syntax is more permissive and allows an ``expr``.
@@ -1240,7 +1288,7 @@ class RestrictingNodeTransformer(ast.NodeTransformer):
1240
1288
  node = self.node_contents_visit(node) # this checks ``node.target``
1241
1289
  target = node.target
1242
1290
  if not isinstance(target, ast.Name):
1243
- self.error(
1291
+ self.error( # type: ignore[unreachable]
1244
1292
  node,
1245
1293
  "Assignment expressions are only allowed for simple targets")
1246
1294
  return node