stouputils 1.15.1__py3-none-any.whl → 1.16.0__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/__init__.py +4 -14
- stouputils/__init__.pyi +1 -0
- stouputils/__main__.py +9 -7
- stouputils/all_doctests.py +20 -9
- stouputils/all_doctests.pyi +3 -2
- stouputils/collections.py +1 -1
- stouputils/collections.pyi +1 -1
- stouputils/continuous_delivery/pypi.py +10 -9
- stouputils/continuous_delivery/pypi.pyi +3 -3
- stouputils/continuous_delivery/stubs.py +1 -1
- stouputils/continuous_delivery/stubs.pyi +1 -1
- stouputils/data_science/scripts/exhaustive_process.py +3 -2
- stouputils/image.py +7 -8
- stouputils/image.pyi +1 -1
- stouputils/parallel.py +15 -30
- stouputils/print.py +2 -1
- stouputils/typing.py +71 -0
- stouputils/typing.pyi +42 -0
- {stouputils-1.15.1.dist-info → stouputils-1.16.0.dist-info}/METADATA +2 -1
- {stouputils-1.15.1.dist-info → stouputils-1.16.0.dist-info}/RECORD +22 -20
- {stouputils-1.15.1.dist-info → stouputils-1.16.0.dist-info}/WHEEL +2 -2
- {stouputils-1.15.1.dist-info → stouputils-1.16.0.dist-info}/entry_points.txt +0 -0
stouputils/__init__.py
CHANGED
|
@@ -1,18 +1,7 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
This package provides various tools and utilities for common development tasks including:
|
|
4
|
-
|
|
5
|
-
Key Features:
|
|
6
|
-
- Continuous delivery utilities (GitHub, PyPI)
|
|
7
|
-
- Display and logging utilities (print)
|
|
8
|
-
- File and I/O management (io)
|
|
9
|
-
- Decorators for common patterns
|
|
10
|
-
- Context managers
|
|
11
|
-
- Archive and backup tools
|
|
12
|
-
- Parallel processing helpers
|
|
13
|
-
- Collection utilities
|
|
14
|
-
- Doctests utilities
|
|
1
|
+
""" Stouputils is a collection of utility modules designed to simplify and enhance the development process.
|
|
2
|
+
It includes a range of tools for tasks such as execution of doctests, display utilities, decorators, as well as context managers.
|
|
15
3
|
|
|
4
|
+
Check the documentation for more details: https://stoupy51.github.io/stouputils/
|
|
16
5
|
"""
|
|
17
6
|
# Version (handle case where the package is not installed)
|
|
18
7
|
from importlib.metadata import PackageNotFoundError
|
|
@@ -31,6 +20,7 @@ from .image import *
|
|
|
31
20
|
from .io import *
|
|
32
21
|
from .parallel import *
|
|
33
22
|
from .print import *
|
|
23
|
+
from .typing import *
|
|
34
24
|
from .version_pkg import *
|
|
35
25
|
|
|
36
26
|
try:
|
stouputils/__init__.pyi
CHANGED
stouputils/__main__.py
CHANGED
|
@@ -7,12 +7,7 @@ import sys
|
|
|
7
7
|
|
|
8
8
|
import argcomplete
|
|
9
9
|
|
|
10
|
-
from .all_doctests import launch_tests
|
|
11
|
-
from .archive import archive_cli
|
|
12
|
-
from .backup import backup_cli
|
|
13
10
|
from .decorators import handle_error
|
|
14
|
-
from .print import CYAN, GREEN, RESET
|
|
15
|
-
from .version_pkg import show_version_cli
|
|
16
11
|
|
|
17
12
|
# Argument Parser Setup for Auto-Completion
|
|
18
13
|
parser = argparse.ArgumentParser(prog="stouputils", add_help=False)
|
|
@@ -29,22 +24,28 @@ def main() -> None:
|
|
|
29
24
|
|
|
30
25
|
# Print the version of stouputils and its dependencies
|
|
31
26
|
if second_arg in ("--version", "-v", "version", "show_version"):
|
|
27
|
+
from .version_pkg import show_version_cli
|
|
32
28
|
return show_version_cli()
|
|
33
29
|
|
|
34
30
|
# Handle "all_doctests" command
|
|
35
31
|
if second_arg == "all_doctests":
|
|
36
|
-
|
|
32
|
+
root_dir: str = "." if len(sys.argv) == 2 else sys.argv[2]
|
|
33
|
+
pattern: str = sys.argv[3] if len(sys.argv) >= 4 else "*"
|
|
34
|
+
from .all_doctests import launch_tests
|
|
35
|
+
if launch_tests(root_dir, pattern=pattern) > 0:
|
|
37
36
|
sys.exit(1)
|
|
38
37
|
return
|
|
39
38
|
|
|
40
39
|
# Handle "archive" command
|
|
41
40
|
if second_arg == "archive":
|
|
42
41
|
sys.argv.pop(1) # Remove "archive" from argv so archive_cli gets clean arguments
|
|
42
|
+
from .archive import archive_cli
|
|
43
43
|
return archive_cli()
|
|
44
44
|
|
|
45
45
|
# Handle "backup" command
|
|
46
46
|
if second_arg == "backup":
|
|
47
47
|
sys.argv.pop(1) # Remove "backup" from argv so backup_cli gets clean arguments
|
|
48
|
+
from .backup import backup_cli
|
|
48
49
|
return backup_cli()
|
|
49
50
|
|
|
50
51
|
# Handle "build" command
|
|
@@ -64,6 +65,7 @@ def main() -> None:
|
|
|
64
65
|
pkg_version = "unknown"
|
|
65
66
|
|
|
66
67
|
# Print help with nice formatting
|
|
68
|
+
from .print import CYAN, GREEN, RESET
|
|
67
69
|
separator: str = "─" * 60
|
|
68
70
|
print(f"""
|
|
69
71
|
{CYAN}{separator}{RESET}
|
|
@@ -73,7 +75,7 @@ def main() -> None:
|
|
|
73
75
|
|
|
74
76
|
{CYAN}Available commands:{RESET}
|
|
75
77
|
{GREEN}--version, -v{RESET} [pkg] [-t <depth>] Show version information (optionally for a specific package)
|
|
76
|
-
{GREEN}all_doctests{RESET} [dir]
|
|
78
|
+
{GREEN}all_doctests{RESET} [dir] [pattern] Run all doctests in the specified directory (optionally filter by pattern)
|
|
77
79
|
{GREEN}archive{RESET} --help Archive utilities (make, repair)
|
|
78
80
|
{GREEN}backup{RESET} --help Backup utilities (delta, consolidate, limit)
|
|
79
81
|
{GREEN}build{RESET} [--no_stubs] [<minor|major>] Build and publish package to PyPI using 'uv' tool (complete routine)
|
stouputils/all_doctests.py
CHANGED
|
@@ -9,29 +9,26 @@ This module is used to run all the doctests for all the modules in a given direc
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
# Imports
|
|
12
|
-
import importlib
|
|
13
|
-
import os
|
|
14
|
-
import pkgutil
|
|
15
|
-
import sys
|
|
16
|
-
from types import ModuleType
|
|
17
12
|
from typing import TYPE_CHECKING
|
|
18
13
|
|
|
19
14
|
from . import decorators
|
|
20
15
|
from .decorators import measure_time
|
|
21
16
|
from .io import clean_path, relative_path
|
|
22
|
-
from .print import error, info,
|
|
17
|
+
from .print import error, info, warning
|
|
23
18
|
|
|
24
19
|
if TYPE_CHECKING:
|
|
25
20
|
from doctest import TestResults
|
|
21
|
+
from types import ModuleType
|
|
26
22
|
|
|
27
23
|
|
|
28
24
|
# Main program
|
|
29
|
-
def launch_tests(root_dir: str, strict: bool = True) -> int:
|
|
25
|
+
def launch_tests(root_dir: str, strict: bool = True, pattern: str = "*") -> int:
|
|
30
26
|
""" Main function to launch tests for all modules in the given directory.
|
|
31
27
|
|
|
32
28
|
Args:
|
|
33
29
|
root_dir (str): Root directory to search for modules
|
|
34
30
|
strict (bool): Modify the force_raise_exception variable to True in the decorators module
|
|
31
|
+
pattern (str): Pattern to filter module names (fnmatch style, e.g., '*typ*', 'io', etc.)
|
|
35
32
|
|
|
36
33
|
Returns:
|
|
37
34
|
int: The number of failed tests
|
|
@@ -62,11 +59,14 @@ def launch_tests(root_dir: str, strict: bool = True) -> int:
|
|
|
62
59
|
strict = old_value
|
|
63
60
|
|
|
64
61
|
# Get the path of the directory to check modules from
|
|
62
|
+
import os
|
|
65
63
|
working_dir: str = clean_path(os.getcwd())
|
|
66
64
|
root_dir = clean_path(os.path.abspath(root_dir))
|
|
67
65
|
dir_to_check: str = os.path.dirname(root_dir) if working_dir != root_dir else root_dir
|
|
68
66
|
|
|
69
67
|
# Get all modules from folder
|
|
68
|
+
import pkgutil
|
|
69
|
+
import sys
|
|
70
70
|
sys.path.insert(0, dir_to_check)
|
|
71
71
|
modules_file_paths: list[str] = []
|
|
72
72
|
for directory_path, _, _ in os.walk(root_dir):
|
|
@@ -94,10 +94,21 @@ def launch_tests(root_dir: str, strict: bool = True) -> int:
|
|
|
94
94
|
if not modules_file_paths:
|
|
95
95
|
raise ValueError(f"No modules found in '{relative_path(root_dir)}'")
|
|
96
96
|
|
|
97
|
+
# Filter modules based on pattern
|
|
98
|
+
if pattern != "*":
|
|
99
|
+
import fnmatch
|
|
100
|
+
modules_file_paths = [
|
|
101
|
+
path for path in modules_file_paths
|
|
102
|
+
if fnmatch.fnmatch(path.split(".")[-1], pattern)
|
|
103
|
+
]
|
|
104
|
+
if not modules_file_paths:
|
|
105
|
+
raise ValueError(f"No modules matching pattern '{pattern}' found in '{relative_path(root_dir)}'")
|
|
106
|
+
|
|
97
107
|
# Find longest module path for alignment
|
|
98
108
|
max_length: int = max(len(path) for path in modules_file_paths)
|
|
99
109
|
|
|
100
110
|
# Dynamically import all modules from iacob package recursively using pkgutil and importlib
|
|
111
|
+
import importlib
|
|
101
112
|
modules: list[ModuleType] = []
|
|
102
113
|
separators: list[str] = []
|
|
103
114
|
for module_path in modules_file_paths:
|
|
@@ -143,7 +154,7 @@ def launch_tests(root_dir: str, strict: bool = True) -> int:
|
|
|
143
154
|
return total_failed
|
|
144
155
|
|
|
145
156
|
|
|
146
|
-
def test_module_with_progress(module: ModuleType, separator: str) ->
|
|
157
|
+
def test_module_with_progress(module: ModuleType, separator: str) -> TestResults:
|
|
147
158
|
""" Test a module with testmod and measure the time taken with progress printing.
|
|
148
159
|
|
|
149
160
|
Args:
|
|
@@ -152,7 +163,7 @@ def test_module_with_progress(module: ModuleType, separator: str) -> "TestResult
|
|
|
152
163
|
Returns:
|
|
153
164
|
TestResults: The results of the tests
|
|
154
165
|
"""
|
|
155
|
-
from doctest import
|
|
166
|
+
from doctest import testmod
|
|
156
167
|
@measure_time(message=f"Testing module '{module.__name__}' {separator}took")
|
|
157
168
|
def internal() -> TestResults:
|
|
158
169
|
return testmod(m=module)
|
stouputils/all_doctests.pyi
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
from . import decorators as decorators
|
|
2
2
|
from .decorators import measure_time as measure_time
|
|
3
3
|
from .io import clean_path as clean_path, relative_path as relative_path
|
|
4
|
-
from .print import error as error, info as info,
|
|
4
|
+
from .print import error as error, info as info, warning as warning
|
|
5
5
|
from doctest import TestResults as TestResults
|
|
6
6
|
from types import ModuleType
|
|
7
7
|
|
|
8
|
-
def launch_tests(root_dir: str, strict: bool = True) -> int:
|
|
8
|
+
def launch_tests(root_dir: str, strict: bool = True, pattern: str = '*') -> int:
|
|
9
9
|
''' Main function to launch tests for all modules in the given directory.
|
|
10
10
|
|
|
11
11
|
\tArgs:
|
|
12
12
|
\t\troot_dir\t\t\t\t(str):\t\t\tRoot directory to search for modules
|
|
13
13
|
\t\tstrict\t\t\t\t\t(bool):\t\t\tModify the force_raise_exception variable to True in the decorators module
|
|
14
|
+
\t\tpattern\t\t\t\t\t(str):\t\t\tPattern to filter module names (fnmatch style, e.g., \'*typ*\', \'io\', etc.)
|
|
14
15
|
|
|
15
16
|
\tReturns:
|
|
16
17
|
\t\tint: The number of failed tests
|
stouputils/collections.py
CHANGED
|
@@ -30,7 +30,7 @@ T = TypeVar("T")
|
|
|
30
30
|
|
|
31
31
|
# Functions
|
|
32
32
|
def unique_list[T](list_to_clean: Iterable[T], method: Literal["id", "hash", "str"] = "str") -> list[T]:
|
|
33
|
-
""" Remove duplicates from the list while keeping the order using ids
|
|
33
|
+
""" Remove duplicates from the list while keeping the order using ids, hash, or str
|
|
34
34
|
|
|
35
35
|
Args:
|
|
36
36
|
list_to_clean (Iterable[T]): The list to clean
|
stouputils/collections.pyi
CHANGED
|
@@ -7,7 +7,7 @@ from typing import Any, Literal, TypeVar
|
|
|
7
7
|
T = TypeVar('T')
|
|
8
8
|
|
|
9
9
|
def unique_list[T](list_to_clean: Iterable[T], method: Literal['id', 'hash', 'str'] = 'str') -> list[T]:
|
|
10
|
-
''' Remove duplicates from the list while keeping the order using ids
|
|
10
|
+
''' Remove duplicates from the list while keeping the order using ids, hash, or str
|
|
11
11
|
|
|
12
12
|
\tArgs:
|
|
13
13
|
\t\tlist_to_clean\t(Iterable[T]):\t\t\t\t\tThe list to clean
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
# Imports
|
|
12
12
|
import os
|
|
13
|
+
import subprocess
|
|
13
14
|
import sys
|
|
14
15
|
from collections.abc import Callable
|
|
15
16
|
from typing import Any
|
|
@@ -22,17 +23,17 @@ def update_pip_and_required_packages() -> int:
|
|
|
22
23
|
""" Update pip and required packages.
|
|
23
24
|
|
|
24
25
|
Returns:
|
|
25
|
-
int: Return code of the
|
|
26
|
+
int: Return code of the subprocess.run call.
|
|
26
27
|
"""
|
|
27
|
-
return
|
|
28
|
+
return subprocess.run(f"{sys.executable} -m pip install --upgrade pip setuptools build twine pkginfo packaging", shell=True).returncode
|
|
28
29
|
|
|
29
30
|
def build_package() -> int:
|
|
30
31
|
""" Build the package.
|
|
31
32
|
|
|
32
33
|
Returns:
|
|
33
|
-
int: Return code of the
|
|
34
|
+
int: Return code of the subprocess.run call.
|
|
34
35
|
"""
|
|
35
|
-
return
|
|
36
|
+
return subprocess.run(f"{sys.executable} -m build", shell=True).returncode
|
|
36
37
|
|
|
37
38
|
def upload_package(repository: str, filepath: str) -> int:
|
|
38
39
|
""" Upload the package to PyPI.
|
|
@@ -42,9 +43,9 @@ def upload_package(repository: str, filepath: str) -> int:
|
|
|
42
43
|
filepath (str): Path to the file to upload.
|
|
43
44
|
|
|
44
45
|
Returns:
|
|
45
|
-
int: Return code of the
|
|
46
|
+
int: Return code of the subprocess.run call.
|
|
46
47
|
"""
|
|
47
|
-
return
|
|
48
|
+
return subprocess.run(f"{sys.executable} -m twine upload --verbose -r {repository} {filepath}", shell=True).returncode
|
|
48
49
|
|
|
49
50
|
@handle_error(message="Error while doing the pypi full routine", error_log=LogLevels.ERROR_TRACEBACK)
|
|
50
51
|
def pypi_full_routine(
|
|
@@ -115,16 +116,16 @@ def pypi_full_routine_using_uv() -> None:
|
|
|
115
116
|
# Increment version in pyproject.toml
|
|
116
117
|
if "--no-bump" not in sys.argv and "--no_bump" not in sys.argv:
|
|
117
118
|
increment: str = "patch" if sys.argv[-1] not in ("minor", "major") else sys.argv[-1]
|
|
118
|
-
if
|
|
119
|
+
if subprocess.run(f"uv version --bump {increment} --frozen", shell=True).returncode != 0:
|
|
119
120
|
raise Exception("Error while incrementing version using 'uv version'")
|
|
120
121
|
|
|
121
122
|
# Build the package using 'uv build'
|
|
122
123
|
import shutil
|
|
123
124
|
shutil.rmtree("dist", ignore_errors=True)
|
|
124
|
-
if
|
|
125
|
+
if subprocess.run(f"{sys.executable} -m uv build", shell=True).returncode != 0:
|
|
125
126
|
raise Exception("Error while building the package using 'uv build'")
|
|
126
127
|
|
|
127
128
|
# Upload the most recent file to PyPI using 'uv publish'
|
|
128
|
-
if
|
|
129
|
+
if subprocess.run(f"{sys.executable} -m uv publish", shell=True).returncode != 0:
|
|
129
130
|
raise Exception("Error while publishing the package using 'uv publish'")
|
|
130
131
|
|
|
@@ -6,13 +6,13 @@ def update_pip_and_required_packages() -> int:
|
|
|
6
6
|
""" Update pip and required packages.
|
|
7
7
|
|
|
8
8
|
\tReturns:
|
|
9
|
-
\t\tint: Return code of the
|
|
9
|
+
\t\tint: Return code of the subprocess.run call.
|
|
10
10
|
\t"""
|
|
11
11
|
def build_package() -> int:
|
|
12
12
|
""" Build the package.
|
|
13
13
|
|
|
14
14
|
\tReturns:
|
|
15
|
-
\t\tint: Return code of the
|
|
15
|
+
\t\tint: Return code of the subprocess.run call.
|
|
16
16
|
\t"""
|
|
17
17
|
def upload_package(repository: str, filepath: str) -> int:
|
|
18
18
|
""" Upload the package to PyPI.
|
|
@@ -22,7 +22,7 @@ def upload_package(repository: str, filepath: str) -> int:
|
|
|
22
22
|
\t\tfilepath (str): Path to the file to upload.
|
|
23
23
|
|
|
24
24
|
\tReturns:
|
|
25
|
-
\t\tint: Return code of the
|
|
25
|
+
\t\tint: Return code of the subprocess.run call.
|
|
26
26
|
\t"""
|
|
27
27
|
def pypi_full_routine(repository: str, dist_directory: str, last_files: int = 1, endswith: str = '.tar.gz', update_all_function: Callable[[], int] = ..., build_package_function: Callable[[], int] = ..., upload_package_function: Callable[[str, str], int] = ...) -> None:
|
|
28
28
|
''' Upload the most recent file(s) to PyPI after updating pip and required packages and building the package.
|
|
@@ -24,7 +24,7 @@ def generate_stubs(
|
|
|
24
24
|
package_name (str): Name of the package to generate stubs for.
|
|
25
25
|
extra_args (str): Extra arguments to pass to stubgen. Defaults to "--include-docstrings --include-private".
|
|
26
26
|
Returns:
|
|
27
|
-
int:
|
|
27
|
+
int: 0 if successful, non-zero otherwise.
|
|
28
28
|
"""
|
|
29
29
|
try:
|
|
30
30
|
from mypy.stubgen import main as stubgen_main
|
|
@@ -10,7 +10,7 @@ def generate_stubs(package_name: str, extra_args: str = '--include-docstrings --
|
|
|
10
10
|
\t\tpackage_name (str): Name of the package to generate stubs for.
|
|
11
11
|
\t\textra_args (str): Extra arguments to pass to stubgen. Defaults to "--include-docstrings --include-private".
|
|
12
12
|
\tReturns:
|
|
13
|
-
\t\tint:
|
|
13
|
+
\t\tint: 0 if successful, non-zero otherwise.
|
|
14
14
|
\t'''
|
|
15
15
|
def clean_stubs_directory(output_directory: str, package_name: str) -> None:
|
|
16
16
|
""" Clean the stubs directory by deleting all .pyi files.
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
# Imports
|
|
3
3
|
import argparse
|
|
4
4
|
import os
|
|
5
|
+
import subprocess
|
|
5
6
|
import sys
|
|
6
7
|
|
|
7
8
|
from ...decorators import handle_error, measure_time
|
|
8
|
-
from ...print import info
|
|
9
9
|
from ...parallel import multithreading
|
|
10
|
+
from ...print import info
|
|
10
11
|
from ..config.get import DataScienceConfig
|
|
11
12
|
from ..dataset import LOWER_GS
|
|
12
13
|
from ..models.all import ALL_MODELS, CLASS_MAP
|
|
@@ -122,7 +123,7 @@ def exhaustive_process(
|
|
|
122
123
|
info(f"Executing command: '{cmd}'")
|
|
123
124
|
sys.stdout.flush()
|
|
124
125
|
sys.stderr.flush()
|
|
125
|
-
|
|
126
|
+
subprocess.run(cmd, shell=True)
|
|
126
127
|
multithreading(
|
|
127
128
|
runner,
|
|
128
129
|
commands,
|
stouputils/image.py
CHANGED
|
@@ -28,7 +28,7 @@ PIL_Image_or_NDArray = TypeVar("PIL_Image_or_NDArray", bound="Image.Image | NDAr
|
|
|
28
28
|
def image_resize[PIL_Image_or_NDArray](
|
|
29
29
|
image: PIL_Image_or_NDArray,
|
|
30
30
|
max_result_size: int,
|
|
31
|
-
resampling:
|
|
31
|
+
resampling: Image.Resampling | None = None,
|
|
32
32
|
min_or_max: Callable[[int, int], int] = max,
|
|
33
33
|
return_type: type[PIL_Image_or_NDArray] | str = "same",
|
|
34
34
|
keep_aspect_ratio: bool = True,
|
|
@@ -37,7 +37,7 @@ def image_resize[PIL_Image_or_NDArray](
|
|
|
37
37
|
Scales the image so that its largest dimension equals max_result_size.
|
|
38
38
|
|
|
39
39
|
Args:
|
|
40
|
-
image (Image.Image |
|
|
40
|
+
image (Image.Image | NDArray): The image to resize.
|
|
41
41
|
max_result_size (int): Maximum size for the largest dimension.
|
|
42
42
|
resampling (Image.Resampling | None): PIL resampling filter to use (default: Image.Resampling.LANCZOS).
|
|
43
43
|
min_or_max (Callable): Function to use to get the minimum or maximum of the two ratios.
|
|
@@ -84,7 +84,7 @@ def image_resize[PIL_Image_or_NDArray](
|
|
|
84
84
|
|
|
85
85
|
# Convert numpy array to PIL Image if needed
|
|
86
86
|
if not original_was_pil:
|
|
87
|
-
image = Image.fromarray(image)
|
|
87
|
+
image = Image.fromarray(image) # type: ignore
|
|
88
88
|
|
|
89
89
|
if keep_aspect_ratio:
|
|
90
90
|
|
|
@@ -123,8 +123,8 @@ def image_resize[PIL_Image_or_NDArray](
|
|
|
123
123
|
|
|
124
124
|
def auto_crop[PIL_Image_or_NDArray](
|
|
125
125
|
image: PIL_Image_or_NDArray,
|
|
126
|
-
mask:
|
|
127
|
-
threshold: int | float | Callable[[
|
|
126
|
+
mask: NDArray[np.bool_] | None = None,
|
|
127
|
+
threshold: int | float | Callable[[NDArray[np.number]], int | float] | None = None,
|
|
128
128
|
return_type: type[PIL_Image_or_NDArray] | str = "same",
|
|
129
129
|
contiguous: bool = True,
|
|
130
130
|
) -> Any:
|
|
@@ -263,7 +263,7 @@ def auto_crop[PIL_Image_or_NDArray](
|
|
|
263
263
|
|
|
264
264
|
def numpy_to_gif(
|
|
265
265
|
path: str,
|
|
266
|
-
array:
|
|
266
|
+
array: NDArray[np.integer | np.floating | np.bool_],
|
|
267
267
|
duration: int = 100,
|
|
268
268
|
loop: int = 0,
|
|
269
269
|
mkdir: bool = True,
|
|
@@ -344,7 +344,7 @@ def numpy_to_gif(
|
|
|
344
344
|
|
|
345
345
|
def numpy_to_obj(
|
|
346
346
|
path: str,
|
|
347
|
-
array:
|
|
347
|
+
array: NDArray[np.integer | np.floating | np.bool_],
|
|
348
348
|
threshold: float = 0.5,
|
|
349
349
|
step_size: int = 1,
|
|
350
350
|
pad_array: bool = True,
|
|
@@ -372,7 +372,6 @@ def numpy_to_obj(
|
|
|
372
372
|
"""
|
|
373
373
|
# Imports
|
|
374
374
|
import numpy as np
|
|
375
|
-
from numpy.typing import NDArray
|
|
376
375
|
from skimage import measure
|
|
377
376
|
|
|
378
377
|
# Assertions
|
stouputils/image.pyi
CHANGED
|
@@ -13,7 +13,7 @@ def image_resize[PIL_Image_or_NDArray](image: PIL_Image_or_NDArray, max_result_s
|
|
|
13
13
|
\tScales the image so that its largest dimension equals max_result_size.
|
|
14
14
|
|
|
15
15
|
\tArgs:
|
|
16
|
-
\t\timage (Image.Image |
|
|
16
|
+
\t\timage (Image.Image | NDArray): The image to resize.
|
|
17
17
|
\t\tmax_result_size (int): Maximum size for the largest dimension.
|
|
18
18
|
\t\tresampling (Image.Resampling | None): PIL resampling filter to use (default: Image.Resampling.LANCZOS).
|
|
19
19
|
\t\tmin_or_max (Callable): Function to use to get the minimum or maximum of the two ratios.
|
stouputils/parallel.py
CHANGED
|
@@ -432,36 +432,21 @@ def _set_process_priority(nice_value: int) -> None:
|
|
|
432
432
|
if sys.platform == "win32":
|
|
433
433
|
# Map Unix nice values to Windows priority classes
|
|
434
434
|
# -20 to -10: HIGH, -9 to -1: ABOVE_NORMAL, 0: NORMAL, 1-9: BELOW_NORMAL, 10-19: IDLE
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
import ctypes
|
|
451
|
-
# Windows priority class constants
|
|
452
|
-
if nice_value <= -10:
|
|
453
|
-
priority = 0x00000080 # HIGH_PRIORITY_CLASS
|
|
454
|
-
elif nice_value < 0:
|
|
455
|
-
priority = 0x00008000 # ABOVE_NORMAL_PRIORITY_CLASS
|
|
456
|
-
elif nice_value == 0:
|
|
457
|
-
priority = 0x00000020 # NORMAL_PRIORITY_CLASS
|
|
458
|
-
elif nice_value < 10:
|
|
459
|
-
priority = 0x00004000 # BELOW_NORMAL_PRIORITY_CLASS
|
|
460
|
-
else:
|
|
461
|
-
priority = 0x00000040 # IDLE_PRIORITY_CLASS
|
|
462
|
-
kernel32 = ctypes.windll.kernel32
|
|
463
|
-
handle = kernel32.GetCurrentProcess()
|
|
464
|
-
kernel32.SetPriorityClass(handle, priority)
|
|
435
|
+
import ctypes
|
|
436
|
+
# Windows priority class constants
|
|
437
|
+
if nice_value <= -10:
|
|
438
|
+
priority = 0x00000080 # HIGH_PRIORITY_CLASS
|
|
439
|
+
elif nice_value < 0:
|
|
440
|
+
priority = 0x00008000 # ABOVE_NORMAL_PRIORITY_CLASS
|
|
441
|
+
elif nice_value == 0:
|
|
442
|
+
priority = 0x00000020 # NORMAL_PRIORITY_CLASS
|
|
443
|
+
elif nice_value < 10:
|
|
444
|
+
priority = 0x00004000 # BELOW_NORMAL_PRIORITY_CLASS
|
|
445
|
+
else:
|
|
446
|
+
priority = 0x00000040 # IDLE_PRIORITY_CLASS
|
|
447
|
+
kernel32 = ctypes.windll.kernel32
|
|
448
|
+
handle = kernel32.GetCurrentProcess()
|
|
449
|
+
kernel32.SetPriorityClass(handle, priority)
|
|
465
450
|
else:
|
|
466
451
|
# Unix-like systems
|
|
467
452
|
os.nice(nice_value)
|
stouputils/print.py
CHANGED
stouputils/typing.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides utilities for typing enhancements such as JSON type aliases:
|
|
3
|
+
- JsonDict
|
|
4
|
+
- JsonList
|
|
5
|
+
- JsonMap
|
|
6
|
+
- MutJsonMap
|
|
7
|
+
- IterAny
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Imports
|
|
11
|
+
from collections.abc import Iterable, Mapping, MutableMapping
|
|
12
|
+
from dataclasses import asdict, is_dataclass
|
|
13
|
+
from typing import Any, cast
|
|
14
|
+
|
|
15
|
+
# Typing aliases
|
|
16
|
+
JsonDict = dict[str, Any]
|
|
17
|
+
""" A type alias for JSON dictionaries """
|
|
18
|
+
JsonList = list[Any]
|
|
19
|
+
""" A type alias for JSON lists """
|
|
20
|
+
JsonMap = Mapping[str, Any]
|
|
21
|
+
""" A type alias for JSON mapping """
|
|
22
|
+
MutJsonMap = MutableMapping[str, Any]
|
|
23
|
+
""" A type alias for mutable JSON mapping """
|
|
24
|
+
IterAny = Iterable[Any]
|
|
25
|
+
""" A type alias for iterable of any type """
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## Utility functions
|
|
29
|
+
def convert_to_serializable(obj: Any) -> Any:
|
|
30
|
+
""" Recursively convert objects to JSON-serializable forms.
|
|
31
|
+
|
|
32
|
+
Objects with a `to_dict()` or `asdict()` method are converted to their dictionary representation.
|
|
33
|
+
Dictionaries and lists are recursively processed.
|
|
34
|
+
|
|
35
|
+
Can also be used to convert nested structures containing custom objects,
|
|
36
|
+
such as defaultdict, dataclasses, or other user-defined types.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
obj (Any): The object to convert
|
|
40
|
+
Returns:
|
|
41
|
+
Any: The JSON-serializable version of the object
|
|
42
|
+
Examples:
|
|
43
|
+
>>> from typing import defaultdict
|
|
44
|
+
>>> my_dict = defaultdict(lambda: defaultdict(int))
|
|
45
|
+
>>> my_dict['a']['b'] += 6
|
|
46
|
+
>>> my_dict['c']['d'] = 4
|
|
47
|
+
>>> my_dict['a']
|
|
48
|
+
defaultdict(<class 'int'>, {'b': 6})
|
|
49
|
+
>>> my_dict['c']
|
|
50
|
+
defaultdict(<class 'int'>, {'d': 4})
|
|
51
|
+
>>> convert_to_serializable(my_dict)
|
|
52
|
+
{'a': {'b': 6}, 'c': {'d': 4}}
|
|
53
|
+
|
|
54
|
+
>>> from dataclasses import dataclass
|
|
55
|
+
>>> @dataclass
|
|
56
|
+
... class Point:
|
|
57
|
+
... x: int
|
|
58
|
+
... y: int
|
|
59
|
+
>>> convert_to_serializable(Point(3, 4))
|
|
60
|
+
{'x': 3, 'y': 4}
|
|
61
|
+
"""
|
|
62
|
+
if hasattr(obj, "to_dict"):
|
|
63
|
+
return obj.to_dict()
|
|
64
|
+
elif is_dataclass(obj):
|
|
65
|
+
return asdict(obj) # pyright: ignore[reportArgumentType]
|
|
66
|
+
elif isinstance(obj, dict | Mapping | MutableMapping):
|
|
67
|
+
return {k: convert_to_serializable(v) for k, v in cast(JsonDict, obj).items()}
|
|
68
|
+
elif isinstance(obj, Iterable) and not isinstance(obj, (str, bytes)):
|
|
69
|
+
return [convert_to_serializable(item) for item in cast(IterAny, obj)]
|
|
70
|
+
return obj
|
|
71
|
+
|
stouputils/typing.pyi
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from collections.abc import Iterable, Mapping, MutableMapping
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
JsonDict = dict[str, Any]
|
|
5
|
+
JsonList = list[Any]
|
|
6
|
+
JsonMap = Mapping[str, Any]
|
|
7
|
+
MutJsonMap = MutableMapping[str, Any]
|
|
8
|
+
IterAny = Iterable[Any]
|
|
9
|
+
|
|
10
|
+
def convert_to_serializable(obj: Any) -> Any:
|
|
11
|
+
""" Recursively convert objects to JSON-serializable forms.
|
|
12
|
+
|
|
13
|
+
\tObjects with a `to_dict()` or `asdict()` method are converted to their dictionary representation.
|
|
14
|
+
\tDictionaries and lists are recursively processed.
|
|
15
|
+
|
|
16
|
+
\tCan also be used to convert nested structures containing custom objects,
|
|
17
|
+
\tsuch as defaultdict, dataclasses, or other user-defined types.
|
|
18
|
+
|
|
19
|
+
\tArgs:
|
|
20
|
+
\t\tobj (Any): The object to convert
|
|
21
|
+
\tReturns:
|
|
22
|
+
\t\tAny: The JSON-serializable version of the object
|
|
23
|
+
\tExamples:
|
|
24
|
+
\t\t>>> from typing import defaultdict
|
|
25
|
+
\t\t>>> my_dict = defaultdict(lambda: defaultdict(int))
|
|
26
|
+
\t\t>>> my_dict['a']['b'] += 6
|
|
27
|
+
\t\t>>> my_dict['c']['d'] = 4
|
|
28
|
+
\t\t>>> my_dict['a']
|
|
29
|
+
\t\tdefaultdict(<class 'int'>, {'b': 6})
|
|
30
|
+
\t\t>>> my_dict['c']
|
|
31
|
+
\t\tdefaultdict(<class 'int'>, {'d': 4})
|
|
32
|
+
\t\t>>> convert_to_serializable(my_dict)
|
|
33
|
+
\t\t{'a': {'b': 6}, 'c': {'d': 4}}
|
|
34
|
+
|
|
35
|
+
\t\t>>> from dataclasses import dataclass
|
|
36
|
+
\t\t>>> @dataclass
|
|
37
|
+
\t\t... class Point:
|
|
38
|
+
\t\t... x: int
|
|
39
|
+
\t\t... y: int
|
|
40
|
+
\t\t>>> convert_to_serializable(Point(3, 4))
|
|
41
|
+
\t\t{'x': 3, 'y': 4}
|
|
42
|
+
\t"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: stouputils
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.16.0
|
|
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
|
|
@@ -94,6 +94,7 @@ Start now by installing the package: `pip install stouputils`.<br>
|
|
|
94
94
|
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.parallel.html">parallel.py</a> <span class="comment"># 🔀 Utility functions for parallel processing <span class="paren">(multiprocessing, multithreading, run_in_subprocess)</span></span>
|
|
95
95
|
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.image.html">image.py</a> <span class="comment"># 🖼️ Little utilities for image processing <span class="paren">(image_resize, auto_crop, numpy_to_gif, numpy_to_obj)</span></span>
|
|
96
96
|
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.collections.html">collections.py</a> <span class="comment"># 🧰 Utilities for collection manipulation <span class="paren">(unique_list, sort_dict_keys, upsert_in_dataframe, array_to_disk)</span></span>
|
|
97
|
+
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.typing.html">typing.py</a> <span class="comment"># 📝 Utilities for typing enhancements <span class="paren">(IterAny, JsonDict, JsonList, ..., convert_to_serializable)</span></span>
|
|
97
98
|
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.all_doctests.html">all_doctests.py</a> <span class="comment"># ✅ Run all doctests for all modules in a given directory <span class="paren">(launch_tests, test_module_with_progress)</span></span>
|
|
98
99
|
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.backup.html">backup.py</a> <span class="comment"># 💾 Utilities for backup management <span class="paren">(delta backup, consolidate)</span></span>
|
|
99
100
|
├── <a href="https://stoupy51.github.io/stouputils/latest/modules/stouputils.archive.html">archive.py</a> <span class="comment"># 📦 Functions for creating and managing archives</span>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
stouputils/__init__.py,sha256=
|
|
2
|
-
stouputils/__init__.pyi,sha256=
|
|
3
|
-
stouputils/__main__.py,sha256=
|
|
1
|
+
stouputils/__init__.py,sha256=w3WHJy3nt28l6WAtlZz6WRiyHhKy9mw66L6SJJXikW8,996
|
|
2
|
+
stouputils/__init__.pyi,sha256=as5qRu9FfJdJwb_DheDTq6hA5y4UfIFgPwItNfPHMwU,374
|
|
3
|
+
stouputils/__main__.py,sha256=MA3jjc1yL8_0Z9oB55BMqrFq1ot_-e5rNqSxFQGsMzs,2910
|
|
4
4
|
stouputils/_deprecated.py,sha256=Bcq6YjdM9Rk9Vq-WMhc_tuEbPORX6U8HAJ9Vh-VIWTA,1478
|
|
5
5
|
stouputils/_deprecated.pyi,sha256=6-8YsftJd2fRAdBLsysc6jf-uA8V2wiqkiFAbdfWfJQ,664
|
|
6
|
-
stouputils/all_doctests.py,sha256=
|
|
7
|
-
stouputils/all_doctests.pyi,sha256=
|
|
6
|
+
stouputils/all_doctests.py,sha256=317v-B4kqf_8lkrw6ul1ZGBgZ75CYIqoDn7kG5k8qyc,6322
|
|
7
|
+
stouputils/all_doctests.pyi,sha256=R3FRKaQv3sTZbxLvvsChHZZKygVMhmL6pqrYYLqvZCg,2017
|
|
8
8
|
stouputils/applications/__init__.py,sha256=dbjwZt8PZF043KoJSItqCpH32FtRxN5sgV-8Q2b1l10,457
|
|
9
9
|
stouputils/applications/__init__.pyi,sha256=DTYq2Uqq1uLzCMkFByjRqdtREA-9SaQnp4QpgmCEPFg,56
|
|
10
10
|
stouputils/applications/automatic_docs.py,sha256=_6XbCuVi2EiSdkiPZ7XHr5mUGh2ZORev8Vd0tJDb0ug,20561
|
|
@@ -21,20 +21,20 @@ 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=Zi2OmlPmUPx-isZZpF9xYWU52OtzNqvSHGYM5use0AA,8838
|
|
25
|
+
stouputils/collections.pyi,sha256=J6Sb-8oSVeD1K-j5zNBZo_cP5Bi5NDh2qN4n4QBJIZE,3508
|
|
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
|
|
29
29
|
stouputils/continuous_delivery/cd_utils.pyi,sha256=nxTLQydVOSVIix88dRtBXjMrUPpI5ftiQYbLI_nMByQ,4848
|
|
30
30
|
stouputils/continuous_delivery/github.py,sha256=Iva2XNm60Th78P_evnhCJHn0Q9-06udPlOZAxtZB5vw,19464
|
|
31
31
|
stouputils/continuous_delivery/github.pyi,sha256=RHRsSroEsT0I1qeuq-Wg0JLdEEDttLrzgHZPVRtLZ0Q,6641
|
|
32
|
-
stouputils/continuous_delivery/pypi.py,sha256=
|
|
33
|
-
stouputils/continuous_delivery/pypi.pyi,sha256=
|
|
32
|
+
stouputils/continuous_delivery/pypi.py,sha256=H19RwvJN6QS-qcqvjtIaSLfZTA398jXu-SgSkvkaj0g,5524
|
|
33
|
+
stouputils/continuous_delivery/pypi.pyi,sha256=3zFRz3L_gF_JuSe1J3RZAKTVsFMFiqEdCJbwHRYBj7g,2478
|
|
34
34
|
stouputils/continuous_delivery/pyproject.py,sha256=olD3QqzLfCLnTBw8IkSKSLBPWyeMv6uS7A0yGdFuIvQ,4802
|
|
35
35
|
stouputils/continuous_delivery/pyproject.pyi,sha256=bMWwqyG0Auo46dt-dWGePQ9yJ8rSrgb7mnJTfbiS3TQ,2053
|
|
36
|
-
stouputils/continuous_delivery/stubs.py,sha256=
|
|
37
|
-
stouputils/continuous_delivery/stubs.pyi,sha256=
|
|
36
|
+
stouputils/continuous_delivery/stubs.py,sha256=N0qPBORNYmGIhoY0h40JVvNIS9CS_ixHlxNWQN1bPRE,3514
|
|
37
|
+
stouputils/continuous_delivery/stubs.pyi,sha256=UrL2dowLC6hsiKe-gfWeVCudz7tKmt4rsiCL9gsBLv4,2392
|
|
38
38
|
stouputils/ctx.py,sha256=KVVDmL3pAPX2WM_QzjsmctbG-YfjJ-4aWBSoI7eU_ws,15586
|
|
39
39
|
stouputils/ctx.pyi,sha256=-7AJwD9bKzKBFsYlgyULPznstq3LvXRXe2r_2at72FI,9799
|
|
40
40
|
stouputils/data_science/config/get.py,sha256=smdWcu5bBlY38WGtC3GzIF2el-gpvSlDMRNsypmr0JM,1773
|
|
@@ -105,14 +105,14 @@ stouputils/data_science/models/model_interface.py,sha256=om1hnEYHTILfLJRcoTDhR7R
|
|
|
105
105
|
stouputils/data_science/models/sandbox.py,sha256=ZeuoXNHnVvMlm6umCgTl2Ss0zyQSlxFEV9xJb3ET1Qw,4269
|
|
106
106
|
stouputils/data_science/range_tuple.py,sha256=5f5PQcwENZEMV0O6U5IpZ2_ylNMB_graDyv-wxrDUhk,6908
|
|
107
107
|
stouputils/data_science/scripts/augment_dataset.py,sha256=zGcQ2uSn_DO570NIFEs2DUc_d5uvWxLfY-RavjdO3aU,3469
|
|
108
|
-
stouputils/data_science/scripts/exhaustive_process.py,sha256=
|
|
108
|
+
stouputils/data_science/scripts/exhaustive_process.py,sha256=Dc5gceIlIiP8U0m1qt3zpJEZAwQ7617JBAYWitdhjJI,5519
|
|
109
109
|
stouputils/data_science/scripts/preprocess_dataset.py,sha256=OLC2KjEtSMeyHHPpNOATfNDuq0lZ09utKhsuzBA4MN4,2929
|
|
110
110
|
stouputils/data_science/scripts/routine.py,sha256=FkTLzmcdm_qUp69D-dPAKJm2RfXZZLtPgje6lEopu2I,7662
|
|
111
111
|
stouputils/data_science/utils.py,sha256=HFXI2RQZ53RbBOn_4Act2bi0z4xQlTtsuR5Am80v9JU,11084
|
|
112
112
|
stouputils/decorators.py,sha256=miZ8r2g8VhmQs2_knkKuUagdQabriZe7w0fCOEB69Nw,21838
|
|
113
113
|
stouputils/decorators.pyi,sha256=vbPRsvox4dotqcln3StgE6iZ1cWCOeAn56M9zMpdw2U,10948
|
|
114
|
-
stouputils/image.py,sha256=
|
|
115
|
-
stouputils/image.pyi,sha256=
|
|
114
|
+
stouputils/image.py,sha256=uGBweT-60JEn4SK5nVAxqiVI4Ijh4YyG_d5uXjXgtCY,16603
|
|
115
|
+
stouputils/image.pyi,sha256=B7aypF1kHsEHHzwTnbcINLam32H4iJJBRxsegwt2n78,8455
|
|
116
116
|
stouputils/installer/__init__.py,sha256=DBwI9w3xvw0NR_jDMxmURwPi1F79kPLe7EuNjmrxW_U,502
|
|
117
117
|
stouputils/installer/__init__.pyi,sha256=ZB-8frAUOW-0pCEJL-e2AdbFodivv46v3EBYwEXCxRo,117
|
|
118
118
|
stouputils/installer/common.py,sha256=UJr5u02h4LQZQdkmVOkJ3vvW_0-ROGgVMMh0PNoVS1A,2209
|
|
@@ -127,14 +127,16 @@ stouputils/installer/windows.py,sha256=r2AIuoyAmtMEuoCtQBH9GWQWI-JUT2J9zoH28j9ru
|
|
|
127
127
|
stouputils/installer/windows.pyi,sha256=tHogIFhPVDQS0I10liLkAxnpaFFAvmFtEVMpPIae5LU,1616
|
|
128
128
|
stouputils/io.py,sha256=XG2cReP8wzmoe0LyMtUqvEqixiHehPvXW23h5hBf_Pw,17202
|
|
129
129
|
stouputils/io.pyi,sha256=TCBTVEWUkI3dO_jWI9oPMF9SbnT1yLzFChE551JPbSY,9076
|
|
130
|
-
stouputils/parallel.py,sha256=
|
|
130
|
+
stouputils/parallel.py,sha256=CJUhoB270QT6XXpg0fHOlJdwbvoFd6qFQhCAZDFZng4,21648
|
|
131
131
|
stouputils/parallel.pyi,sha256=BTAtl4TFr71LgV3nVBY-yjpxUxlt9m6O2q82tNFHlbE,12420
|
|
132
|
-
stouputils/print.py,sha256=
|
|
132
|
+
stouputils/print.py,sha256=q-qSkUGeyn-lBMU5GU36ccm_dTmWS2i_RMxMYUhncfY,24564
|
|
133
133
|
stouputils/print.pyi,sha256=SRAAdObriW_LPcqvDGrCpjfGLrswRhIyJmCvC9_3OpM,10232
|
|
134
134
|
stouputils/py.typed,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
135
|
+
stouputils/typing.py,sha256=TwvxrvxhBRkyHkoOpfyXebN13M3xJb8MAjKXiNIWjew,2205
|
|
136
|
+
stouputils/typing.pyi,sha256=U2UmFZausMYpnsUQROQE2JOwHcjx2hKV0rJuOdR57Ew,1341
|
|
135
137
|
stouputils/version_pkg.py,sha256=Jsp-s03L14DkiZ94vQgrlQmaxApfn9DC8M_nzT1SJLk,7014
|
|
136
138
|
stouputils/version_pkg.pyi,sha256=QPvqp1U3QA-9C_CC1dT9Vahv1hXEhstbM7x5uzMZSsQ,755
|
|
137
|
-
stouputils-1.
|
|
138
|
-
stouputils-1.
|
|
139
|
-
stouputils-1.
|
|
140
|
-
stouputils-1.
|
|
139
|
+
stouputils-1.16.0.dist-info/WHEEL,sha256=XV0cjMrO7zXhVAIyyc8aFf1VjZ33Fen4IiJk5zFlC3g,80
|
|
140
|
+
stouputils-1.16.0.dist-info/entry_points.txt,sha256=tx0z9VOnE-sfkmbFbA93zaBMzV3XSsKEJa_BWIqUzxw,57
|
|
141
|
+
stouputils-1.16.0.dist-info/METADATA,sha256=cSM0j3GOs_HHAfqbLFyDyRo8khriZLWyL__71W7JFZE,13890
|
|
142
|
+
stouputils-1.16.0.dist-info/RECORD,,
|
|
File without changes
|