11
11
from referencing import Resource , Specification
12
12
13
13
if TYPE_CHECKING :
14
+ from importlib .resources .abc import Traversable
15
+
14
16
from referencing .typing import URI
15
17
16
18
@@ -22,21 +24,55 @@ def from_path(root: Path) -> Iterable[tuple[URI, Resource[Any]]]:
22
24
the root) -- though it still is often a good idea to explicitly indicate
23
25
what specification every resource is written for internally.
24
26
"""
25
- specification : Specification [Any ] | None = None
26
- for dir , _ , files in _walk (root ):
27
- for file in files :
28
- path = dir / file
29
- contents = json .loads (path .read_text ())
30
- if specification is None :
31
- specification = Specification .detect (contents ) # type: ignore[reportUnknownMemberType]
32
- resource = specification .detect (contents ).create_resource (contents )
33
- yield path .as_uri (), resource
27
+ return _from_walked (_walk (root ))
34
28
35
29
36
- def _walk (path : Path ) -> Iterable [tuple [ Path , Iterable [ str ], Iterable [ str ]] ]:
30
+ def _walk (path : Path ) -> Iterable [Path ]:
37
31
walk = getattr (path , "walk" , None )
38
- if walk is not None :
39
- yield from walk ()
40
- return
41
- for root , dirs , files in os .walk (path ): # pragma: no cover
42
- yield Path (root ), dirs , files
32
+ if walk is None :
33
+ for dir , _ , files in os .walk (path ): # pragma: no cover
34
+ for file in files :
35
+ yield Path (dir ) / file
36
+ else :
37
+ for dir , _ , files in walk ():
38
+ for file in files :
39
+ yield dir / file
40
+
41
+
42
+ def _walk_traversable (root : Traversable ) -> Iterable [Traversable ]:
43
+ """
44
+ .walk() for importlib resources paths, which don't have the method :/
45
+ """ # noqa: D415
46
+ walking = [root ]
47
+ while walking :
48
+ path = walking .pop ()
49
+ for each in path .iterdir ():
50
+ if each .is_dir ():
51
+ walking .append (each )
52
+ else :
53
+ yield each
54
+
55
+
56
+ def from_traversable (root : Traversable ) -> Iterable [tuple [URI , Resource [Any ]]]:
57
+ """
58
+ Load some resources from a given `importlib.resources` traversable.
59
+
60
+ (I.e. load schemas from data within a Python package.)
61
+ """
62
+ return _from_walked (
63
+ each
64
+ for each in _walk_traversable (root )
65
+ if not each .name .endswith (".py" )
66
+ )
67
+
68
+
69
+ def _from_walked (
70
+ paths : Iterable [Path | Traversable ],
71
+ ) -> Iterable [tuple [URI , Resource [Any ]]]:
72
+ specification : Specification [Any ] | None = None
73
+ for path in paths :
74
+ contents = json .loads (path .read_text ())
75
+ if specification is None :
76
+ specification = Specification .detect (contents ) # type: ignore[reportUnknownMemberType]
77
+ resource = specification .detect (contents ).create_resource (contents )
78
+ yield getattr (path , "as_uri" , lambda : "" )(), resource
0 commit comments