7
7
#
8
8
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
9
9
"""Create filename pairs, triplets etc, with expected extensions"""
10
+ from __future__ import annotations
11
+
10
12
import os
11
- import pathlib
13
+ import typing as ty
14
+
15
+ if ty .TYPE_CHECKING : # pragma: no cover
16
+ FileSpec = str | os .PathLike [str ]
17
+ ExtensionSpec = tuple [str , str | None ]
12
18
13
19
14
20
class TypesFilenamesError (Exception ):
15
21
pass
16
22
17
23
18
- def _stringify_path (filepath_or_buffer ) :
24
+ def _stringify_path (filepath_or_buffer : FileSpec ) -> str :
19
25
"""Attempt to convert a path-like object to a string.
20
26
21
27
Parameters
@@ -28,30 +34,21 @@ def _stringify_path(filepath_or_buffer):
28
34
29
35
Notes
30
36
-----
31
- Objects supporting the fspath protocol (python 3.6+) are coerced
32
- according to its __fspath__ method.
33
- For backwards compatibility with older pythons, pathlib.Path objects
34
- are specially coerced.
35
- Any other object is passed through unchanged, which includes bytes,
36
- strings, buffers, or anything else that's not even path-like.
37
-
38
- Copied from:
39
- https://github.com/pandas-dev/pandas/blob/325dd686de1589c17731cf93b649ed5ccb5a99b4/pandas/io/common.py#L131-L160
37
+ Adapted from:
38
+ https://github.com/pandas-dev/pandas/blob/325dd68/pandas/io/common.py#L131-L160
40
39
"""
41
- if hasattr (filepath_or_buffer , '__fspath__' ):
40
+ if isinstance (filepath_or_buffer , os . PathLike ):
42
41
return filepath_or_buffer .__fspath__ ()
43
- elif isinstance (filepath_or_buffer , pathlib .Path ):
44
- return str (filepath_or_buffer )
45
42
return filepath_or_buffer
46
43
47
44
48
45
def types_filenames (
49
- template_fname ,
50
- types_exts ,
51
- trailing_suffixes = ('.gz' , '.bz2' ),
52
- enforce_extensions = True ,
53
- match_case = False ,
54
- ):
46
+ template_fname : FileSpec ,
47
+ types_exts : ty . Sequence [ ExtensionSpec ] ,
48
+ trailing_suffixes : ty . Sequence [ str ] = ('.gz' , '.bz2' ),
49
+ enforce_extensions : bool = True ,
50
+ match_case : bool = False ,
51
+ ) -> dict [ str , str ] :
55
52
"""Return filenames with standard extensions from template name
56
53
57
54
The typical case is returning image and header filenames for an
@@ -152,12 +149,12 @@ def types_filenames(
152
149
# we've found .IMG as the extension, we want .HDR as the matching
153
150
# one. Let's only do this when the extension is all upper or all
154
151
# lower case.
155
- proc_ext = lambda s : s
152
+ proc_ext : ty . Callable [[ str ], str ] = lambda s : s
156
153
if found_ext :
157
154
if found_ext == found_ext .upper ():
158
- proc_ext = lambda s : s .upper ()
155
+ proc_ext = str .upper
159
156
elif found_ext == found_ext .lower ():
160
- proc_ext = lambda s : s .lower ()
157
+ proc_ext = str .lower
161
158
for name , ext in types_exts :
162
159
if name == direct_set_name :
163
160
tfns [name ] = template_fname
@@ -171,7 +168,12 @@ def types_filenames(
171
168
return tfns
172
169
173
170
174
- def parse_filename (filename , types_exts , trailing_suffixes , match_case = False ):
171
+ def parse_filename (
172
+ filename : FileSpec ,
173
+ types_exts : ty .Sequence [ExtensionSpec ],
174
+ trailing_suffixes : ty .Sequence [str ],
175
+ match_case : bool = False ,
176
+ ) -> tuple [str , str , str | None , str | None ]:
175
177
"""Split filename into fileroot, extension, trailing suffix; guess type.
176
178
177
179
Parameters
@@ -230,9 +232,9 @@ def parse_filename(filename, types_exts, trailing_suffixes, match_case=False):
230
232
break
231
233
guessed_name = None
232
234
found_ext = None
233
- for name , ext in types_exts :
234
- if ext and endswith (filename , ext ):
235
- extpos = - len (ext )
235
+ for name , type_ext in types_exts :
236
+ if type_ext and endswith (filename , type_ext ):
237
+ extpos = - len (type_ext )
236
238
found_ext = filename [extpos :]
237
239
filename = filename [:extpos ]
238
240
guessed_name = name
@@ -242,15 +244,19 @@ def parse_filename(filename, types_exts, trailing_suffixes, match_case=False):
242
244
return (filename , found_ext , ignored , guessed_name )
243
245
244
246
245
- def _endswith (whole , end ) :
247
+ def _endswith (whole : str , end : str ) -> bool :
246
248
return whole .endswith (end )
247
249
248
250
249
- def _iendswith (whole , end ) :
251
+ def _iendswith (whole : str , end : str ) -> bool :
250
252
return whole .lower ().endswith (end .lower ())
251
253
252
254
253
- def splitext_addext (filename , addexts = ('.gz' , '.bz2' , '.zst' ), match_case = False ):
255
+ def splitext_addext (
256
+ filename : FileSpec ,
257
+ addexts : ty .Sequence [str ] = ('.gz' , '.bz2' , '.zst' ),
258
+ match_case : bool = False ,
259
+ ) -> tuple [str , str , str ]:
254
260
"""Split ``/pth/fname.ext.gz`` into ``/pth/fname, .ext, .gz``
255
261
256
262
where ``.gz`` may be any of passed `addext` trailing suffixes.
0 commit comments