stouputils 1.15.0__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 +73 -2
- stouputils/parallel.pyi +21 -1
- stouputils/print.py +2 -1
- stouputils/typing.py +71 -0
- stouputils/typing.pyi +42 -0
- {stouputils-1.15.0.dist-info → stouputils-1.16.0.dist-info}/METADATA +2 -1
- {stouputils-1.15.0.dist-info → stouputils-1.16.0.dist-info}/RECORD +23 -21
- {stouputils-1.15.0.dist-info → stouputils-1.16.0.dist-info}/WHEEL +2 -2
- {stouputils-1.15.0.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
|
@@ -7,6 +7,16 @@ This module provides utility functions for parallel processing, such as:
|
|
|
7
7
|
|
|
8
8
|
I highly encourage you to read the function docstrings to understand when to use each method.
|
|
9
9
|
|
|
10
|
+
Priority (nice) mapping for multiprocessing():
|
|
11
|
+
|
|
12
|
+
- Unix-style values from -20 (highest priority) to 19 (lowest priority)
|
|
13
|
+
- Windows automatic mapping:
|
|
14
|
+
* -20 to -10: HIGH_PRIORITY_CLASS
|
|
15
|
+
* -9 to -1: ABOVE_NORMAL_PRIORITY_CLASS
|
|
16
|
+
* 0: NORMAL_PRIORITY_CLASS
|
|
17
|
+
* 1 to 9: BELOW_NORMAL_PRIORITY_CLASS
|
|
18
|
+
* 10 to 19: IDLE_PRIORITY_CLASS
|
|
19
|
+
|
|
10
20
|
.. image:: https://raw.githubusercontent.com/Stoupy51/stouputils/refs/heads/main/assets/parallel_module.gif
|
|
11
21
|
:alt: stouputils parallel examples
|
|
12
22
|
"""
|
|
@@ -42,6 +52,7 @@ def multiprocessing[T, R](
|
|
|
42
52
|
desc: str = "",
|
|
43
53
|
max_workers: int | float = CPU_COUNT,
|
|
44
54
|
delay_first_calls: float = 0,
|
|
55
|
+
nice: int | None = None,
|
|
45
56
|
color: str = MAGENTA,
|
|
46
57
|
bar_format: str = BAR_FORMAT,
|
|
47
58
|
ascii: bool = False,
|
|
@@ -69,6 +80,11 @@ def multiprocessing[T, R](
|
|
|
69
80
|
delay_first_calls (float): Apply i*delay_first_calls seconds delay to the first "max_workers" calls.
|
|
70
81
|
For instance, the first process will be delayed by 0 seconds, the second by 1 second, etc.
|
|
71
82
|
(Defaults to 0): This can be useful to avoid functions being called in the same second.
|
|
83
|
+
nice (int | None): Adjust the priority of worker processes (Defaults to None).
|
|
84
|
+
Use Unix-style values: -20 (highest priority) to 19 (lowest priority).
|
|
85
|
+
Positive values reduce priority, negative values increase it.
|
|
86
|
+
Automatically converted to appropriate priority class on Windows.
|
|
87
|
+
If None, no priority adjustment is made.
|
|
72
88
|
color (str): Color of the progress bar (Defaults to MAGENTA)
|
|
73
89
|
bar_format (str): Format of the progress bar (Defaults to BAR_FORMAT)
|
|
74
90
|
ascii (bool): Whether to use ASCII or Unicode characters for the progress bar
|
|
@@ -140,13 +156,21 @@ def multiprocessing[T, R](
|
|
|
140
156
|
# Do multiprocessing only if there is more than 1 argument and more than 1 CPU
|
|
141
157
|
if max_workers > 1 and len(args) > 1:
|
|
142
158
|
def process() -> list[Any]:
|
|
159
|
+
# Wrap function with nice if specified
|
|
160
|
+
if nice is not None:
|
|
161
|
+
wrapped_args = [(nice, func, arg) for arg in args]
|
|
162
|
+
wrapped_func = _nice_wrapper
|
|
163
|
+
else:
|
|
164
|
+
wrapped_args = args
|
|
165
|
+
wrapped_func = func
|
|
166
|
+
|
|
143
167
|
if verbose:
|
|
144
168
|
return list(process_map(
|
|
145
|
-
|
|
169
|
+
wrapped_func, wrapped_args, max_workers=max_workers, chunksize=chunksize, desc=desc, bar_format=bar_format, ascii=ascii, **tqdm_kwargs
|
|
146
170
|
)) # type: ignore
|
|
147
171
|
else:
|
|
148
172
|
with Pool(max_workers) as pool:
|
|
149
|
-
return list(pool.map(
|
|
173
|
+
return list(pool.map(wrapped_func, wrapped_args, chunksize=chunksize)) # type: ignore
|
|
150
174
|
try:
|
|
151
175
|
return process()
|
|
152
176
|
except RuntimeError as e:
|
|
@@ -382,6 +406,53 @@ def run_in_subprocess[R](
|
|
|
382
406
|
raise RuntimeError("Subprocess did not return any result") from e
|
|
383
407
|
|
|
384
408
|
|
|
409
|
+
# "Private" function to wrap function execution with nice priority (must be at module level for pickling)
|
|
410
|
+
def _nice_wrapper[T, R](args: tuple[int, Callable[[T], R], T]) -> R:
|
|
411
|
+
""" Wrapper that applies nice priority then executes the function.
|
|
412
|
+
|
|
413
|
+
Args:
|
|
414
|
+
args (tuple): Tuple containing (nice_value, func, arg)
|
|
415
|
+
|
|
416
|
+
Returns:
|
|
417
|
+
R: Result of the function execution
|
|
418
|
+
"""
|
|
419
|
+
nice_value, func, arg = args
|
|
420
|
+
_set_process_priority(nice_value)
|
|
421
|
+
return func(arg)
|
|
422
|
+
|
|
423
|
+
# "Private" function to set process priority (must be at module level for pickling on Windows)
|
|
424
|
+
def _set_process_priority(nice_value: int) -> None:
|
|
425
|
+
""" Set the priority of the current process.
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
nice_value (int): Unix-style priority value (-20 to 19)
|
|
429
|
+
"""
|
|
430
|
+
try:
|
|
431
|
+
import sys
|
|
432
|
+
if sys.platform == "win32":
|
|
433
|
+
# Map Unix nice values to Windows priority classes
|
|
434
|
+
# -20 to -10: HIGH, -9 to -1: ABOVE_NORMAL, 0: NORMAL, 1-9: BELOW_NORMAL, 10-19: IDLE
|
|
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)
|
|
450
|
+
else:
|
|
451
|
+
# Unix-like systems
|
|
452
|
+
os.nice(nice_value)
|
|
453
|
+
except Exception:
|
|
454
|
+
pass # Silently ignore if we can't set priority
|
|
455
|
+
|
|
385
456
|
# "Private" function for subprocess wrapper (must be at module level for pickling on Windows)
|
|
386
457
|
def _subprocess_wrapper[R](
|
|
387
458
|
result_queue: Any,
|
stouputils/parallel.pyi
CHANGED
|
@@ -10,7 +10,7 @@ CPU_COUNT: int
|
|
|
10
10
|
T = TypeVar('T')
|
|
11
11
|
R = TypeVar('R')
|
|
12
12
|
|
|
13
|
-
def multiprocessing[T, R](func: Callable[..., R] | list[Callable[..., R]], args: Iterable[T], use_starmap: bool = False, chunksize: int = 1, desc: str = '', max_workers: int | float = ..., delay_first_calls: float = 0, color: str = ..., bar_format: str = ..., ascii: bool = False, smooth_tqdm: bool = True, **tqdm_kwargs: Any) -> list[R]:
|
|
13
|
+
def multiprocessing[T, R](func: Callable[..., R] | list[Callable[..., R]], args: Iterable[T], use_starmap: bool = False, chunksize: int = 1, desc: str = '', max_workers: int | float = ..., delay_first_calls: float = 0, nice: int | None = None, color: str = ..., bar_format: str = ..., ascii: bool = False, smooth_tqdm: bool = True, **tqdm_kwargs: Any) -> list[R]:
|
|
14
14
|
''' Method to execute a function in parallel using multiprocessing
|
|
15
15
|
|
|
16
16
|
\t- For CPU-bound operations where the GIL (Global Interpreter Lock) is a bottleneck.
|
|
@@ -32,6 +32,11 @@ def multiprocessing[T, R](func: Callable[..., R] | list[Callable[..., R]], args:
|
|
|
32
32
|
\t\tdelay_first_calls\t(float):\t\t\tApply i*delay_first_calls seconds delay to the first "max_workers" calls.
|
|
33
33
|
\t\t\tFor instance, the first process will be delayed by 0 seconds, the second by 1 second, etc.
|
|
34
34
|
\t\t\t(Defaults to 0): This can be useful to avoid functions being called in the same second.
|
|
35
|
+
\t\tnice\t\t\t\t(int | None):\t\tAdjust the priority of worker processes (Defaults to None).
|
|
36
|
+
\t\t\tUse Unix-style values: -20 (highest priority) to 19 (lowest priority).
|
|
37
|
+
\t\t\tPositive values reduce priority, negative values increase it.
|
|
38
|
+
\t\t\tAutomatically converted to appropriate priority class on Windows.
|
|
39
|
+
\t\t\tIf None, no priority adjustment is made.
|
|
35
40
|
\t\tcolor\t\t\t\t(str):\t\t\t\tColor of the progress bar (Defaults to MAGENTA)
|
|
36
41
|
\t\tbar_format\t\t\t(str):\t\t\t\tFormat of the progress bar (Defaults to BAR_FORMAT)
|
|
37
42
|
\t\tascii\t\t\t\t(bool):\t\t\t\tWhether to use ASCII or Unicode characters for the progress bar
|
|
@@ -169,6 +174,21 @@ def run_in_subprocess[R](func: Callable[..., R], *args: Any, timeout: float | No
|
|
|
169
174
|
\t\t\t> # With timeout to prevent hanging
|
|
170
175
|
\t\t\t> run_in_subprocess(some_gpu_func, data, timeout=300.0)
|
|
171
176
|
\t'''
|
|
177
|
+
def _nice_wrapper[T, R](args: tuple[int, Callable[[T], R], T]) -> R:
|
|
178
|
+
""" Wrapper that applies nice priority then executes the function.
|
|
179
|
+
|
|
180
|
+
\tArgs:
|
|
181
|
+
\t\targs (tuple): Tuple containing (nice_value, func, arg)
|
|
182
|
+
|
|
183
|
+
\tReturns:
|
|
184
|
+
\t\tR: Result of the function execution
|
|
185
|
+
\t"""
|
|
186
|
+
def _set_process_priority(nice_value: int) -> None:
|
|
187
|
+
""" Set the priority of the current process.
|
|
188
|
+
|
|
189
|
+
\tArgs:
|
|
190
|
+
\t\tnice_value (int): Unix-style priority value (-20 to 19)
|
|
191
|
+
\t"""
|
|
172
192
|
def _subprocess_wrapper[R](result_queue: Any, func: Callable[..., R], args: tuple[Any, ...], kwargs: dict[str, Any]) -> None:
|
|
173
193
|
""" Wrapper function to execute the target function and store the result in the queue.
|
|
174
194
|
|
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=
|
|
131
|
-
stouputils/parallel.pyi,sha256=
|
|
132
|
-
stouputils/print.py,sha256=
|
|
130
|
+
stouputils/parallel.py,sha256=CJUhoB270QT6XXpg0fHOlJdwbvoFd6qFQhCAZDFZng4,21648
|
|
131
|
+
stouputils/parallel.pyi,sha256=BTAtl4TFr71LgV3nVBY-yjpxUxlt9m6O2q82tNFHlbE,12420
|
|
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
|