fpathlib 0.1.3.dev0__py3-none-any.whl → 0.1.4.dev12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fpathlib/_version.py +2 -2
- fpathlib/expand.py +2 -1
- fpathlib/ext/polars.py +32 -0
- fpathlib/fpath.py +33 -1
- {fpathlib-0.1.3.dev0.dist-info → fpathlib-0.1.4.dev12.dist-info}/METADATA +1 -1
- fpathlib-0.1.4.dev12.dist-info/RECORD +13 -0
- fpathlib/__pycache__/__init__.cpython-313.pyc +0 -0
- fpathlib/__pycache__/path.cpython-313.pyc +0 -0
- fpathlib/__pycache__/utils.cpython-313.pyc +0 -0
- fpathlib/ext/__pycache__/__init__.cpython-313.pyc +0 -0
- fpathlib/ext/__pycache__/polars.cpython-313.pyc +0 -0
- fpathlib-0.1.3.dev0.dist-info/RECORD +0 -18
- {fpathlib-0.1.3.dev0.dist-info → fpathlib-0.1.4.dev12.dist-info}/WHEEL +0 -0
- {fpathlib-0.1.3.dev0.dist-info → fpathlib-0.1.4.dev12.dist-info}/licenses/LICENSE +0 -0
- {fpathlib-0.1.3.dev0.dist-info → fpathlib-0.1.4.dev12.dist-info}/top_level.txt +0 -0
fpathlib/_version.py
CHANGED
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.1.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
21
|
+
__version__ = version = '0.1.4.dev12'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 4, 'dev12')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
fpathlib/expand.py
CHANGED
|
@@ -88,7 +88,8 @@ def expand_fpath_decorator(f=None, require_expandable=True, post_process=None):
|
|
|
88
88
|
|
|
89
89
|
def is_expandable(fpath):
|
|
90
90
|
"""
|
|
91
|
-
Check
|
|
91
|
+
Check whether `fpath` has fpathlib's own named f-string captures (e.g.
|
|
92
|
+
`{name}`).
|
|
92
93
|
|
|
93
94
|
Parameters
|
|
94
95
|
----------
|
fpathlib/ext/polars.py
CHANGED
|
@@ -169,6 +169,7 @@ def scan_txt(
|
|
|
169
169
|
has_header=False,
|
|
170
170
|
keep_line=False,
|
|
171
171
|
usecols=None,
|
|
172
|
+
validate_schema=True,
|
|
172
173
|
*args,
|
|
173
174
|
**kwargs,
|
|
174
175
|
):
|
|
@@ -198,6 +199,17 @@ def scan_txt(
|
|
|
198
199
|
Whether to keep the original line as a column in the output.
|
|
199
200
|
usecols : :obj:`list`[:obj:`int`], optional
|
|
200
201
|
Indexes of columns to keep in the output. If not provided, all columns are kept. Only applicable if `separator` is provided.
|
|
202
|
+
validate_schema : :obj:`bool`
|
|
203
|
+
When the field count is inferred from a single representative file
|
|
204
|
+
(the fast path for a multi-file glob/pattern), also check that no
|
|
205
|
+
*other* matched file has *more* fields than that sample. A file with
|
|
206
|
+
fewer fields than the sample already raises a clear polars error
|
|
207
|
+
(out-of-bounds list access); a file with more fields would otherwise
|
|
208
|
+
have its extra columns silently dropped instead of erroring. This
|
|
209
|
+
check reads every matched file's line count, which costs an extra
|
|
210
|
+
full pass over the data on top of the fast path -- pass False if
|
|
211
|
+
you've already confirmed your files are consistent and want to
|
|
212
|
+
skip it for speed on very large globs. (Default: True)
|
|
201
213
|
*args
|
|
202
214
|
Positional arguments to pass to :meth:`polars.scan_csv`.
|
|
203
215
|
**kwargs
|
|
@@ -282,6 +294,26 @@ def scan_txt(
|
|
|
282
294
|
# Initial field names, may be renamed later from header or by `new_columns`
|
|
283
295
|
fields = {i: f"field_{i}" for i in range(n_fields)}
|
|
284
296
|
|
|
297
|
+
# n_fields came from a single sample file (see above), so a file
|
|
298
|
+
# with *fewer* fields than the sample will already raise a clear
|
|
299
|
+
# polars error below (list.get() on an out-of-bounds index). A
|
|
300
|
+
# file with *more* fields would not -- its extra columns would
|
|
301
|
+
# just be silently dropped -- so check for that explicitly if
|
|
302
|
+
# requested.
|
|
303
|
+
if validate_schema and sample_schema is not None:
|
|
304
|
+
max_fields = (
|
|
305
|
+
lf.select(_polars.col("fields").list.len().max())
|
|
306
|
+
.collect()
|
|
307
|
+
.item()
|
|
308
|
+
)
|
|
309
|
+
if max_fields is not None and max_fields > n_fields:
|
|
310
|
+
msg = (
|
|
311
|
+
f"field count mismatch: schema was inferred from a "
|
|
312
|
+
f"single sample file with {n_fields} fields, but at "
|
|
313
|
+
f"least one matched file has {max_fields} fields"
|
|
314
|
+
)
|
|
315
|
+
raise ValueError(msg)
|
|
316
|
+
|
|
285
317
|
# Add each field as a separate column
|
|
286
318
|
for i, field in fields.items():
|
|
287
319
|
lf = lf.with_columns(_polars.col("fields").list.get(i).alias(field))
|
fpathlib/fpath.py
CHANGED
|
@@ -58,6 +58,32 @@ class FPath:
|
|
|
58
58
|
|
|
59
59
|
parser = parse.compile(self.fpath)
|
|
60
60
|
|
|
61
|
+
# glob() (used below to find files) and `parse` (used above to
|
|
62
|
+
# extract {name} values) disagree about what a bare '*', '?', or
|
|
63
|
+
# '[...]' means outside a {} capture: glob treats it as a wildcard,
|
|
64
|
+
# but parse's format-string language only special-cases {...} and
|
|
65
|
+
# reads everything else -- including '*' -- as literal text to
|
|
66
|
+
# match. A pattern like "{a}/*" would find files fine via glob()
|
|
67
|
+
# but then fail to parse against that same string, since real
|
|
68
|
+
# filenames don't literally contain "/*" -- silently producing
|
|
69
|
+
# metadata=None for every match, or raising a confusing "metadata
|
|
70
|
+
# not found" error, with no indication that '*' was the actual
|
|
71
|
+
# problem. Fail fast and explain it instead. Only applies when
|
|
72
|
+
# there's a {} capture to begin with -- a plain glob with none is a
|
|
73
|
+
# separate, unaffected case (no metadata is expected from it).
|
|
74
|
+
if parser.named_fields:
|
|
75
|
+
literal_fpath = re.sub(r"\{.*?\}", "", self.fpath)
|
|
76
|
+
for c in "*?[":
|
|
77
|
+
if c in literal_fpath:
|
|
78
|
+
msg = (
|
|
79
|
+
f"glob wildcard {c!r} outside a {{}} capture is not "
|
|
80
|
+
f"supported in {self.fpath!r} -- 'parse' treats it "
|
|
81
|
+
"as a literal character, not a wildcard. Use a "
|
|
82
|
+
"named capture (e.g. '{a}/{b}') if you want that "
|
|
83
|
+
"segment captured too."
|
|
84
|
+
)
|
|
85
|
+
raise ValueError(msg)
|
|
86
|
+
|
|
61
87
|
paths = []
|
|
62
88
|
for fname in glob(re.sub(r"\{.*?\}", "*", self.fpath)):
|
|
63
89
|
path = Path(fname)
|
|
@@ -153,7 +179,13 @@ class ExpandedFPath(Sequence):
|
|
|
153
179
|
|
|
154
180
|
pl = import_optional_dependency("polars")
|
|
155
181
|
|
|
156
|
-
|
|
182
|
+
# `value` is None whenever this ExpandedFPath was built with
|
|
183
|
+
# require_metadata=False and a path's metadata simply wasn't found
|
|
184
|
+
# (e.g. a plain glob with no named captures at all) -- treat that as
|
|
185
|
+
# "no metadata columns" rather than crashing on `**None`.
|
|
186
|
+
data = [
|
|
187
|
+
{"fname": str(key), **(value or {})} for key, value in self.metadata.items()
|
|
188
|
+
]
|
|
157
189
|
df = pl.DataFrame(data)
|
|
158
190
|
if lazy:
|
|
159
191
|
df = df.lazy()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
fpathlib/__init__.py,sha256=VniZjNqT5pxzj6ymcpAlhNoWC44MwkQLu9jssc7o13Q,308
|
|
2
|
+
fpathlib/_version.py,sha256=xCkV2LVlX6YKEXfWlZphUkmo_tboft1yQfti1gQE5Dw,535
|
|
3
|
+
fpathlib/expand.py,sha256=jSkDZnGrEzSRGhKXp4G2uh6T0N-cJjt9oKGmOOjXalQ,3458
|
|
4
|
+
fpathlib/fpath.py,sha256=VhCLZAqCCiOVWSB_eQu7MQj0efBJX--DIMqXO-2n3Mw,6742
|
|
5
|
+
fpathlib/path.py,sha256=ME2jfMBCK1Emu35mu8wN-KvmPE4p8qQqX8q-uO5cDsI,2629
|
|
6
|
+
fpathlib/utils.py,sha256=os9ggFllqOZXYcjfKcxPIy92LuRfvt6jWL0gNfet1N0,545
|
|
7
|
+
fpathlib/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
fpathlib/ext/polars.py,sha256=lamkEI1CKW0g1n6jvj0aJug-ypyNqa_H3vdTb6YfmIo,12819
|
|
9
|
+
fpathlib-0.1.4.dev12.dist-info/licenses/LICENSE,sha256=76rZ9i4ZumZ1M4jlYM9ZDOTYEeyzuxdsTKjF2qha3Lc,1069
|
|
10
|
+
fpathlib-0.1.4.dev12.dist-info/METADATA,sha256=bvmweQlBt9HiLoAJK7qZ38IyclOD0a8kOhUUc_1RgdA,2142
|
|
11
|
+
fpathlib-0.1.4.dev12.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
12
|
+
fpathlib-0.1.4.dev12.dist-info/top_level.txt,sha256=QT5pDgO4--AJn7X4RB51xpNTt0pD5_U2mCjsydpQAQw,9
|
|
13
|
+
fpathlib-0.1.4.dev12.dist-info/RECORD,,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
fpathlib/__init__.py,sha256=VniZjNqT5pxzj6ymcpAlhNoWC44MwkQLu9jssc7o13Q,308
|
|
2
|
-
fpathlib/_version.py,sha256=dxsNQZw4RtnKvRTjSi1emxt4lZsN7c7hbUngeAYGVZY,533
|
|
3
|
-
fpathlib/expand.py,sha256=M_K1nfRAD9c983d68kCRuzo7-zNaOY_3R9gn8aBritI,3393
|
|
4
|
-
fpathlib/fpath.py,sha256=okEgqpWQjearSyDTp6RdIWbFolijI3BrXR8F5t-9Was,4877
|
|
5
|
-
fpathlib/path.py,sha256=ME2jfMBCK1Emu35mu8wN-KvmPE4p8qQqX8q-uO5cDsI,2629
|
|
6
|
-
fpathlib/utils.py,sha256=os9ggFllqOZXYcjfKcxPIy92LuRfvt6jWL0gNfet1N0,545
|
|
7
|
-
fpathlib/__pycache__/__init__.cpython-313.pyc,sha256=clLXRuVcvX9dJt4CTvaUBR6vhAzg67Ex7gKRwtumJFY,428
|
|
8
|
-
fpathlib/__pycache__/path.cpython-313.pyc,sha256=mQVWw1qjmvUp3NflXzhC_Q654H4hFW29gLYHP9nxRPQ,12257
|
|
9
|
-
fpathlib/__pycache__/utils.cpython-313.pyc,sha256=V4KSHMjm3ePQfaOKWwAkmaocvYb4VOul6Zooh0EvLa0,772
|
|
10
|
-
fpathlib/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
fpathlib/ext/polars.py,sha256=r3-MoGfbB11cOrECGCEyFzdKXGGEI9DSV6Xfc8vHeJo,10994
|
|
12
|
-
fpathlib/ext/__pycache__/__init__.cpython-313.pyc,sha256=lrgZbujuH_tlWGfe_Huo46srJdYJd1NQ6ZQFWamc6tc,153
|
|
13
|
-
fpathlib/ext/__pycache__/polars.cpython-313.pyc,sha256=S0epPPABmHRj0IrCxyOC8hD2_g0hBKggFFWfsmXw4m0,7740
|
|
14
|
-
fpathlib-0.1.3.dev0.dist-info/licenses/LICENSE,sha256=76rZ9i4ZumZ1M4jlYM9ZDOTYEeyzuxdsTKjF2qha3Lc,1069
|
|
15
|
-
fpathlib-0.1.3.dev0.dist-info/METADATA,sha256=EqyLMoPqqdMHwjd0To4_dc-o-wW2B2t6HmHel926ueM,2141
|
|
16
|
-
fpathlib-0.1.3.dev0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
17
|
-
fpathlib-0.1.3.dev0.dist-info/top_level.txt,sha256=QT5pDgO4--AJn7X4RB51xpNTt0pD5_U2mCjsydpQAQw,9
|
|
18
|
-
fpathlib-0.1.3.dev0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|