pytorch-lightning
88 строк · 3.0 Кб
1# Copyright The Lightning AI team.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Utilities for traversing the tree of components in an app."""
15
16from typing import TYPE_CHECKING, Type
17
18import lightning.app
19
20if TYPE_CHECKING:
21from lightning.app.utilities.types import Component, ComponentTuple
22
23
24def breadth_first(root: "Component", types: Type["ComponentTuple"] = None):
25"""Returns a generator that walks through the tree of components breadth-first.
26
27Arguments:
28root: The root component of the tree
29types: If provided, only the component types in this list will be visited.
30
31"""
32yield from _BreadthFirstVisitor(root, types)
33
34
35class _BreadthFirstVisitor:
36def __init__(self, root: "Component", types: Type["ComponentTuple"] = None) -> None:
37self.queue = [root]
38self.types = types
39
40def __iter__(self):
41return self
42
43def __next__(self):
44from lightning.app.structures import Dict
45
46while self.queue:
47component = self.queue.pop(0)
48
49if isinstance(component, lightning.app.LightningFlow):
50components = [getattr(component, el) for el in sorted(component._flows)]
51for struct_name in sorted(component._structures):
52structure = getattr(component, struct_name)
53if isinstance(structure, Dict):
54values = sorted(structure.items(), key=lambda x: x[0])
55else:
56values = sorted(((v.name, v) for v in structure), key=lambda x: x[0])
57for _, value in values:
58if isinstance(value, lightning.app.LightningFlow):
59components.append(value)
60self.queue += components
61self.queue += component.works(recurse=False)
62
63if any(isinstance(component, t) for t in self.types):
64return component
65
66raise StopIteration
67
68
69class _DepthFirstVisitor:
70def __init__(self, root: "Component", types: Type["ComponentTuple"] = None) -> None:
71self.stack = [root]
72self.types = types
73
74def __iter__(self):
75return self
76
77def __next__(self):
78while self.stack:
79component = self.stack.pop()
80
81if isinstance(component, lightning.app.LightningFlow):
82self.stack += list(component.flows.values())
83self.stack += component.works(recurse=False)
84
85if any(isinstance(component, t) for t in self.types):
86return component
87
88raise StopIteration
89