1
1
import abc
2
- from typing import BinaryIO , Iterable , Text
2
+ import io
3
+ import os
4
+ from typing import Any , BinaryIO , Iterable , Iterator , NoReturn , Text , Optional
3
5
from typing import runtime_checkable , Protocol
6
+ from typing import Union
7
+
8
+
9
+ StrPath = Union [str , os .PathLike [str ]]
10
+
11
+ __all__ = ["ResourceReader" , "Traversable" , "TraversableResources" ]
4
12
5
13
6
14
class ResourceReader (metaclass = abc .ABCMeta ):
@@ -50,22 +58,25 @@ class Traversable(Protocol):
50
58
"""
51
59
An object with a subset of pathlib.Path methods suitable for
52
60
traversing directories and opening files.
61
+
62
+ Any exceptions that occur when accessing the backing resource
63
+ may propagate unaltered.
53
64
"""
54
65
55
66
@abc .abstractmethod
56
- def iterdir (self ):
67
+ def iterdir (self ) -> Iterator [ "Traversable" ] :
57
68
"""
58
69
Yield Traversable objects in self
59
70
"""
60
71
61
- def read_bytes (self ):
72
+ def read_bytes (self ) -> bytes :
62
73
"""
63
74
Read contents of self as bytes
64
75
"""
65
76
with self .open ('rb' ) as strm :
66
77
return strm .read ()
67
78
68
- def read_text (self , encoding = None ):
79
+ def read_text (self , encoding : Optional [ str ] = None ) -> str :
69
80
"""
70
81
Read contents of self as text
71
82
"""
@@ -85,12 +96,16 @@ def is_file(self) -> bool:
85
96
"""
86
97
87
98
@abc .abstractmethod
88
- def joinpath (self , child ) :
99
+ def joinpath (self , * descendants : StrPath ) -> "Traversable" :
89
100
"""
90
- Return Traversable child in self
101
+ Return Traversable resolved with any descendants applied.
102
+
103
+ Each descendant should be a path segment relative to self
104
+ and each may contain multiple levels separated by
105
+ ``posixpath.sep`` (``/``).
91
106
"""
92
107
93
- def __truediv__ (self , child ) :
108
+ def __truediv__ (self , child : StrPath ) -> "Traversable" :
94
109
"""
95
110
Return Traversable child in self
96
111
"""
@@ -120,17 +135,17 @@ class TraversableResources(ResourceReader):
120
135
"""
121
136
122
137
@abc .abstractmethod
123
- def files (self ):
138
+ def files (self ) -> "Traversable" :
124
139
"""Return a Traversable object for the loaded package."""
125
140
126
- def open_resource (self , resource ) :
141
+ def open_resource (self , resource : StrPath ) -> io . BufferedReader :
127
142
return self .files ().joinpath (resource ).open ('rb' )
128
143
129
- def resource_path (self , resource ) :
144
+ def resource_path (self , resource : Any ) -> NoReturn :
130
145
raise FileNotFoundError (resource )
131
146
132
- def is_resource (self , path ) :
147
+ def is_resource (self , path : StrPath ) -> bool :
133
148
return self .files ().joinpath (path ).is_file ()
134
149
135
- def contents (self ):
150
+ def contents (self ) -> Iterator [ str ] :
136
151
return (item .name for item in self .files ().iterdir ())
0 commit comments