stouputils 1.18.0__py3-none-any.whl → 1.18.2__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.
- stouputils/collections.py +35 -2
- stouputils/collections.pyi +33 -4
- stouputils/io.py +3 -3
- stouputils/io.pyi +1 -1
- stouputils/parallel/capturer.py +5 -6
- stouputils/parallel/subprocess.py +40 -18
- stouputils/parallel/subprocess.pyi +11 -1
- {stouputils-1.18.0.dist-info → stouputils-1.18.2.dist-info}/METADATA +1 -1
- {stouputils-1.18.0.dist-info → stouputils-1.18.2.dist-info}/RECORD +11 -11
- {stouputils-1.18.0.dist-info → stouputils-1.18.2.dist-info}/WHEEL +1 -1
- {stouputils-1.18.0.dist-info → stouputils-1.18.2.dist-info}/entry_points.txt +0 -0
stouputils/collections.py
CHANGED
|
@@ -132,16 +132,45 @@ def sort_dict_keys[T](dictionary: dict[T, Any], order: list[T], reverse: bool =
|
|
|
132
132
|
def upsert_in_dataframe(
|
|
133
133
|
df: "pl.DataFrame",
|
|
134
134
|
new_entry: dict[str, Any],
|
|
135
|
-
primary_keys: dict[str, Any] | None = None
|
|
135
|
+
primary_keys: list[str] | dict[str, Any] | None = None
|
|
136
136
|
) -> "pl.DataFrame":
|
|
137
137
|
""" Insert or update a row in the Polars DataFrame based on primary keys.
|
|
138
138
|
|
|
139
139
|
Args:
|
|
140
140
|
df (pl.DataFrame): The Polars DataFrame to update.
|
|
141
141
|
new_entry (dict[str, Any]): The new entry to insert or update.
|
|
142
|
-
primary_keys (dict[str, Any]): The primary keys to identify the row (
|
|
142
|
+
primary_keys (list[str] | dict[str, Any] | None): The primary keys to identify the row (for updates).
|
|
143
143
|
Returns:
|
|
144
144
|
pl.DataFrame: The updated Polars DataFrame.
|
|
145
|
+
Examples:
|
|
146
|
+
>>> import polars as pl
|
|
147
|
+
>>> df = pl.DataFrame({"id": [1, 2], "value": ["a", "b"]})
|
|
148
|
+
>>> new_entry = {"id": 2, "value": "updated"}
|
|
149
|
+
>>> updated_df = upsert_in_dataframe(df, new_entry, primary_keys=["id"])
|
|
150
|
+
>>> print(updated_df)
|
|
151
|
+
shape: (2, 2)
|
|
152
|
+
┌─────┬─────────┐
|
|
153
|
+
│ id ┆ value │
|
|
154
|
+
│ --- ┆ --- │
|
|
155
|
+
│ i64 ┆ str │
|
|
156
|
+
╞═════╪═════════╡
|
|
157
|
+
│ 1 ┆ a │
|
|
158
|
+
│ 2 ┆ updated │
|
|
159
|
+
└─────┴─────────┘
|
|
160
|
+
|
|
161
|
+
>>> new_entry = {"id": 3, "value": "new"}
|
|
162
|
+
>>> updated_df = upsert_in_dataframe(updated_df, new_entry, primary_keys=["id"])
|
|
163
|
+
>>> print(updated_df)
|
|
164
|
+
shape: (3, 2)
|
|
165
|
+
┌─────┬─────────┐
|
|
166
|
+
│ id ┆ value │
|
|
167
|
+
│ --- ┆ --- │
|
|
168
|
+
│ i64 ┆ str │
|
|
169
|
+
╞═════╪═════════╡
|
|
170
|
+
│ 1 ┆ a │
|
|
171
|
+
│ 2 ┆ updated │
|
|
172
|
+
│ 3 ┆ new │
|
|
173
|
+
└─────┴─────────┘
|
|
145
174
|
"""
|
|
146
175
|
# Imports
|
|
147
176
|
import polars as pl
|
|
@@ -155,6 +184,10 @@ def upsert_in_dataframe(
|
|
|
155
184
|
new_row_df = pl.DataFrame([new_entry])
|
|
156
185
|
return pl.concat([df, new_row_df], how="diagonal_relaxed")
|
|
157
186
|
|
|
187
|
+
# If primary keys are provided as a list, convert to dict with values from new_entry
|
|
188
|
+
if isinstance(primary_keys, list):
|
|
189
|
+
primary_keys = {key: new_entry[key] for key in primary_keys if key in new_entry}
|
|
190
|
+
|
|
158
191
|
# Build mask based on primary keys
|
|
159
192
|
mask: pl.Expr = pl.lit(True)
|
|
160
193
|
for key, value in primary_keys.items():
|
stouputils/collections.pyi
CHANGED
|
@@ -69,16 +69,45 @@ def sort_dict_keys[T](dictionary: dict[T, Any], order: list[T], reverse: bool =
|
|
|
69
69
|
\t\t>>> sort_dict_keys({\'b\': 2, \'a\': 1, \'c\': 3, \'d\': 4}, order=["c", "b"])
|
|
70
70
|
\t\t{\'c\': 3, \'b\': 2, \'a\': 1, \'d\': 4}
|
|
71
71
|
\t'''
|
|
72
|
-
def upsert_in_dataframe(df: pl.DataFrame, new_entry: dict[str, Any], primary_keys: dict[str, Any] | None = None) -> pl.DataFrame:
|
|
73
|
-
|
|
72
|
+
def upsert_in_dataframe(df: pl.DataFrame, new_entry: dict[str, Any], primary_keys: list[str] | dict[str, Any] | None = None) -> pl.DataFrame:
|
|
73
|
+
''' Insert or update a row in the Polars DataFrame based on primary keys.
|
|
74
74
|
|
|
75
75
|
\tArgs:
|
|
76
76
|
\t\tdf\t\t\t\t(pl.DataFrame):\t\tThe Polars DataFrame to update.
|
|
77
77
|
\t\tnew_entry\t\t(dict[str, Any]):\tThe new entry to insert or update.
|
|
78
|
-
\t\tprimary_keys\t(dict[str, Any]):\tThe primary keys to identify the row (
|
|
78
|
+
\t\tprimary_keys\t(list[str] | dict[str, Any] | None):\tThe primary keys to identify the row (for updates).
|
|
79
79
|
\tReturns:
|
|
80
80
|
\t\tpl.DataFrame: The updated Polars DataFrame.
|
|
81
|
-
\
|
|
81
|
+
\tExamples:
|
|
82
|
+
\t\t>>> import polars as pl
|
|
83
|
+
\t\t>>> df = pl.DataFrame({"id": [1, 2], "value": ["a", "b"]})
|
|
84
|
+
\t\t>>> new_entry = {"id": 2, "value": "updated"}
|
|
85
|
+
\t\t>>> updated_df = upsert_in_dataframe(df, new_entry, primary_keys=["id"])
|
|
86
|
+
\t\t>>> print(updated_df)
|
|
87
|
+
\t\tshape: (2, 2)
|
|
88
|
+
\t\t┌─────┬─────────┐
|
|
89
|
+
\t\t│ id ┆ value │
|
|
90
|
+
\t\t│ --- ┆ --- │
|
|
91
|
+
\t\t│ i64 ┆ str │
|
|
92
|
+
\t\t╞═════╪═════════╡
|
|
93
|
+
\t\t│ 1 ┆ a │
|
|
94
|
+
\t\t│ 2 ┆ updated │
|
|
95
|
+
\t\t└─────┴─────────┘
|
|
96
|
+
|
|
97
|
+
\t\t>>> new_entry = {"id": 3, "value": "new"}
|
|
98
|
+
\t\t>>> updated_df = upsert_in_dataframe(updated_df, new_entry, primary_keys=["id"])
|
|
99
|
+
\t\t>>> print(updated_df)
|
|
100
|
+
\t\tshape: (3, 2)
|
|
101
|
+
\t\t┌─────┬─────────┐
|
|
102
|
+
\t\t│ id ┆ value │
|
|
103
|
+
\t\t│ --- ┆ --- │
|
|
104
|
+
\t\t│ i64 ┆ str │
|
|
105
|
+
\t\t╞═════╪═════════╡
|
|
106
|
+
\t\t│ 1 ┆ a │
|
|
107
|
+
\t\t│ 2 ┆ updated │
|
|
108
|
+
\t\t│ 3 ┆ new │
|
|
109
|
+
\t\t└─────┴─────────┘
|
|
110
|
+
\t'''
|
|
82
111
|
def array_to_disk(data: NDArray[Any] | zarr.Array, delete_input: bool = True, more_data: NDArray[Any] | zarr.Array | None = None) -> tuple['zarr.Array', str, int]:
|
|
83
112
|
""" Easily handle large numpy arrays on disk using zarr for efficient storage and access.
|
|
84
113
|
|
stouputils/io.py
CHANGED
|
@@ -492,7 +492,7 @@ def clean_path(file_path: str, trailing_slash: bool = True) -> str:
|
|
|
492
492
|
# Return the cleaned path
|
|
493
493
|
return file_path if file_path != "." else ""
|
|
494
494
|
|
|
495
|
-
def safe_close(file: IO[Any] | int | None) -> None:
|
|
495
|
+
def safe_close(file: IO[Any] | int | Any | None) -> None:
|
|
496
496
|
""" Safely close a file object (or file descriptor) after flushing, ignoring any exceptions.
|
|
497
497
|
|
|
498
498
|
Args:
|
|
@@ -506,9 +506,9 @@ def safe_close(file: IO[Any] | int | None) -> None:
|
|
|
506
506
|
except Exception:
|
|
507
507
|
pass
|
|
508
508
|
elif file:
|
|
509
|
-
for func in (
|
|
509
|
+
for func in ("flush", "close"):
|
|
510
510
|
try:
|
|
511
|
-
func()
|
|
511
|
+
getattr(file, func)()
|
|
512
512
|
except Exception:
|
|
513
513
|
pass
|
|
514
514
|
|
stouputils/io.pyi
CHANGED
|
@@ -211,7 +211,7 @@ def clean_path(file_path: str, trailing_slash: bool = True) -> str:
|
|
|
211
211
|
\t\t>>> clean_path("C:/folder1\\\\folder2")
|
|
212
212
|
\t\t\'C:/folder1/folder2\'
|
|
213
213
|
\t'''
|
|
214
|
-
def safe_close(file: IO[Any] | int | None) -> None:
|
|
214
|
+
def safe_close(file: IO[Any] | int | Any | None) -> None:
|
|
215
215
|
""" Safely close a file object (or file descriptor) after flushing, ignoring any exceptions.
|
|
216
216
|
|
|
217
217
|
\tArgs:
|
stouputils/parallel/capturer.py
CHANGED
|
@@ -65,8 +65,7 @@ class CaptureOutput:
|
|
|
65
65
|
|
|
66
66
|
def parent_close_write(self) -> None:
|
|
67
67
|
""" Close the parent's copy of the write end; the child's copy remains. """
|
|
68
|
-
safe_close(self.
|
|
69
|
-
self.write_conn.close()
|
|
68
|
+
safe_close(self.write_conn)
|
|
70
69
|
self.write_fd = -1 # Prevent accidental reuse
|
|
71
70
|
|
|
72
71
|
def start_listener(self) -> None:
|
|
@@ -110,8 +109,7 @@ class CaptureOutput:
|
|
|
110
109
|
if len(buffer) > self.chunk_size * 4:
|
|
111
110
|
_handle_buffer()
|
|
112
111
|
finally:
|
|
113
|
-
safe_close(self.
|
|
114
|
-
self.read_conn.close()
|
|
112
|
+
safe_close(self.read_conn)
|
|
115
113
|
self.read_fd = -1
|
|
116
114
|
self._thread = None # Mark thread as stopped so callers don't block unnecessarily
|
|
117
115
|
|
|
@@ -123,8 +121,9 @@ class CaptureOutput:
|
|
|
123
121
|
def join_listener(self, timeout: float | None = None) -> None:
|
|
124
122
|
""" Wait for the listener thread to finish (until EOF). """
|
|
125
123
|
if self._thread is None:
|
|
126
|
-
safe_close(self.
|
|
127
|
-
|
|
124
|
+
safe_close(self.read_conn)
|
|
125
|
+
self.read_fd = -1
|
|
126
|
+
return
|
|
128
127
|
self._thread.join(timeout)
|
|
129
128
|
|
|
130
129
|
# If thread finished, ensure read fd is closed and clear thread
|
|
@@ -4,9 +4,20 @@ import time
|
|
|
4
4
|
from collections.abc import Callable
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
+
from ..typing import JsonDict
|
|
7
8
|
from .capturer import CaptureOutput
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
class RemoteSubprocessError(RuntimeError):
|
|
12
|
+
""" Raised in the parent when the child raised an exception - contains the child's formatted traceback. """
|
|
13
|
+
def __init__(self, exc_type: str, exc_repr: str, traceback_str: str):
|
|
14
|
+
msg = f"Exception in subprocess ({exc_type}): {exc_repr}\n\nRemote traceback:\n{traceback_str}"
|
|
15
|
+
super().__init__(msg)
|
|
16
|
+
self.remote_type = exc_type
|
|
17
|
+
self.remote_repr = exc_repr
|
|
18
|
+
self.remote_traceback = traceback_str
|
|
19
|
+
|
|
20
|
+
|
|
10
21
|
def run_in_subprocess[R](
|
|
11
22
|
func: Callable[..., R],
|
|
12
23
|
*args: Any,
|
|
@@ -37,7 +48,8 @@ def run_in_subprocess[R](
|
|
|
37
48
|
R: The return value of the function.
|
|
38
49
|
|
|
39
50
|
Raises:
|
|
40
|
-
|
|
51
|
+
RemoteSubprocessError: If the child raised an exception - contains the child's formatted traceback.
|
|
52
|
+
RuntimeError: If the subprocess exits with a non-zero exit code or did not return a result.
|
|
41
53
|
TimeoutError: If the subprocess exceeds the specified timeout.
|
|
42
54
|
|
|
43
55
|
Examples:
|
|
@@ -66,7 +78,7 @@ def run_in_subprocess[R](
|
|
|
66
78
|
from multiprocessing import Queue
|
|
67
79
|
|
|
68
80
|
# Create a queue to get the result from the subprocess (only if we need to wait)
|
|
69
|
-
result_queue: Queue[
|
|
81
|
+
result_queue: Queue[JsonDict] | None = None if no_join else Queue()
|
|
70
82
|
|
|
71
83
|
# Optionally setup output capture pipe and listener
|
|
72
84
|
capturer: CaptureOutput | None = None
|
|
@@ -105,23 +117,22 @@ def run_in_subprocess[R](
|
|
|
105
117
|
process.join()
|
|
106
118
|
raise TimeoutError(f"Subprocess exceeded timeout of {timeout} seconds and was terminated")
|
|
107
119
|
|
|
108
|
-
#
|
|
120
|
+
# Retrieve the payload if present
|
|
121
|
+
result_payload: JsonDict | None = result_queue.get_nowait() if not result_queue.empty() else None
|
|
122
|
+
|
|
123
|
+
# If the child sent a structured exception, raise it with the formatted traceback
|
|
124
|
+
if isinstance(result_payload, dict):
|
|
125
|
+
if result_payload.pop("ok", False) is False:
|
|
126
|
+
raise RemoteSubprocessError(**result_payload)
|
|
127
|
+
else:
|
|
128
|
+
return result_payload["result"]
|
|
129
|
+
|
|
130
|
+
# Raise an error according to the exit code presence
|
|
109
131
|
if process.exitcode != 0:
|
|
110
|
-
# Try to get any exception from the queue (non-blocking)
|
|
111
|
-
if not result_queue.empty():
|
|
112
|
-
result_or_exception = result_queue.get_nowait()
|
|
113
|
-
if isinstance(result_or_exception, Exception):
|
|
114
|
-
raise result_or_exception
|
|
115
132
|
raise RuntimeError(f"Subprocess failed with exit code {process.exitcode}")
|
|
133
|
+
raise RuntimeError("Subprocess did not return any result")
|
|
116
134
|
|
|
117
|
-
|
|
118
|
-
try:
|
|
119
|
-
result_or_exception = result_queue.get_nowait()
|
|
120
|
-
if isinstance(result_or_exception, Exception):
|
|
121
|
-
raise result_or_exception
|
|
122
|
-
return result_or_exception
|
|
123
|
-
except Exception as e:
|
|
124
|
-
raise RuntimeError("Subprocess did not return any result") from e
|
|
135
|
+
# Finally, ensure we drain/join the listener if capturing output
|
|
125
136
|
finally:
|
|
126
137
|
if capturer is not None:
|
|
127
138
|
capturer.join_listener(timeout=5.0)
|
|
@@ -154,10 +165,21 @@ def _subprocess_wrapper[R](
|
|
|
154
165
|
# Execute the target function and put the result in the queue
|
|
155
166
|
result: R = func(*args, **kwargs)
|
|
156
167
|
if result_queue is not None:
|
|
157
|
-
result_queue.put(result)
|
|
168
|
+
result_queue.put({"ok": True, "result": result})
|
|
158
169
|
|
|
159
170
|
# Handle cleanup and exceptions
|
|
160
171
|
except Exception as e:
|
|
161
172
|
if result_queue is not None:
|
|
162
|
-
|
|
173
|
+
try:
|
|
174
|
+
import traceback
|
|
175
|
+
tb = traceback.format_exc()
|
|
176
|
+
result_queue.put({
|
|
177
|
+
"ok": False,
|
|
178
|
+
"exc_type": e.__class__.__name__,
|
|
179
|
+
"exc_repr": repr(e),
|
|
180
|
+
"traceback_str": tb,
|
|
181
|
+
})
|
|
182
|
+
except Exception:
|
|
183
|
+
# Nothing we can do if even this fails
|
|
184
|
+
pass
|
|
163
185
|
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
from ..typing import JsonDict as JsonDict
|
|
1
2
|
from .capturer import CaptureOutput as CaptureOutput
|
|
3
|
+
from _typeshed import Incomplete
|
|
2
4
|
from collections.abc import Callable as Callable
|
|
3
5
|
from typing import Any
|
|
4
6
|
|
|
7
|
+
class RemoteSubprocessError(RuntimeError):
|
|
8
|
+
""" Raised in the parent when the child raised an exception - contains the child's formatted traceback. """
|
|
9
|
+
remote_type: Incomplete
|
|
10
|
+
remote_repr: Incomplete
|
|
11
|
+
remote_traceback: Incomplete
|
|
12
|
+
def __init__(self, exc_type: str, exc_repr: str, traceback_str: str) -> None: ...
|
|
13
|
+
|
|
5
14
|
def run_in_subprocess[R](func: Callable[..., R], *args: Any, timeout: float | None = None, no_join: bool = False, capture_output: bool = False, **kwargs: Any) -> R:
|
|
6
15
|
''' Execute a function in a subprocess with positional and keyword arguments.
|
|
7
16
|
|
|
@@ -25,7 +34,8 @@ def run_in_subprocess[R](func: Callable[..., R], *args: Any, timeout: float | No
|
|
|
25
34
|
\t\tR: The return value of the function.
|
|
26
35
|
|
|
27
36
|
\tRaises:
|
|
28
|
-
\t\
|
|
37
|
+
\t\tRemoteSubprocessError: If the child raised an exception - contains the child\'s formatted traceback.
|
|
38
|
+
\t\tRuntimeError: If the subprocess exits with a non-zero exit code or did not return a result.
|
|
29
39
|
\t\tTimeoutError: If the subprocess exceeds the specified timeout.
|
|
30
40
|
|
|
31
41
|
\tExamples:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: stouputils
|
|
3
|
-
Version: 1.18.
|
|
3
|
+
Version: 1.18.2
|
|
4
4
|
Summary: Stouputils is a collection of utility modules designed to simplify and enhance the development process. It includes a range of tools for tasks such as execution of doctests, display utilities, decorators, as well as context managers, and many more.
|
|
5
5
|
Keywords: utilities,tools,helpers,development,python
|
|
6
6
|
Author: Stoupy51
|
|
@@ -21,8 +21,8 @@ stouputils/archive.py,sha256=uDrPFxbY_C8SwUZRH4FWnYSoJKkFWynCx751zP9AHaY,12144
|
|
|
21
21
|
stouputils/archive.pyi,sha256=Z2BbQAiErRYntv53QC9uf_XPw3tx3Oy73wB0Bbil11c,3246
|
|
22
22
|
stouputils/backup.py,sha256=AE5WKMLiyk0VkRUfhmNfO2EUeUbZY5GTFVIuI5z7axA,20947
|
|
23
23
|
stouputils/backup.pyi,sha256=-SLVykkR5U8479T84zjNPVBNnV193s0zyWjathY2DDA,4923
|
|
24
|
-
stouputils/collections.py,sha256=
|
|
25
|
-
stouputils/collections.pyi,sha256=
|
|
24
|
+
stouputils/collections.py,sha256=73799uJ5ryQoNBo7N4Cz41Q992QP_kSsw_hy33ZpDyw,11121
|
|
25
|
+
stouputils/collections.pyi,sha256=jPzyaeesz1IqutuT69Bt4DFOguURjXbcYO2l2sifXRA,5448
|
|
26
26
|
stouputils/continuous_delivery/__init__.py,sha256=JqPww29xZ-pp6OJDGhUj2dxyV9rgTTMUz0YDDVr9RaA,731
|
|
27
27
|
stouputils/continuous_delivery/__init__.pyi,sha256=_Sz2D10n1CDEyY8qDFwXNKdr01HVxanY4qdq9aN19cc,117
|
|
28
28
|
stouputils/continuous_delivery/cd_utils.py,sha256=fkaHk2V3j66uFAUsM2c_UddNhXW2KAQcrh7jVsH79pU,8594
|
|
@@ -125,8 +125,8 @@ stouputils/installer/main.py,sha256=8wrx_cnQo1dFGRf6x8vtxh6-96tQ-AzMyvJ0S64j0io,
|
|
|
125
125
|
stouputils/installer/main.pyi,sha256=r3j4GoMBpU06MpOqjSwoDTiSMOmbA3WWUA87970b6KE,3134
|
|
126
126
|
stouputils/installer/windows.py,sha256=r2AIuoyAmtMEuoCtQBH9GWQWI-JUT2J9zoH28j9ruOU,4880
|
|
127
127
|
stouputils/installer/windows.pyi,sha256=tHogIFhPVDQS0I10liLkAxnpaFFAvmFtEVMpPIae5LU,1616
|
|
128
|
-
stouputils/io.py,sha256=
|
|
129
|
-
stouputils/io.pyi,sha256=
|
|
128
|
+
stouputils/io.py,sha256=3-n6RGItDn7mdHSkzK4oSUMeL-3VJ1k2cvoSfzBH_ak,17797
|
|
129
|
+
stouputils/io.pyi,sha256=n2o28-4BfhlEH1f-vCLU8YlaqzG-4qgrZ3p8jEnJFeE,9314
|
|
130
130
|
stouputils/lock/__init__.py,sha256=8EvKPwnd5oHAWP-2vs6ULUDCSNyUh-mw12nYvBqgVAc,1029
|
|
131
131
|
stouputils/lock/__init__.pyi,sha256=qcTm6JcGXfwQB2dUCa2wFEInSwJF2pOrYnejSpvGd7k,120
|
|
132
132
|
stouputils/lock/base.py,sha256=hjSXRzOLVTMNrxpf4QcmfCfdlSRHFT9e130Zz_cqxY8,20483
|
|
@@ -141,14 +141,14 @@ stouputils/lock/shared.py,sha256=G8Mcy7dXtNESyU7hSaeihNrCU4l98VhyQyO_vQYPJ7g,788
|
|
|
141
141
|
stouputils/lock/shared.pyi,sha256=0CV6TpTaDEkcGA35Q-ijp8ckImZ32umlMA4U-8C_O-I,545
|
|
142
142
|
stouputils/parallel/__init__.py,sha256=myD8KiVfPPKF26Xu8Clu0p-VaYDK74loMUjUkl6-9XU,1013
|
|
143
143
|
stouputils/parallel/__init__.pyi,sha256=UtZKtl9i__OH0Edypap9oZUcTF1h91qfpItG1-x7TfE,97
|
|
144
|
-
stouputils/parallel/capturer.py,sha256=
|
|
144
|
+
stouputils/parallel/capturer.py,sha256=1ON8QuMrk9B0WS5lCIKtItzKRmlddrHsJAhMHYvKFyE,4127
|
|
145
145
|
stouputils/parallel/capturer.pyi,sha256=DWa3biPFzrGJBmkaFhAWwhbX4gbKQAipBAOJm4_XBy8,1665
|
|
146
146
|
stouputils/parallel/common.py,sha256=niDcAiEX3flX0ow91gXOB4umlOrR8PIYvpcKPClJHfM,4910
|
|
147
147
|
stouputils/parallel/common.pyi,sha256=jbyftOYHKP2qaA8YC1f1f12-BDBkhfsQsnPdsR4oet8,2493
|
|
148
148
|
stouputils/parallel/multi.py,sha256=tHJgcQJwsI6QeKEHoGJC4tsVK_6t1Fazkb06i1u-W_8,12610
|
|
149
149
|
stouputils/parallel/multi.pyi,sha256=DWolZn1UoXxOfuw7LqEJcU8aQJsN-_DRhPGJlJCA5pQ,8021
|
|
150
|
-
stouputils/parallel/subprocess.py,sha256=
|
|
151
|
-
stouputils/parallel/subprocess.pyi,sha256=
|
|
150
|
+
stouputils/parallel/subprocess.py,sha256=LWbwwAmnz54dCz9TAcKNg1TOMCVSP0C-0GIXaS5nVx0,6728
|
|
151
|
+
stouputils/parallel/subprocess.pyi,sha256=gzRtpTslvoENLtSNk79fe3Xz8lV3IwuopT9uMHW9BTU,3680
|
|
152
152
|
stouputils/print.py,sha256=PNyKvKheI7ior_-jQQ0Xu8ym7tSctheyHXTFykw2MKc,24552
|
|
153
153
|
stouputils/print.pyi,sha256=0z-BFpOEZ48GBGcD08C4Be67cPKX4ZxSHqKyOLRS_M8,10205
|
|
154
154
|
stouputils/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
@@ -156,7 +156,7 @@ stouputils/typing.py,sha256=TwvxrvxhBRkyHkoOpfyXebN13M3xJb8MAjKXiNIWjew,2205
|
|
|
156
156
|
stouputils/typing.pyi,sha256=U2UmFZausMYpnsUQROQE2JOwHcjx2hKV0rJuOdR57Ew,1341
|
|
157
157
|
stouputils/version_pkg.py,sha256=Jsp-s03L14DkiZ94vQgrlQmaxApfn9DC8M_nzT1SJLk,7014
|
|
158
158
|
stouputils/version_pkg.pyi,sha256=QPvqp1U3QA-9C_CC1dT9Vahv1hXEhstbM7x5uzMZSsQ,755
|
|
159
|
-
stouputils-1.18.
|
|
160
|
-
stouputils-1.18.
|
|
161
|
-
stouputils-1.18.
|
|
162
|
-
stouputils-1.18.
|
|
159
|
+
stouputils-1.18.2.dist-info/WHEEL,sha256=e_m4S054HL0hyR3CpOk-b7Q7fDX6BuFkgL5OjAExXas,80
|
|
160
|
+
stouputils-1.18.2.dist-info/entry_points.txt,sha256=tx0z9VOnE-sfkmbFbA93zaBMzV3XSsKEJa_BWIqUzxw,57
|
|
161
|
+
stouputils-1.18.2.dist-info/METADATA,sha256=74JWSrmZCgZa1xNxkPpitRGeL9SUre0dE8dFIY8BosA,14011
|
|
162
|
+
stouputils-1.18.2.dist-info/RECORD,,
|
|
File without changes
|