pathlibutil 0.3.6__tar.gz → 0.3.8__tar.gz
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.
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/PKG-INFO +7 -6
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/README.md +1 -0
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/pathlibutil/base.py +8 -3
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/pathlibutil/path.py +94 -32
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/pathlibutil/types.py +36 -23
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/pyproject.toml +30 -32
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/LICENSE +0 -0
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/pathlibutil/__init__.py +0 -0
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/pathlibutil/json.py +0 -0
- {pathlibutil-0.3.6 → pathlibutil-0.3.8}/pathlibutil/urlpath.py +0 -0
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: pathlibutil
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
4
4
|
Summary: inherits from pathlib.Path with methods for hashing, copying, deleting and more
|
|
5
5
|
License: MIT
|
|
6
|
-
|
|
7
|
-
Keywords: pathlib,hashlib,shutil,urllib.parse,json,urlpath
|
|
6
|
+
Keywords: hashlib,json,pathlib,shutil,urllib.parse,urlpath
|
|
8
7
|
Author: Christoph Dörrer
|
|
9
8
|
Author-email: d-chris@web.de
|
|
10
|
-
Requires-Python: >=3.8
|
|
9
|
+
Requires-Python: >=3.8,<4.0
|
|
11
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
12
11
|
Classifier: Operating System :: OS Independent
|
|
13
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.9
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
21
20
|
Provides-Extra: 7z
|
|
22
21
|
Requires-Dist: py7zr (>=0.20.2) ; extra == "7z"
|
|
22
|
+
Requires-Dist: typing-extensions (>=4.13.2)
|
|
23
23
|
Project-URL: documentation, https://d-chris.github.io/pathlibutil
|
|
24
24
|
Project-URL: repository, https://github.com/d-chris/pathlibutil
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
@@ -66,6 +66,7 @@ filename: ./README.md
|
|
|
66
66
|
- `Path.iterdir()` with `recursive` all files from the directory tree will be yielded and `exclude_dirs` via callable.
|
|
67
67
|
- `Path.is_expired()` to check if a file is expired by a given `datetime.timedelta`
|
|
68
68
|
- `Path.expand()` yields file paths for multiple file patterns if they exsits.
|
|
69
|
+
- `Path.with_anchor()` to change the anchor of a path object, e.g. for UNC paths on Windows.
|
|
69
70
|
|
|
70
71
|
JSON serialization of `Path` objects is supported in `pathlibutil.json`.
|
|
71
72
|
|
|
@@ -40,6 +40,7 @@ filename: ./README.md
|
|
|
40
40
|
- `Path.iterdir()` with `recursive` all files from the directory tree will be yielded and `exclude_dirs` via callable.
|
|
41
41
|
- `Path.is_expired()` to check if a file is expired by a given `datetime.timedelta`
|
|
42
42
|
- `Path.expand()` yields file paths for multiple file patterns if they exsits.
|
|
43
|
+
- `Path.with_anchor()` to change the anchor of a path object, e.g. for UNC paths on Windows.
|
|
43
44
|
|
|
44
45
|
JSON serialization of `Path` objects is supported in `pathlibutil.json`.
|
|
45
46
|
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import os
|
|
2
4
|
import pathlib
|
|
3
5
|
import sys
|
|
4
|
-
|
|
6
|
+
import typing as t
|
|
7
|
+
|
|
8
|
+
if t.TYPE_CHECKING:
|
|
9
|
+
from typing_extensions import Self
|
|
5
10
|
|
|
6
11
|
|
|
7
12
|
class BasePath(pathlib.Path):
|
|
@@ -17,7 +22,7 @@ class BasePath(pathlib.Path):
|
|
|
17
22
|
)
|
|
18
23
|
|
|
19
24
|
@classmethod
|
|
20
|
-
def expand(cls, file: str) -> Generator[
|
|
25
|
+
def expand(cls, file: str) -> t.Generator[Self, None, None]:
|
|
21
26
|
"""
|
|
22
27
|
yields only Path object of file names that exists. Supports glob patterns in
|
|
23
28
|
filename as wildcards.
|
|
@@ -31,7 +36,7 @@ class BasePath(pathlib.Path):
|
|
|
31
36
|
BasePath('pathlibutil/__init__.py')]
|
|
32
37
|
"""
|
|
33
38
|
|
|
34
|
-
file = cls(file)
|
|
39
|
+
file = cls(file) # type: Self
|
|
35
40
|
try:
|
|
36
41
|
file.resolve(True)
|
|
37
42
|
except (OSError, FileNotFoundError):
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import errno
|
|
2
4
|
import hashlib
|
|
3
5
|
import itertools
|
|
@@ -6,11 +8,16 @@ import re
|
|
|
6
8
|
import shutil
|
|
7
9
|
import subprocess
|
|
8
10
|
import sys
|
|
11
|
+
import typing as t
|
|
9
12
|
from datetime import datetime, timedelta
|
|
10
|
-
from typing import Callable, Dict, Generator, List, Literal, Set, Tuple, Union
|
|
11
13
|
|
|
12
14
|
from pathlibutil.base import BasePath
|
|
13
|
-
from pathlibutil.types import ByteInt, StatResult, TimeInt,
|
|
15
|
+
from pathlibutil.types import ByteInt, StatResult, TimeInt, byteint
|
|
16
|
+
|
|
17
|
+
if t.TYPE_CHECKING:
|
|
18
|
+
from typing_extensions import Self
|
|
19
|
+
|
|
20
|
+
from pathlibutil.types import _stat_result
|
|
14
21
|
|
|
15
22
|
|
|
16
23
|
class Path(BasePath):
|
|
@@ -28,7 +35,7 @@ class Path(BasePath):
|
|
|
28
35
|
```
|
|
29
36
|
"""
|
|
30
37
|
|
|
31
|
-
_archive_formats: Dict[str, Callable] = {}
|
|
38
|
+
_archive_formats: t.Dict[str, t.Callable] = {}
|
|
32
39
|
"""
|
|
33
40
|
Dict holding function to register shutil archive formats.
|
|
34
41
|
"""
|
|
@@ -57,7 +64,7 @@ class Path(BasePath):
|
|
|
57
64
|
pass
|
|
58
65
|
|
|
59
66
|
@property
|
|
60
|
-
def algorithms_available(self) -> Set[str]:
|
|
67
|
+
def algorithms_available(self) -> t.Set[str]:
|
|
61
68
|
"""
|
|
62
69
|
Set of `hashlib.algorithms_available` that can be passed to `hexdigest()`,
|
|
63
70
|
`verify()` method as `algorithm` parameter or to set the `default_hash`
|
|
@@ -72,7 +79,12 @@ class Path(BasePath):
|
|
|
72
79
|
"""
|
|
73
80
|
return hashlib.algorithms_available
|
|
74
81
|
|
|
75
|
-
def hexdigest(
|
|
82
|
+
def hexdigest(
|
|
83
|
+
self,
|
|
84
|
+
algorithm: t.Optional[str] = None,
|
|
85
|
+
/,
|
|
86
|
+
**kwargs,
|
|
87
|
+
) -> str:
|
|
76
88
|
"""
|
|
77
89
|
Returns the hexdigest of the file using the named algorithm (default:
|
|
78
90
|
`default_hash`).
|
|
@@ -101,7 +113,12 @@ class Path(BasePath):
|
|
|
101
113
|
return hash.hexdigest(length)
|
|
102
114
|
|
|
103
115
|
def verify(
|
|
104
|
-
self,
|
|
116
|
+
self,
|
|
117
|
+
digest: str,
|
|
118
|
+
algorithm: t.Optional[str] = None,
|
|
119
|
+
*,
|
|
120
|
+
strict: bool = True,
|
|
121
|
+
**kwargs,
|
|
105
122
|
) -> bool:
|
|
106
123
|
"""
|
|
107
124
|
Verifies the hash of the file using the named algorithm (default:
|
|
@@ -130,7 +147,7 @@ class Path(BasePath):
|
|
|
130
147
|
|
|
131
148
|
return True
|
|
132
149
|
|
|
133
|
-
def __enter__(self) ->
|
|
150
|
+
def __enter__(self) -> Self:
|
|
134
151
|
"""
|
|
135
152
|
Contextmanager to changes the current working directory.
|
|
136
153
|
"""
|
|
@@ -154,7 +171,7 @@ class Path(BasePath):
|
|
|
154
171
|
finally:
|
|
155
172
|
del self.__stack
|
|
156
173
|
|
|
157
|
-
def read_lines(self, **kwargs) -> Generator[str, None, None]:
|
|
174
|
+
def read_lines(self, **kwargs) -> t.Generator[str, None, None]:
|
|
158
175
|
"""
|
|
159
176
|
Iterates over all lines of the file until EOF is reached.
|
|
160
177
|
|
|
@@ -175,7 +192,12 @@ class Path(BasePath):
|
|
|
175
192
|
|
|
176
193
|
return super().stat(**kwargs).st_size
|
|
177
194
|
|
|
178
|
-
def copy(
|
|
195
|
+
def copy(
|
|
196
|
+
self,
|
|
197
|
+
dst: str,
|
|
198
|
+
exist_ok: bool = True,
|
|
199
|
+
**kwargs,
|
|
200
|
+
) -> Self:
|
|
179
201
|
"""
|
|
180
202
|
Copies the file or directory to a destination directory, if it is missing it
|
|
181
203
|
will be created.
|
|
@@ -200,7 +222,11 @@ class Path(BasePath):
|
|
|
200
222
|
return self.__class__(_path)
|
|
201
223
|
|
|
202
224
|
def delete(
|
|
203
|
-
self,
|
|
225
|
+
self,
|
|
226
|
+
*,
|
|
227
|
+
recursive: bool = False,
|
|
228
|
+
missing_ok: bool = False,
|
|
229
|
+
**kwargs,
|
|
204
230
|
) -> None:
|
|
205
231
|
"""
|
|
206
232
|
Deletes the file or directory.
|
|
@@ -227,7 +253,7 @@ class Path(BasePath):
|
|
|
227
253
|
|
|
228
254
|
shutil.rmtree(self, **kwargs)
|
|
229
255
|
|
|
230
|
-
def move(self, dst: str) ->
|
|
256
|
+
def move(self, dst: str) -> Self:
|
|
231
257
|
"""
|
|
232
258
|
Moves the file or directory into the destination directory.
|
|
233
259
|
|
|
@@ -247,7 +273,7 @@ class Path(BasePath):
|
|
|
247
273
|
return self.__class__(_path)
|
|
248
274
|
|
|
249
275
|
@staticmethod
|
|
250
|
-
def _find_archive_format(filename:
|
|
276
|
+
def _find_archive_format(filename: Path) -> str:
|
|
251
277
|
"""
|
|
252
278
|
Searches for a file the correct archive format.
|
|
253
279
|
"""
|
|
@@ -272,8 +298,12 @@ class Path(BasePath):
|
|
|
272
298
|
register_format()
|
|
273
299
|
|
|
274
300
|
def make_archive(
|
|
275
|
-
self,
|
|
276
|
-
|
|
301
|
+
self,
|
|
302
|
+
archivename: str,
|
|
303
|
+
*,
|
|
304
|
+
exists_ok: bool = False,
|
|
305
|
+
**kwargs,
|
|
306
|
+
) -> Self:
|
|
277
307
|
"""
|
|
278
308
|
Creates an archive file (eg. zip) and returns the path to the archive.
|
|
279
309
|
|
|
@@ -296,7 +326,10 @@ class Path(BasePath):
|
|
|
296
326
|
Path('test.zpy')
|
|
297
327
|
"""
|
|
298
328
|
|
|
299
|
-
def _archive_exists(
|
|
329
|
+
def _archive_exists(
|
|
330
|
+
file: str,
|
|
331
|
+
exists_ok: bool,
|
|
332
|
+
) -> Self:
|
|
300
333
|
"""
|
|
301
334
|
Returns a `Path` object of the archive file or raises a `FileExistsError`
|
|
302
335
|
If `exists_ok` is `True` the file will be deleted.
|
|
@@ -311,7 +344,10 @@ class Path(BasePath):
|
|
|
311
344
|
|
|
312
345
|
return file
|
|
313
346
|
|
|
314
|
-
def _archive_filename(
|
|
347
|
+
def _archive_filename(
|
|
348
|
+
expect: Path,
|
|
349
|
+
real: str,
|
|
350
|
+
) -> Self:
|
|
315
351
|
"""
|
|
316
352
|
Check if the expected archive filename matches the real filename.
|
|
317
353
|
If not try to rename the real filename.
|
|
@@ -346,7 +382,7 @@ class Path(BasePath):
|
|
|
346
382
|
|
|
347
383
|
return _archive_filename(_filename, _archive)
|
|
348
384
|
|
|
349
|
-
def unpack_archive(self, extract_dir: str, **kwargs) ->
|
|
385
|
+
def unpack_archive(self, extract_dir: str, **kwargs) -> Self:
|
|
350
386
|
"""
|
|
351
387
|
Unpacks an archive file (eg. zip) into a directory and returns the path to the
|
|
352
388
|
extracted files.
|
|
@@ -376,7 +412,7 @@ class Path(BasePath):
|
|
|
376
412
|
self._register_format(_format)
|
|
377
413
|
|
|
378
414
|
@property
|
|
379
|
-
def archive_formats(self) -> Set[str]:
|
|
415
|
+
def archive_formats(self) -> t.Set[str]:
|
|
380
416
|
"""
|
|
381
417
|
Returns a set with names of the supported archive formats.
|
|
382
418
|
|
|
@@ -405,7 +441,7 @@ class Path(BasePath):
|
|
|
405
441
|
"""
|
|
406
442
|
return StatResult(super().stat(**kwargs))
|
|
407
443
|
|
|
408
|
-
def with_suffix(self, suffix: Union[str, List[str]]) ->
|
|
444
|
+
def with_suffix(self, suffix: t.Union[str, t.List[str]]) -> Self:
|
|
409
445
|
"""
|
|
410
446
|
Return a new `Path` with changed suffix or remove it when its an empty
|
|
411
447
|
string.
|
|
@@ -444,8 +480,10 @@ class Path(BasePath):
|
|
|
444
480
|
return super(self.__class__, stem).with_suffix(suffix)
|
|
445
481
|
|
|
446
482
|
def relative_to(
|
|
447
|
-
self,
|
|
448
|
-
|
|
483
|
+
self,
|
|
484
|
+
*other: t.Union[str, Path],
|
|
485
|
+
walk_up: t.Union[bool, int] = False,
|
|
486
|
+
) -> Self:
|
|
449
487
|
"""
|
|
450
488
|
Return the relative path to another path identified by the passed
|
|
451
489
|
arguments. If the operation is not possible (because this is not
|
|
@@ -485,7 +523,11 @@ class Path(BasePath):
|
|
|
485
523
|
return relative
|
|
486
524
|
|
|
487
525
|
@classmethod
|
|
488
|
-
def cwd(
|
|
526
|
+
def cwd(
|
|
527
|
+
cls,
|
|
528
|
+
*,
|
|
529
|
+
frozen: t.Literal[True, False, "_MEIPASS"] = False,
|
|
530
|
+
) -> Self:
|
|
489
531
|
"""
|
|
490
532
|
Return a `Path` object representing the current working directory.
|
|
491
533
|
|
|
@@ -505,7 +547,7 @@ class Path(BasePath):
|
|
|
505
547
|
return super().cwd()
|
|
506
548
|
|
|
507
549
|
@classmethod
|
|
508
|
-
def _net_use(cls) -> Dict[str, str]:
|
|
550
|
+
def _net_use(cls) -> t.Dict[str, str]:
|
|
509
551
|
"""
|
|
510
552
|
Return a dictionary of mapped network drives. Keys are UNC paths and values
|
|
511
553
|
are drive letters.
|
|
@@ -536,7 +578,7 @@ class Path(BasePath):
|
|
|
536
578
|
except Exception:
|
|
537
579
|
return {}
|
|
538
580
|
|
|
539
|
-
def _resolve_unc(self) ->
|
|
581
|
+
def _resolve_unc(self) -> Self:
|
|
540
582
|
"""
|
|
541
583
|
Resolve UNC paths to mapped network drives.
|
|
542
584
|
"""
|
|
@@ -549,7 +591,11 @@ class Path(BasePath):
|
|
|
549
591
|
except KeyError:
|
|
550
592
|
return self
|
|
551
593
|
|
|
552
|
-
def resolve(
|
|
594
|
+
def resolve(
|
|
595
|
+
self,
|
|
596
|
+
strict: bool = False,
|
|
597
|
+
unc: bool = True,
|
|
598
|
+
) -> Self:
|
|
553
599
|
"""
|
|
554
600
|
Make the path absolute, resolving all symlinks on the way and also normalizing
|
|
555
601
|
it.
|
|
@@ -577,9 +623,9 @@ class Path(BasePath):
|
|
|
577
623
|
def walk(
|
|
578
624
|
self,
|
|
579
625
|
top_down: bool = True,
|
|
580
|
-
on_error: Callable[[OSError], object] = None,
|
|
626
|
+
on_error: t.Callable[[OSError], object] = None,
|
|
581
627
|
follow_symlinks: bool = False,
|
|
582
|
-
) -> Generator[Tuple[
|
|
628
|
+
) -> t.Generator[t.Tuple[Self, t.List[str], t.List[str]], None, None]:
|
|
583
629
|
"""
|
|
584
630
|
Walks the directory tree and yields a 3-tuple of (dirpath, dirnames, filenames).
|
|
585
631
|
"""
|
|
@@ -601,10 +647,10 @@ class Path(BasePath):
|
|
|
601
647
|
def iterdir(
|
|
602
648
|
self,
|
|
603
649
|
*,
|
|
604
|
-
recursive: Union[bool, int] = False,
|
|
605
|
-
exclude_dirs: Callable[[
|
|
650
|
+
recursive: t.Union[bool, int] = False,
|
|
651
|
+
exclude_dirs: t.Callable[[Path], bool] = None,
|
|
606
652
|
**kwargs,
|
|
607
|
-
) -> Generator[
|
|
653
|
+
) -> t.Generator[Self, None, None]:
|
|
608
654
|
"""
|
|
609
655
|
Iterates over the files in the directory.
|
|
610
656
|
|
|
@@ -636,7 +682,12 @@ class Path(BasePath):
|
|
|
636
682
|
else:
|
|
637
683
|
yield from super().iterdir()
|
|
638
684
|
|
|
639
|
-
def is_expired(
|
|
685
|
+
def is_expired(
|
|
686
|
+
self,
|
|
687
|
+
*,
|
|
688
|
+
stat: str = "st_mtime",
|
|
689
|
+
**kwargs,
|
|
690
|
+
) -> bool:
|
|
640
691
|
"""
|
|
641
692
|
Returns `True` if the time of the file is greater than a given threshold.
|
|
642
693
|
|
|
@@ -660,7 +711,7 @@ class Path(BasePath):
|
|
|
660
711
|
cls,
|
|
661
712
|
*files: str,
|
|
662
713
|
duplicates: bool = True,
|
|
663
|
-
) -> Generator[
|
|
714
|
+
) -> t.Generator[Self, None, None]:
|
|
664
715
|
"""
|
|
665
716
|
Yields only Path object of file names that exists. Supports glob patterns in
|
|
666
717
|
filename as wildcards.
|
|
@@ -682,6 +733,17 @@ class Path(BasePath):
|
|
|
682
733
|
seen.add(item)
|
|
683
734
|
yield item
|
|
684
735
|
|
|
736
|
+
def with_anchor(self, anchor: t.Union[str, os.PathLike]) -> Self:
|
|
737
|
+
"""
|
|
738
|
+
Returns a new `Path` object with the given anchor.
|
|
739
|
+
|
|
740
|
+
>>> Path("README.md").with_anchor("C:\\")
|
|
741
|
+
Path('C:/README.md')
|
|
742
|
+
"""
|
|
743
|
+
relpath = self.relative_to(self.anchor)
|
|
744
|
+
|
|
745
|
+
return self.__class__(anchor).joinpath(relpath)
|
|
746
|
+
|
|
685
747
|
|
|
686
748
|
class Register7zFormat(Path, archive="7z"):
|
|
687
749
|
"""
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import functools
|
|
2
4
|
import os
|
|
3
5
|
import re
|
|
6
|
+
import typing as t
|
|
4
7
|
from datetime import datetime, tzinfo
|
|
5
|
-
from typing import Iterable, Set, Tuple, TypeVar
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
if t.TYPE_CHECKING:
|
|
10
|
+
from typing_extensions import Self
|
|
11
|
+
|
|
12
|
+
_ByteInt = t.TypeVar("_ByteInt", bound="ByteInt")
|
|
13
|
+
_stat_result = t.TypeVar("_stat_result", bound="os.stat_result")
|
|
9
14
|
|
|
10
15
|
|
|
11
16
|
class ByteInt(int):
|
|
@@ -49,7 +54,7 @@ class ByteInt(int):
|
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
@property
|
|
52
|
-
def units(self) -> Set[str]:
|
|
57
|
+
def units(self) -> t.Set[str]:
|
|
53
58
|
"""
|
|
54
59
|
`decimal` and `binary` units for measuring storage data.
|
|
55
60
|
|
|
@@ -73,7 +78,7 @@ class ByteInt(int):
|
|
|
73
78
|
def __str__(self) -> str:
|
|
74
79
|
return self.string()
|
|
75
80
|
|
|
76
|
-
def string(self, decimal=True) -> str:
|
|
81
|
+
def string(self, decimal: bool = True) -> str:
|
|
77
82
|
"""
|
|
78
83
|
Return a string representation of `self` in the most appropriate unit.
|
|
79
84
|
|
|
@@ -101,7 +106,7 @@ class ByteInt(int):
|
|
|
101
106
|
return f"{int(self)} b"
|
|
102
107
|
|
|
103
108
|
@classmethod
|
|
104
|
-
def info(cls, unit: str) -> Tuple[int, str]:
|
|
109
|
+
def info(cls, unit: str) -> t.Tuple[int, str]:
|
|
105
110
|
"""
|
|
106
111
|
Return a tuple containing `bytes` and `name` for a given `unit`
|
|
107
112
|
|
|
@@ -137,61 +142,61 @@ class ByteInt(int):
|
|
|
137
142
|
|
|
138
143
|
return value.__format__(self.__regex.sub("f", __format_spec, 1))
|
|
139
144
|
|
|
140
|
-
def __add__(self, other: int) ->
|
|
145
|
+
def __add__(self, other: int) -> Self:
|
|
141
146
|
"""
|
|
142
147
|
b + 1
|
|
143
148
|
"""
|
|
144
149
|
return self.__class__(super().__add__(other))
|
|
145
150
|
|
|
146
|
-
def __iadd__(self, other: int) ->
|
|
151
|
+
def __iadd__(self, other: int) -> Self:
|
|
147
152
|
"""
|
|
148
153
|
b += 1
|
|
149
154
|
"""
|
|
150
155
|
return self.__add__(other)
|
|
151
156
|
|
|
152
|
-
def __sub__(self, other: int) ->
|
|
157
|
+
def __sub__(self, other: int) -> Self:
|
|
153
158
|
"""
|
|
154
159
|
b - 1
|
|
155
160
|
"""
|
|
156
161
|
return self.__class__(super().__sub__(other))
|
|
157
162
|
|
|
158
|
-
def __isub__(self, other: int) ->
|
|
163
|
+
def __isub__(self, other: int) -> Self:
|
|
159
164
|
"""
|
|
160
165
|
b -=1
|
|
161
166
|
"""
|
|
162
167
|
return self.__sub__(other)
|
|
163
168
|
|
|
164
|
-
def __mul__(self, other: int) ->
|
|
169
|
+
def __mul__(self, other: int) -> Self:
|
|
165
170
|
"""
|
|
166
171
|
b * 1
|
|
167
172
|
"""
|
|
168
173
|
return self.__class__(super().__mul__(other))
|
|
169
174
|
|
|
170
|
-
def __imul__(self, other: int) ->
|
|
175
|
+
def __imul__(self, other: int) -> Self:
|
|
171
176
|
"""
|
|
172
177
|
b *= 1
|
|
173
178
|
"""
|
|
174
179
|
return self.__mul__(other)
|
|
175
180
|
|
|
176
|
-
def __floordiv__(self, other: int) ->
|
|
181
|
+
def __floordiv__(self, other: int) -> Self:
|
|
177
182
|
"""
|
|
178
183
|
b // 1
|
|
179
184
|
"""
|
|
180
185
|
return self.__class__(super().__floordiv__(other))
|
|
181
186
|
|
|
182
|
-
def __ifloordiv__(self, other: int) ->
|
|
187
|
+
def __ifloordiv__(self, other: int) -> Self:
|
|
183
188
|
"""
|
|
184
189
|
b //= 1
|
|
185
190
|
"""
|
|
186
191
|
return self.__floordiv__(other)
|
|
187
192
|
|
|
188
|
-
def __mod__(self, other: int) ->
|
|
193
|
+
def __mod__(self, other: int) -> Self:
|
|
189
194
|
"""
|
|
190
195
|
b % 1
|
|
191
196
|
"""
|
|
192
197
|
return self.__class__(super().__mod__(other))
|
|
193
198
|
|
|
194
|
-
def __imod__(self, other: int) ->
|
|
199
|
+
def __imod__(self, other: int) -> Self:
|
|
195
200
|
"""
|
|
196
201
|
b %= 1
|
|
197
202
|
"""
|
|
@@ -247,19 +252,27 @@ class TimeInt(float):
|
|
|
247
252
|
'1970-01-01 00:00:00'
|
|
248
253
|
"""
|
|
249
254
|
|
|
250
|
-
format = "%Y-%m-%d %H:%M:%S"
|
|
255
|
+
format: str = "%Y-%m-%d %H:%M:%S"
|
|
251
256
|
"""
|
|
252
257
|
Format string to which is uesed to convert `self` to a string. Default: 'isoformat'.
|
|
253
258
|
For more information see `datetime.datetime.strftime`.
|
|
254
259
|
"""
|
|
255
260
|
|
|
256
|
-
def __new__(
|
|
261
|
+
def __new__(
|
|
262
|
+
cls,
|
|
263
|
+
value: int,
|
|
264
|
+
tz: t.Optional[tzinfo] = None,
|
|
265
|
+
) -> float:
|
|
257
266
|
"""
|
|
258
267
|
Create a new instance from baseclass `int`.
|
|
259
268
|
"""
|
|
260
269
|
return super().__new__(cls, value)
|
|
261
270
|
|
|
262
|
-
def __init__(
|
|
271
|
+
def __init__(
|
|
272
|
+
self,
|
|
273
|
+
value: int,
|
|
274
|
+
tz: t.Optional[tzinfo] = None,
|
|
275
|
+
) -> None:
|
|
263
276
|
"""
|
|
264
277
|
Create a new instance from baseclass `int` with optional `timezone` info.
|
|
265
278
|
"""
|
|
@@ -283,7 +296,7 @@ class TimeInt(float):
|
|
|
283
296
|
"""
|
|
284
297
|
return self.string()
|
|
285
298
|
|
|
286
|
-
def string(self, format_string: str = None) -> str:
|
|
299
|
+
def string(self, format_string: t.Optional[str] = None) -> str:
|
|
287
300
|
"""
|
|
288
301
|
Return a string representation of `datetime` using the `format_string`.
|
|
289
302
|
|
|
@@ -301,13 +314,13 @@ class StatResult:
|
|
|
301
314
|
to prevent subclassing.
|
|
302
315
|
"""
|
|
303
316
|
|
|
304
|
-
def __init__(self, stat):
|
|
317
|
+
def __init__(self, stat: os.stat_result) -> None:
|
|
305
318
|
"""
|
|
306
319
|
Wrapper for `os.stat_result`.
|
|
307
320
|
"""
|
|
308
321
|
self._obj = stat
|
|
309
322
|
|
|
310
|
-
def __getattr__(self, name):
|
|
323
|
+
def __getattr__(self, name: str) -> t.Any:
|
|
311
324
|
"""
|
|
312
325
|
Forward all unknown attributes to `self._obj`.
|
|
313
326
|
"""
|
|
@@ -334,7 +347,7 @@ class StatResult:
|
|
|
334
347
|
"""
|
|
335
348
|
return repr(self._obj)
|
|
336
349
|
|
|
337
|
-
def __dir__(self) ->
|
|
350
|
+
def __dir__(self) -> t.Iterator[str]:
|
|
338
351
|
"""
|
|
339
352
|
Return a list of attributes of `os.stat_result` object.
|
|
340
353
|
"""
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
build-backend = "poetry.core.masonry.api"
|
|
3
|
-
|
|
4
3
|
requires = [ "poetry-core" ]
|
|
5
4
|
|
|
6
5
|
[tool.poetry]
|
|
7
6
|
name = "pathlibutil"
|
|
8
|
-
version = "v0.3.
|
|
7
|
+
version = "v0.3.8"
|
|
9
8
|
description = "inherits from pathlib.Path with methods for hashing, copying, deleting and more"
|
|
9
|
+
license = "MIT"
|
|
10
10
|
authors = [ "Christoph Dörrer <d-chris@web.de>" ]
|
|
11
11
|
readme = "README.md"
|
|
12
|
-
|
|
12
|
+
keywords = [ "hashlib", "json", "pathlib", "shutil", "urllib.parse", "urlpath" ]
|
|
13
13
|
classifiers = [
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
14
16
|
"Programming Language :: Python :: 3.8",
|
|
15
17
|
"Programming Language :: Python :: 3.9",
|
|
16
18
|
"Programming Language :: Python :: 3.10",
|
|
@@ -18,36 +20,26 @@ classifiers = [
|
|
|
18
20
|
"Programming Language :: Python :: 3.12",
|
|
19
21
|
"Programming Language :: Python :: 3.13",
|
|
20
22
|
"Programming Language :: Python :: 3.14",
|
|
21
|
-
"License :: OSI Approved :: MIT License",
|
|
22
|
-
"Operating System :: OS Independent",
|
|
23
23
|
]
|
|
24
|
-
keywords = [ "pathlib", "hashlib", "shutil", "urllib.parse", "json", "urlpath" ]
|
|
25
|
-
|
|
26
|
-
[tool.poetry.urls]
|
|
27
|
-
repository = "https://github.com/d-chris/pathlibutil"
|
|
28
|
-
documentation = "https://d-chris.github.io/pathlibutil"
|
|
29
24
|
|
|
30
25
|
[tool.poetry.dependencies]
|
|
31
|
-
python = "^3.8
|
|
26
|
+
python = "^3.8"
|
|
32
27
|
py7zr = { version = ">=0.20.2", optional = true }
|
|
28
|
+
typing-extensions = ">=4.13.2"
|
|
33
29
|
|
|
34
30
|
[tool.poetry.extras]
|
|
35
31
|
7z = [ "py7zr" ]
|
|
36
32
|
|
|
37
|
-
[tool.poetry.group.
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
[tool.poetry.group.docs.dependencies]
|
|
34
|
+
jinja2-pdoc = { version = "^1.3.0", python = ">=3.8.1" }
|
|
35
|
+
pyperclip = "^1.9.0"
|
|
40
36
|
|
|
41
37
|
[tool.poetry.group.test.dependencies]
|
|
38
|
+
exrex = ">=0.12.0"
|
|
42
39
|
pytest = ">=8.3.3"
|
|
43
|
-
pytest-random-order = ">=1.1.0"
|
|
44
40
|
pytest-cov = ">=4.1.0"
|
|
45
41
|
pytest-mock = ">=3.12.0"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
[tool.poetry.group.docs.dependencies]
|
|
49
|
-
jinja2-pdoc = ">=1.1.0"
|
|
50
|
-
pyperclip = ">=1.9.0"
|
|
42
|
+
pytest-random-order = ">=1.1.0"
|
|
51
43
|
|
|
52
44
|
[[tool.poetry.source]]
|
|
53
45
|
name = "PyPI"
|
|
@@ -58,13 +50,21 @@ name = "testpypi"
|
|
|
58
50
|
url = "https://test.pypi.org/legacy/"
|
|
59
51
|
priority = "explicit"
|
|
60
52
|
|
|
53
|
+
[tool.poetry.urls]
|
|
54
|
+
documentation = "https://d-chris.github.io/pathlibutil"
|
|
55
|
+
repository = "https://github.com/d-chris/pathlibutil"
|
|
56
|
+
|
|
61
57
|
[tool.isort]
|
|
62
58
|
profile = "black"
|
|
63
59
|
|
|
64
|
-
[tool.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
[tool.pyproject-fmt]
|
|
61
|
+
tool_format = "short"
|
|
62
|
+
expand_tables = [ "tool.poetry" ]
|
|
63
|
+
|
|
64
|
+
[tool.pytest]
|
|
65
|
+
ini_options.minversion = "6.0"
|
|
66
|
+
ini_options.testpaths = "tests"
|
|
67
|
+
ini_options.addopts = [
|
|
68
68
|
"--random-order",
|
|
69
69
|
"--color=yes",
|
|
70
70
|
"-s",
|
|
@@ -73,14 +73,12 @@ addopts = [
|
|
|
73
73
|
"--cov-report=xml",
|
|
74
74
|
]
|
|
75
75
|
|
|
76
|
-
[tool.coverage
|
|
77
|
-
|
|
78
|
-
"^def normalize_url",
|
|
79
|
-
]
|
|
80
|
-
|
|
81
|
-
[tool.coverage.run]
|
|
82
|
-
omit = [
|
|
83
|
-
"*/tests/*",
|
|
76
|
+
[tool.coverage]
|
|
77
|
+
run.omit = [
|
|
84
78
|
"*/docs/*",
|
|
85
79
|
"*/examples/*",
|
|
80
|
+
"*/tests/*",
|
|
81
|
+
]
|
|
82
|
+
report.exclude_lines = [
|
|
83
|
+
"^def normalize_url",
|
|
86
84
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|