-
-
Notifications
You must be signed in to change notification settings - Fork 279
Expand file tree
/
Copy path_pruning.py
More file actions
60 lines (51 loc) · 2 KB
/
_pruning.py
File metadata and controls
60 lines (51 loc) · 2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from __future__ import annotations
__all__ = ["get_reachable_classes"]
from collections.abc import Iterable, Mapping
from typing import TYPE_CHECKING
from ..utils import ClassName
from .properties import (
EnumProperty,
ListProperty,
LiteralEnumProperty,
ModelProperty,
Property,
UnionProperty,
)
from .properties.protocol import PropertyProtocol
if TYPE_CHECKING: # pragma: no cover
from .openapi import Endpoint
def get_reachable_classes(
*,
endpoints: Iterable[Endpoint],
classes_by_name: Mapping[ClassName, Property],
) -> set[ClassName]:
"""Class names reachable from the given endpoints. Anything else is safe to prune.
Walks each endpoint's properties transitively, collecting models and enums by name.
Re-fetches each model from ``classes_by_name`` on descent, since the copy an endpoint
holds may have empty properties.
"""
reachable: set[ClassName] = set()
stack: list[PropertyProtocol] = []
for endpoint in endpoints:
stack.extend(endpoint.list_all_parameters())
stack.extend(response.prop for response in endpoint.responses)
while stack:
prop = stack.pop()
if isinstance(prop, ModelProperty):
name = prop.class_info.name
if name in reachable:
continue
reachable.add(name)
canonical = classes_by_name.get(name, prop)
if isinstance(canonical, ModelProperty):
stack.extend(canonical.required_properties or [])
stack.extend(canonical.optional_properties or [])
if canonical.additional_properties is not None:
stack.append(canonical.additional_properties)
elif isinstance(prop, EnumProperty | LiteralEnumProperty):
reachable.add(prop.class_info.name)
elif isinstance(prop, ListProperty):
stack.append(prop.inner_property)
elif isinstance(prop, UnionProperty):
stack.extend(prop.inner_properties)
return reachable