20
20
Import ,
21
21
ImportFrom ,
22
22
Instance ,
23
+ JoinedStr ,
23
24
Module ,
24
25
Name ,
25
26
NodeNG ,
@@ -220,30 +221,31 @@ def __repr__(self):
220
221
def attach_child_tree (self , tree : Tree ) -> None :
221
222
"""Attach a child tree.
222
223
223
- Attaching a child tree is a **stateful** operation for both the parent and child tree. After attaching a child
224
- tree, a tree can be traversed starting from the parent or child tree. From both starting points all nodes in
225
- both trees can be reached, though, the order of nodes will be different as that is relative to the starting
226
- point.
224
+ 1. Make parent tree of the nodes in the child tree
225
+ 2. Extend parents globals with child globals
226
+
227
+ Attaching a child tree is a **stateful** operation for the child tree. After attaching a child
228
+ tree, the tree can be traversed starting from the child tree as a child knows its parent. However, the tree can
229
+ not be traversed from the parent tree as that node object does not contain a list with children trees.
227
230
"""
228
231
if not isinstance (tree .node , Module ):
229
232
raise NotImplementedError (f"Cannot attach child tree: { type (tree .node ).__name__ } " )
230
233
tree_module : Module = cast (Module , tree .node )
231
- self .attach_nodes (tree_module .body )
234
+ self .attach_child_nodes (tree_module .body )
232
235
self .extend_globals (tree_module .globals )
233
236
234
- def attach_nodes (self , nodes : list [NodeNG ]) -> None :
235
- """Attach nodes.
237
+ def attach_child_nodes (self , nodes : list [NodeNG ]) -> None :
238
+ """Attach child nodes.
236
239
237
- Attaching nodes is a **stateful** operation for both this tree's node, the parent node, and the child nodes.
238
- After attaching the nodes, the parent node has the nodes in its body and the child nodes have this tree's node
239
- as parent node.
240
+ Attaching a child tree is a **stateful** operation for the child tree. After attaching a child
241
+ tree, the tree can be traversed starting from the child tree as a child knows its parent. However, the tree can
242
+ not be traversed from the parent tree as that node object does not contain a list with children trees .
240
243
"""
241
244
if not isinstance (self .node , Module ):
242
245
raise NotImplementedError (f"Cannot attach nodes to: { type (self .node ).__name__ } " )
243
246
self_module : Module = cast (Module , self .node )
244
247
for node in nodes :
245
248
node .parent = self_module
246
- self_module .body .append (node )
247
249
248
250
def extend_globals (self , globs : dict [str , list [NodeNG ]]) -> None :
249
251
"""Extend globals by extending the global values for each global key.
@@ -559,6 +561,11 @@ def visit_importfrom(self, node: ImportFrom) -> None:
559
561
return
560
562
self ._matched_nodes .append (node )
561
563
564
+ def visit_joinedstr (self , node : JoinedStr ) -> None :
565
+ if self ._node_type is not JoinedStr :
566
+ return
567
+ self ._matched_nodes .append (node )
568
+
562
569
def _matches (self , node : NodeNG , depth : int ) -> bool :
563
570
if depth >= len (self ._match_nodes ):
564
571
return False
@@ -674,7 +681,8 @@ def collect_dfsas(self, source_code: str) -> Iterable[DirectFsAccess]:
674
681
def collect_dfsas_from_tree (self , tree : Tree ) -> Iterable [DirectFsAccessNode ]: ...
675
682
676
683
677
- class PythonSequentialLinter (Linter , DfsaCollector , TableCollector ):
684
+ class PythonSequentialLinter (PythonLinter , DfsaPyCollector , TablePyCollector ):
685
+ """A linter for sequencing python linters and collectors."""
678
686
679
687
def __init__ (
680
688
self ,
@@ -685,74 +693,15 @@ def __init__(
685
693
self ._linters = linters
686
694
self ._dfsa_collectors = dfsa_collectors
687
695
self ._table_collectors = table_collectors
688
- self ._tree : Tree | None = None
689
-
690
- def lint (self , code : str ) -> Iterable [Advice ]:
691
- maybe_tree = self ._parse_and_append (code )
692
- if maybe_tree .failure :
693
- yield maybe_tree .failure
694
- return
695
- assert maybe_tree .tree is not None
696
- yield from self .lint_tree (maybe_tree .tree )
697
696
698
697
def lint_tree (self , tree : Tree ) -> Iterable [Advice ]:
699
698
for linter in self ._linters :
700
699
yield from linter .lint_tree (tree )
701
700
702
- def _parse_and_append (self , code : str ) -> MaybeTree :
703
- maybe_tree = MaybeTree .from_source_code (code )
704
- if maybe_tree .failure :
705
- return maybe_tree
706
- assert maybe_tree .tree is not None
707
- self .append_tree (maybe_tree .tree )
708
- return maybe_tree
709
-
710
- def append_tree (self , tree : Tree ) -> None :
711
- self ._make_tree ().attach_child_tree (tree )
712
-
713
- def append_nodes (self , nodes : list [NodeNG ]) -> None :
714
- self ._make_tree ().attach_nodes (nodes )
715
-
716
- def append_globals (self , globs : dict ) -> None :
717
- self ._make_tree ().extend_globals (globs )
718
-
719
- def process_child_cell (self , code : str ) -> None :
720
- this_tree = self ._make_tree ()
721
- maybe_tree = MaybeTree .from_source_code (code )
722
- if maybe_tree .failure :
723
- # TODO: bubble up this error
724
- logger .warning (maybe_tree .failure .message )
725
- return
726
- assert maybe_tree .tree is not None
727
- this_tree .attach_child_tree (maybe_tree .tree )
728
-
729
- def collect_dfsas (self , source_code : str ) -> Iterable [DirectFsAccess ]:
730
- maybe_tree = self ._parse_and_append (source_code )
731
- if maybe_tree .failure :
732
- logger .warning (maybe_tree .failure .message )
733
- return
734
- assert maybe_tree .tree is not None
735
- for dfsa_node in self .collect_dfsas_from_tree (maybe_tree .tree ):
736
- yield dfsa_node .dfsa
737
-
738
701
def collect_dfsas_from_tree (self , tree : Tree ) -> Iterable [DirectFsAccessNode ]:
739
702
for collector in self ._dfsa_collectors :
740
703
yield from collector .collect_dfsas_from_tree (tree )
741
704
742
- def collect_tables (self , source_code : str ) -> Iterable [UsedTable ]:
743
- maybe_tree = self ._parse_and_append (source_code )
744
- if maybe_tree .failure :
745
- logger .warning (maybe_tree .failure .message )
746
- return
747
- assert maybe_tree .tree is not None
748
- for table_node in self .collect_tables_from_tree (maybe_tree .tree ):
749
- yield table_node .table
750
-
751
705
def collect_tables_from_tree (self , tree : Tree ) -> Iterable [UsedTableNode ]:
752
706
for collector in self ._table_collectors :
753
707
yield from collector .collect_tables_from_tree (tree )
754
-
755
- def _make_tree (self ) -> Tree :
756
- if self ._tree is None :
757
- self ._tree = Tree .new_module ()
758
- return self ._tree
0 commit comments