1
+ import functools
1
2
import sys
3
+ import typing
4
+ from enum import Enum
5
+ from functools import partial
6
+ from pathlib import PurePath
2
7
from typing import Any
8
+ from typing import Callable
3
9
from typing import Dict
4
10
from typing import Iterable
5
11
from typing import List
12
+ from typing import Literal
13
+ from typing import Optional
6
14
from typing import Tuple
7
15
from typing import Type
8
16
from typing import Union
9
17
10
- if sys .version_info >= (3 , 8 ):
11
- from typing import Literal
12
- else :
13
- from typing_extensions import Literal
14
18
if sys .version_info >= (3 , 12 ):
15
19
from typing import TypeAlias
16
20
else :
17
21
from typing_extensions import TypeAlias
18
22
19
- import functools
20
- from enum import Enum
21
- from functools import partial
22
- from pathlib import PurePath
23
- from typing import Callable
24
- from typing import Optional
25
-
26
23
import attr
27
24
28
25
import fgpyo .util .types as types
@@ -60,18 +57,24 @@ def split_at_given_level(
60
57
decrease_in_depth += high_level_split .count (char )
61
58
outer_depth_of_split += increase_in_depth - decrease_in_depth
62
59
63
- assert outer_depth_of_split >= 0 , "Unpaired depth character! Likely incorrect output"
60
+ assert (
61
+ outer_depth_of_split >= 0
62
+ ), "Unpaired depth character! Likely incorrect output"
64
63
65
64
current_outer_splits .append (high_level_split )
66
65
if outer_depth_of_split == 0 :
67
66
out_vals .append (split_delim .join (current_outer_splits ))
68
67
current_outer_splits = []
69
- assert outer_depth_of_split == 0 , "Unpaired depth character! Likely incorrect output!"
68
+ assert (
69
+ outer_depth_of_split == 0
70
+ ), "Unpaired depth character! Likely incorrect output!"
70
71
return out_vals
71
72
72
73
73
74
def _get_parser (
74
- cls : Type , type_ : TypeAlias , parsers : Optional [Dict [type , Callable [[str ], Any ]]] = None
75
+ cls : Type ,
76
+ type_ : TypeAlias ,
77
+ parsers : Optional [Dict [type , Callable [[str ], Any ]]] = None ,
75
78
) -> partial :
76
79
"""Attempts to find a parser for a provided type.
77
80
@@ -109,8 +112,8 @@ def get_parser() -> partial:
109
112
raise ValueError ("Unable to parse set (try typing.Set[type])" )
110
113
elif type_ == dict :
111
114
raise ValueError ("Unable to parse dict (try typing.Mapping[type])" )
112
- elif types . get_origin_type (type_ ) == list :
113
- subtypes = types . get_arg_types (type_ )
115
+ elif typing . get_origin (type_ ) == list :
116
+ subtypes = typing . get_args (type_ )
114
117
115
118
assert (
116
119
len (subtypes ) == 1
@@ -130,8 +133,8 @@ def get_parser() -> partial:
130
133
]
131
134
)
132
135
)
133
- elif types . get_origin_type (type_ ) == set :
134
- subtypes = types . get_arg_types (type_ )
136
+ elif typing . get_origin (type_ ) == set :
137
+ subtypes = typing . get_args (type_ )
135
138
assert (
136
139
len (subtypes ) == 1
137
140
), "Sets are allowed only one subtype per PEP specification!"
@@ -146,18 +149,20 @@ def get_parser() -> partial:
146
149
if s == "{}"
147
150
else [
148
151
subtype_parser (item )
149
- for item in set (split_at_given_level (s [1 :- 1 ], split_delim = "," ))
152
+ for item in set (
153
+ split_at_given_level (s [1 :- 1 ], split_delim = "," )
154
+ )
150
155
]
151
156
)
152
157
)
153
- elif types . get_origin_type (type_ ) == tuple :
158
+ elif typing . get_origin (type_ ) == tuple :
154
159
subtype_parsers = [
155
160
_get_parser (
156
161
cls ,
157
162
subtype ,
158
163
parsers ,
159
164
)
160
- for subtype in types . get_arg_types (type_ )
165
+ for subtype in typing . get_args (type_ )
161
166
]
162
167
163
168
def tuple_parse (tuple_string : str ) -> Tuple [Any , ...]:
@@ -172,16 +177,18 @@ def tuple_parse(tuple_string: str) -> Tuple[Any, ...]:
172
177
if len (tuple_string ) == 0 :
173
178
return ()
174
179
else :
175
- val_strings = split_at_given_level (tuple_string , split_delim = "," )
180
+ val_strings = split_at_given_level (
181
+ tuple_string , split_delim = ","
182
+ )
176
183
return tuple (
177
184
parser (val_str )
178
185
for parser , val_str in zip (subtype_parsers , val_strings )
179
186
)
180
187
181
188
return functools .partial (tuple_parse )
182
189
183
- elif types . get_origin_type (type_ ) == dict :
184
- subtypes = types . get_arg_types (type_ )
190
+ elif typing . get_origin (type_ ) == dict :
191
+ subtypes = typing . get_args (type_ )
185
192
assert (
186
193
len (subtypes ) == 2
187
194
), "Dict object must have exactly 2 subtypes per PEP specification!"
@@ -208,10 +215,14 @@ def dict_parse(dict_string: str) -> Dict[Any, Any]:
208
215
if len (dict_string ) == 0 :
209
216
return {}
210
217
else :
211
- outer_splits = split_at_given_level (dict_string , split_delim = "," )
218
+ outer_splits = split_at_given_level (
219
+ dict_string , split_delim = ","
220
+ )
212
221
out_dict = {}
213
222
for outer_split in outer_splits :
214
- inner_splits = split_at_given_level (outer_split , split_delim = ";" )
223
+ inner_splits = split_at_given_level (
224
+ outer_split , split_delim = ";"
225
+ )
215
226
assert (
216
227
len (inner_splits ) % 2 == 0
217
228
), "Inner splits of dict didn't have matched key val pairs"
@@ -228,15 +239,21 @@ def dict_parse(dict_string: str) -> Dict[Any, Any]:
228
239
return functools .partial (type_ )
229
240
elif isinstance (type_ , type (type (None ))):
230
241
return functools .partial (types .none_parser )
231
- elif types . get_origin_type (type_ ) is Union :
242
+ elif typing . get_origin (type_ ) is Union :
232
243
return types .make_union_parser (
233
244
union = type_ ,
234
- parsers = [_get_parser (cls , arg , parsers ) for arg in types .get_arg_types (type_ )],
245
+ parsers = [
246
+ _get_parser (cls , arg , parsers )
247
+ for arg in typing .get_args (type_ )
248
+ ],
235
249
)
236
- elif types . get_origin_type (type_ ) is Literal : # Py>=3.7.
250
+ elif typing . get_origin (type_ ) is Literal : # Py>=3.7.
237
251
return types .make_literal_parser (
238
252
type_ ,
239
- [_get_parser (cls , type (arg ), parsers ) for arg in types .get_arg_types (type_ )],
253
+ [
254
+ _get_parser (cls , type (arg ), parsers )
255
+ for arg in typing .get_args (type_ )
256
+ ],
240
257
)
241
258
else :
242
259
raise ParserNotFoundException (
@@ -255,7 +272,9 @@ def dict_parse(dict_string: str) -> Dict[Any, Any]:
255
272
256
273
257
274
def attr_from (
258
- cls : Type , kwargs : Dict [str , str ], parsers : Optional [Dict [type , Callable [[str ], Any ]]] = None
275
+ cls : Type ,
276
+ kwargs : Dict [str , str ],
277
+ parsers : Optional [Dict [type , Callable [[str ], Any ]]] = None ,
259
278
) -> Any :
260
279
"""Builds an attr class from key-word arguments
261
280
@@ -289,7 +308,11 @@ def attr_from(
289
308
# try setting by casting
290
309
# Note that while bools *can* be cast from string, all non-empty strings evaluate to
291
310
# True, because python, so we need to check for that explicitly
292
- if not set_value and attribute .type is not None and not attribute .type == bool :
311
+ if (
312
+ not set_value
313
+ and attribute .type is not None
314
+ and not attribute .type == bool
315
+ ):
293
316
try :
294
317
return_value = attribute .type (str_value )
295
318
set_value = True
@@ -316,8 +339,8 @@ def attr_from(
316
339
317
340
def attribute_is_optional (attribute : attr .Attribute ) -> bool :
318
341
"""Returns True if the attribute is optional, False otherwise"""
319
- return types . get_origin_type (attribute .type ) is Union and isinstance (
320
- None , types . get_arg_types (attribute .type )
342
+ return typing . get_origin (attribute .type ) is Union and isinstance (
343
+ None , typing . get_args (attribute .type )
321
344
)
322
345
323
346
0 commit comments