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