77#
88### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
99"""Create filename pairs, triplets etc, with expected extensions"""
10+ from __future__ import annotations
11+
1012import 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 ]
1218
1319
1420class TypesFilenamesError (Exception ):
1521 pass
1622
1723
18- def _stringify_path (filepath_or_buffer ) :
24+ def _stringify_path (filepath_or_buffer : FileSpec ) -> str :
1925 """Attempt to convert a path-like object to a string.
2026
2127 Parameters
@@ -28,30 +34,21 @@ def _stringify_path(filepath_or_buffer):
2834
2935 Notes
3036 -----
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
4039 """
41- if hasattr (filepath_or_buffer , '__fspath__' ):
40+ if isinstance (filepath_or_buffer , os . PathLike ):
4241 return filepath_or_buffer .__fspath__ ()
43- elif isinstance (filepath_or_buffer , pathlib .Path ):
44- return str (filepath_or_buffer )
4542 return filepath_or_buffer
4643
4744
4845def 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 ] :
5552 """Return filenames with standard extensions from template name
5653
5754 The typical case is returning image and header filenames for an
@@ -152,12 +149,12 @@ def types_filenames(
152149 # we've found .IMG as the extension, we want .HDR as the matching
153150 # one. Let's only do this when the extension is all upper or all
154151 # lower case.
155- proc_ext = lambda s : s
152+ proc_ext : ty . Callable [[ str ], str ] = lambda s : s
156153 if found_ext :
157154 if found_ext == found_ext .upper ():
158- proc_ext = lambda s : s .upper ()
155+ proc_ext = str .upper
159156 elif found_ext == found_ext .lower ():
160- proc_ext = lambda s : s .lower ()
157+ proc_ext = str .lower
161158 for name , ext in types_exts :
162159 if name == direct_set_name :
163160 tfns [name ] = template_fname
@@ -171,7 +168,12 @@ def types_filenames(
171168 return tfns
172169
173170
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 ]:
175177 """Split filename into fileroot, extension, trailing suffix; guess type.
176178
177179 Parameters
@@ -230,9 +232,9 @@ def parse_filename(filename, types_exts, trailing_suffixes, match_case=False):
230232 break
231233 guessed_name = None
232234 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 )
236238 found_ext = filename [extpos :]
237239 filename = filename [:extpos ]
238240 guessed_name = name
@@ -242,15 +244,19 @@ def parse_filename(filename, types_exts, trailing_suffixes, match_case=False):
242244 return (filename , found_ext , ignored , guessed_name )
243245
244246
245- def _endswith (whole , end ) :
247+ def _endswith (whole : str , end : str ) -> bool :
246248 return whole .endswith (end )
247249
248250
249- def _iendswith (whole , end ) :
251+ def _iendswith (whole : str , end : str ) -> bool :
250252 return whole .lower ().endswith (end .lower ())
251253
252254
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 ]:
254260 """Split ``/pth/fname.ext.gz`` into ``/pth/fname, .ext, .gz``
255261
256262 where ``.gz`` may be any of passed `addext` trailing suffixes.
0 commit comments