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
+ FileSpec = ty .Union [str , os .PathLike [str ]]
16
+ ExtensionSpec = ty .Tuple [str , str | None ]
13
17
14
18
15
19
class TypesFilenamesError (Exception ):
16
20
pass
17
21
18
22
19
- def _stringify_path (filepath_or_buffer ) :
23
+ def _stringify_path (filepath_or_buffer : FileSpec ) -> str :
20
24
"""Attempt to convert a path-like object to a string.
21
25
22
26
Parameters
@@ -29,30 +33,21 @@ def _stringify_path(filepath_or_buffer):
29
33
30
34
Notes
31
35
-----
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:
36
+ Initially copied from:
40
37
https://github.com/pandas-dev/pandas/blob/325dd686de1589c17731cf93b649ed5ccb5a99b4/pandas/io/common.py#L131-L160
41
38
"""
42
- if hasattr (filepath_or_buffer , '__fspath__' ):
39
+ if isinstance (filepath_or_buffer , os . PathLike ):
43
40
return filepath_or_buffer .__fspath__ ()
44
- elif isinstance (filepath_or_buffer , pathlib .Path ):
45
- return str (filepath_or_buffer )
46
41
return filepath_or_buffer
47
42
48
43
49
44
def types_filenames (
50
- template_fname ,
51
- types_exts ,
52
- trailing_suffixes = ('.gz' , '.bz2' ),
53
- enforce_extensions = True ,
54
- match_case = False ,
55
- ):
45
+ template_fname : FileSpec ,
46
+ types_exts : ty . Sequence [ ExtensionSpec ] ,
47
+ trailing_suffixes : ty . Sequence [ str ] = ('.gz' , '.bz2' ),
48
+ enforce_extensions : bool = True ,
49
+ match_case : bool = False ,
50
+ ) -> dict [ str , str ] :
56
51
"""Return filenames with standard extensions from template name
57
52
58
53
The typical case is returning image and header filenames for an
@@ -153,12 +148,12 @@ def types_filenames(
153
148
# we've found .IMG as the extension, we want .HDR as the matching
154
149
# one. Let's only do this when the extension is all upper or all
155
150
# lower case.
156
- proc_ext = lambda s : s
151
+ proc_ext : ty . Callable [[ str ], str ] = lambda s : s
157
152
if found_ext :
158
153
if found_ext == found_ext .upper ():
159
- proc_ext = lambda s : s .upper ()
154
+ proc_ext = str .upper
160
155
elif found_ext == found_ext .lower ():
161
- proc_ext = lambda s : s .lower ()
156
+ proc_ext = str .lower
162
157
for name , ext in types_exts :
163
158
if name == direct_set_name :
164
159
tfns [name ] = template_fname
@@ -172,7 +167,12 @@ def types_filenames(
172
167
return tfns
173
168
174
169
175
- def parse_filename (filename , types_exts , trailing_suffixes , match_case = False ):
170
+ def parse_filename (
171
+ filename : FileSpec ,
172
+ types_exts : ty .Sequence [ExtensionSpec ],
173
+ trailing_suffixes : ty .Sequence [str ],
174
+ match_case : bool = False ,
175
+ ) -> tuple [str , str , str | None , str | None ]:
176
176
"""Split filename into fileroot, extension, trailing suffix; guess type.
177
177
178
178
Parameters
@@ -231,9 +231,9 @@ def parse_filename(filename, types_exts, trailing_suffixes, match_case=False):
231
231
break
232
232
guessed_name = None
233
233
found_ext = None
234
- for name , ext in types_exts :
235
- if ext and endswith (filename , ext ):
236
- extpos = - len (ext )
234
+ for name , type_ext in types_exts :
235
+ if type_ext and endswith (filename , type_ext ):
236
+ extpos = - len (type_ext )
237
237
found_ext = filename [extpos :]
238
238
filename = filename [:extpos ]
239
239
guessed_name = name
@@ -243,15 +243,19 @@ def parse_filename(filename, types_exts, trailing_suffixes, match_case=False):
243
243
return (filename , found_ext , ignored , guessed_name )
244
244
245
245
246
- def _endswith (whole , end ) :
246
+ def _endswith (whole : str , end : str ) -> bool :
247
247
return whole .endswith (end )
248
248
249
249
250
- def _iendswith (whole , end ) :
250
+ def _iendswith (whole : str , end : str ) -> bool :
251
251
return whole .lower ().endswith (end .lower ())
252
252
253
253
254
- def splitext_addext (filename , addexts = ('.gz' , '.bz2' , '.zst' ), match_case = False ):
254
+ def splitext_addext (
255
+ filename : FileSpec ,
256
+ addexts : ty .Sequence [str ] = ('.gz' , '.bz2' , '.zst' ),
257
+ match_case : bool = False ,
258
+ ) -> tuple [str , str , str ]:
255
259
"""Split ``/pth/fname.ext.gz`` into ``/pth/fname, .ext, .gz``
256
260
257
261
where ``.gz`` may be any of passed `addext` trailing suffixes.
0 commit comments