pyutilkit 0.3.0__tar.gz → 0.4.0__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.
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/PKG-INFO +1 -1
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/pyproject.toml +1 -1
- pyutilkit-0.4.0/src/pyutilkit/py.typed +0 -0
- pyutilkit-0.4.0/src/pyutilkit/timing.py +123 -0
- pyutilkit-0.3.0/src/pyutilkit/timing.py +0 -68
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/LICENSE.md +0 -0
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/docs/README.md +0 -0
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/src/pyutilkit/__init__.py +0 -0
- /pyutilkit-0.3.0/src/pyutilkit/data/__init__.py → /pyutilkit-0.4.0/src/pyutilkit/cache.py +0 -0
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/src/pyutilkit/classes.py +0 -0
- /pyutilkit-0.3.0/src/pyutilkit/py.typed → /pyutilkit-0.4.0/src/pyutilkit/data/__init__.py +0 -0
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/src/pyutilkit/data/timezones.py +0 -0
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/src/pyutilkit/date_utils.py +0 -0
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/src/pyutilkit/files.py +0 -0
- {pyutilkit-0.3.0 → pyutilkit-0.4.0}/src/pyutilkit/term.py +0 -0
|
File without changes
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
from __future__ import annotations # py3.9: remove this line
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from time import perf_counter_ns
|
|
5
|
+
from types import TracebackType
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from typing_extensions import Self # py3.10: import Self from typing
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True, order=True)
|
|
13
|
+
class Timing:
|
|
14
|
+
__slots__ = ("nanoseconds",) # py3.9: remove this line
|
|
15
|
+
|
|
16
|
+
nanoseconds: int
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
*,
|
|
21
|
+
days: int = 0,
|
|
22
|
+
seconds: int = 0,
|
|
23
|
+
milliseconds: int = 0,
|
|
24
|
+
microseconds: int = 0,
|
|
25
|
+
nanoseconds: int = 0,
|
|
26
|
+
) -> None:
|
|
27
|
+
total_nanoseconds = (
|
|
28
|
+
nanoseconds
|
|
29
|
+
+ 1000 * microseconds
|
|
30
|
+
+ 1_000_000 * milliseconds
|
|
31
|
+
+ 1_000_000_000 * seconds
|
|
32
|
+
+ 86_400_000_000_000 * days
|
|
33
|
+
)
|
|
34
|
+
object.__setattr__(self, "nanoseconds", total_nanoseconds)
|
|
35
|
+
|
|
36
|
+
def __str__(self) -> str:
|
|
37
|
+
if self.nanoseconds < 1000:
|
|
38
|
+
return f"{self.nanoseconds}ns"
|
|
39
|
+
microseconds = self.nanoseconds / 1000
|
|
40
|
+
if microseconds < 1000:
|
|
41
|
+
return f"{microseconds:.1f}µs"
|
|
42
|
+
milliseconds = microseconds / 1000
|
|
43
|
+
if milliseconds < 1000:
|
|
44
|
+
return f"{milliseconds:.1f}ms"
|
|
45
|
+
seconds = milliseconds / 1000
|
|
46
|
+
if seconds < 60:
|
|
47
|
+
return f"{seconds:.2f}s"
|
|
48
|
+
round_seconds = int(seconds)
|
|
49
|
+
minutes, seconds = divmod(round_seconds, 60)
|
|
50
|
+
hours, minutes = divmod(minutes, 60)
|
|
51
|
+
if hours < 24:
|
|
52
|
+
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
|
53
|
+
days, hours = divmod(hours, 24)
|
|
54
|
+
return f"{days:,}d {hours:02d}:{minutes:02d}:{seconds:02d}"
|
|
55
|
+
|
|
56
|
+
def __bool__(self) -> bool:
|
|
57
|
+
return bool(self.nanoseconds)
|
|
58
|
+
|
|
59
|
+
def __add__(self, other: Any) -> Timing:
|
|
60
|
+
if not isinstance(other, Timing):
|
|
61
|
+
return NotImplemented
|
|
62
|
+
return Timing(nanoseconds=self.nanoseconds + other.nanoseconds)
|
|
63
|
+
|
|
64
|
+
def __radd__(self, other: Any) -> Timing:
|
|
65
|
+
if not isinstance(other, Timing):
|
|
66
|
+
return NotImplemented
|
|
67
|
+
return Timing(nanoseconds=self.nanoseconds + other.nanoseconds)
|
|
68
|
+
|
|
69
|
+
def __mul__(self, other: Any) -> Timing:
|
|
70
|
+
if not isinstance(other, int):
|
|
71
|
+
return NotImplemented
|
|
72
|
+
return Timing(nanoseconds=self.nanoseconds * other)
|
|
73
|
+
|
|
74
|
+
def __rmul__(self, other: Any) -> Timing:
|
|
75
|
+
if not isinstance(other, int):
|
|
76
|
+
return NotImplemented
|
|
77
|
+
return Timing(nanoseconds=self.nanoseconds * other)
|
|
78
|
+
|
|
79
|
+
def __floordiv__(self, other: Any) -> Timing:
|
|
80
|
+
if not isinstance(other, int):
|
|
81
|
+
return NotImplemented
|
|
82
|
+
return Timing(nanoseconds=self.nanoseconds // other)
|
|
83
|
+
|
|
84
|
+
def __truediv__(self, other: Any) -> Timing:
|
|
85
|
+
if not isinstance(other, int):
|
|
86
|
+
return NotImplemented
|
|
87
|
+
return Timing(nanoseconds=self.nanoseconds // other)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Stopwatch:
|
|
91
|
+
_start: int
|
|
92
|
+
laps: list[Timing]
|
|
93
|
+
|
|
94
|
+
def __init__(self) -> None:
|
|
95
|
+
self._start = 0
|
|
96
|
+
self.laps: list[Timing] = []
|
|
97
|
+
|
|
98
|
+
def __enter__(self) -> Self:
|
|
99
|
+
self._start = perf_counter_ns()
|
|
100
|
+
return self
|
|
101
|
+
|
|
102
|
+
def __exit__(
|
|
103
|
+
self,
|
|
104
|
+
exc_type: type[Exception] | None,
|
|
105
|
+
exc_value: Exception | None,
|
|
106
|
+
traceback: TracebackType | None,
|
|
107
|
+
) -> None:
|
|
108
|
+
_end = perf_counter_ns()
|
|
109
|
+
self.laps.append(Timing(nanoseconds=_end - self._start))
|
|
110
|
+
|
|
111
|
+
def __bool__(self) -> bool:
|
|
112
|
+
return bool(self.elapsed)
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def elapsed(self) -> Timing:
|
|
116
|
+
return sum(self.laps, Timing())
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def average(self) -> Timing:
|
|
120
|
+
if not self.laps:
|
|
121
|
+
msg = "No laps recorded"
|
|
122
|
+
raise ZeroDivisionError(msg)
|
|
123
|
+
return self.elapsed // len(self.laps)
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations # py3.9: remove this line
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from time import perf_counter_ns
|
|
5
|
-
from types import TracebackType
|
|
6
|
-
from typing import TYPE_CHECKING
|
|
7
|
-
|
|
8
|
-
if TYPE_CHECKING:
|
|
9
|
-
from typing_extensions import Self # py3.10: import Self from typing
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@dataclass(frozen=True, order=True)
|
|
13
|
-
class Timing:
|
|
14
|
-
__slots__ = ("nanoseconds",) # py3.9: remove this line
|
|
15
|
-
|
|
16
|
-
nanoseconds: int
|
|
17
|
-
|
|
18
|
-
def __init__(
|
|
19
|
-
self,
|
|
20
|
-
*,
|
|
21
|
-
days: int = 0,
|
|
22
|
-
seconds: int = 0,
|
|
23
|
-
milliseconds: int = 0,
|
|
24
|
-
microseconds: int = 0,
|
|
25
|
-
nanoseconds: int = 0,
|
|
26
|
-
) -> None:
|
|
27
|
-
total_nanoseconds = (
|
|
28
|
-
nanoseconds
|
|
29
|
-
+ 1000 * microseconds
|
|
30
|
-
+ 1_000_000 * milliseconds
|
|
31
|
-
+ 1_000_000_000 * seconds
|
|
32
|
-
+ 86_400_000_000_000 * days
|
|
33
|
-
)
|
|
34
|
-
object.__setattr__(self, "nanoseconds", total_nanoseconds)
|
|
35
|
-
|
|
36
|
-
def __str__(self) -> str:
|
|
37
|
-
if self.nanoseconds < 1000:
|
|
38
|
-
return f"{self.nanoseconds}ns"
|
|
39
|
-
microseconds = self.nanoseconds / 1000
|
|
40
|
-
if microseconds < 1000:
|
|
41
|
-
return f"{microseconds:.1f}µs"
|
|
42
|
-
milliseconds = microseconds / 1000
|
|
43
|
-
if milliseconds < 1000:
|
|
44
|
-
return f"{milliseconds:.1f}ms"
|
|
45
|
-
seconds = milliseconds / 1000
|
|
46
|
-
return f"{seconds:,.2f}s"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class Stopwatch:
|
|
50
|
-
_start: int
|
|
51
|
-
timing: Timing
|
|
52
|
-
|
|
53
|
-
def __init__(self) -> None:
|
|
54
|
-
self._start = 0
|
|
55
|
-
self.timing = Timing(nanoseconds=0)
|
|
56
|
-
|
|
57
|
-
def __enter__(self) -> Self:
|
|
58
|
-
self._start = perf_counter_ns()
|
|
59
|
-
return self
|
|
60
|
-
|
|
61
|
-
def __exit__(
|
|
62
|
-
self,
|
|
63
|
-
exc_type: type[Exception] | None,
|
|
64
|
-
exc_value: Exception | None,
|
|
65
|
-
traceback: TracebackType | None,
|
|
66
|
-
) -> None:
|
|
67
|
-
_end = perf_counter_ns()
|
|
68
|
-
self.timing = Timing(nanoseconds=_end - self._start)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|