stouputils 1.14.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 +40 -0
- stouputils/__main__.py +86 -0
- stouputils/_deprecated.py +37 -0
- stouputils/all_doctests.py +160 -0
- stouputils/applications/__init__.py +22 -0
- stouputils/applications/automatic_docs.py +634 -0
- stouputils/applications/upscaler/__init__.py +39 -0
- stouputils/applications/upscaler/config.py +128 -0
- stouputils/applications/upscaler/image.py +247 -0
- stouputils/applications/upscaler/video.py +287 -0
- stouputils/archive.py +344 -0
- stouputils/backup.py +488 -0
- stouputils/collections.py +244 -0
- stouputils/continuous_delivery/__init__.py +27 -0
- stouputils/continuous_delivery/cd_utils.py +243 -0
- stouputils/continuous_delivery/github.py +522 -0
- stouputils/continuous_delivery/pypi.py +130 -0
- stouputils/continuous_delivery/pyproject.py +147 -0
- stouputils/continuous_delivery/stubs.py +86 -0
- stouputils/ctx.py +408 -0
- stouputils/data_science/config/get.py +51 -0
- stouputils/data_science/config/set.py +125 -0
- stouputils/data_science/data_processing/image/__init__.py +66 -0
- stouputils/data_science/data_processing/image/auto_contrast.py +79 -0
- stouputils/data_science/data_processing/image/axis_flip.py +58 -0
- stouputils/data_science/data_processing/image/bias_field_correction.py +74 -0
- stouputils/data_science/data_processing/image/binary_threshold.py +73 -0
- stouputils/data_science/data_processing/image/blur.py +59 -0
- stouputils/data_science/data_processing/image/brightness.py +54 -0
- stouputils/data_science/data_processing/image/canny.py +110 -0
- stouputils/data_science/data_processing/image/clahe.py +92 -0
- stouputils/data_science/data_processing/image/common.py +30 -0
- stouputils/data_science/data_processing/image/contrast.py +53 -0
- stouputils/data_science/data_processing/image/curvature_flow_filter.py +74 -0
- stouputils/data_science/data_processing/image/denoise.py +378 -0
- stouputils/data_science/data_processing/image/histogram_equalization.py +123 -0
- stouputils/data_science/data_processing/image/invert.py +64 -0
- stouputils/data_science/data_processing/image/laplacian.py +60 -0
- stouputils/data_science/data_processing/image/median_blur.py +52 -0
- stouputils/data_science/data_processing/image/noise.py +59 -0
- stouputils/data_science/data_processing/image/normalize.py +65 -0
- stouputils/data_science/data_processing/image/random_erase.py +66 -0
- stouputils/data_science/data_processing/image/resize.py +69 -0
- stouputils/data_science/data_processing/image/rotation.py +80 -0
- stouputils/data_science/data_processing/image/salt_pepper.py +68 -0
- stouputils/data_science/data_processing/image/sharpening.py +55 -0
- stouputils/data_science/data_processing/image/shearing.py +64 -0
- stouputils/data_science/data_processing/image/threshold.py +64 -0
- stouputils/data_science/data_processing/image/translation.py +71 -0
- stouputils/data_science/data_processing/image/zoom.py +83 -0
- stouputils/data_science/data_processing/image_augmentation.py +118 -0
- stouputils/data_science/data_processing/image_preprocess.py +183 -0
- stouputils/data_science/data_processing/prosthesis_detection.py +359 -0
- stouputils/data_science/data_processing/technique.py +481 -0
- stouputils/data_science/dataset/__init__.py +45 -0
- stouputils/data_science/dataset/dataset.py +292 -0
- stouputils/data_science/dataset/dataset_loader.py +135 -0
- stouputils/data_science/dataset/grouping_strategy.py +296 -0
- stouputils/data_science/dataset/image_loader.py +100 -0
- stouputils/data_science/dataset/xy_tuple.py +696 -0
- stouputils/data_science/metric_dictionnary.py +106 -0
- stouputils/data_science/metric_utils.py +847 -0
- stouputils/data_science/mlflow_utils.py +206 -0
- stouputils/data_science/models/abstract_model.py +149 -0
- stouputils/data_science/models/all.py +85 -0
- stouputils/data_science/models/base_keras.py +765 -0
- stouputils/data_science/models/keras/all.py +38 -0
- stouputils/data_science/models/keras/convnext.py +62 -0
- stouputils/data_science/models/keras/densenet.py +50 -0
- stouputils/data_science/models/keras/efficientnet.py +60 -0
- stouputils/data_science/models/keras/mobilenet.py +56 -0
- stouputils/data_science/models/keras/resnet.py +52 -0
- stouputils/data_science/models/keras/squeezenet.py +233 -0
- stouputils/data_science/models/keras/vgg.py +42 -0
- stouputils/data_science/models/keras/xception.py +38 -0
- stouputils/data_science/models/keras_utils/callbacks/__init__.py +20 -0
- stouputils/data_science/models/keras_utils/callbacks/colored_progress_bar.py +219 -0
- stouputils/data_science/models/keras_utils/callbacks/learning_rate_finder.py +148 -0
- stouputils/data_science/models/keras_utils/callbacks/model_checkpoint_v2.py +31 -0
- stouputils/data_science/models/keras_utils/callbacks/progressive_unfreezing.py +249 -0
- stouputils/data_science/models/keras_utils/callbacks/warmup_scheduler.py +66 -0
- stouputils/data_science/models/keras_utils/losses/__init__.py +12 -0
- stouputils/data_science/models/keras_utils/losses/next_generation_loss.py +56 -0
- stouputils/data_science/models/keras_utils/visualizations.py +416 -0
- stouputils/data_science/models/model_interface.py +939 -0
- stouputils/data_science/models/sandbox.py +116 -0
- stouputils/data_science/range_tuple.py +234 -0
- stouputils/data_science/scripts/augment_dataset.py +77 -0
- stouputils/data_science/scripts/exhaustive_process.py +133 -0
- stouputils/data_science/scripts/preprocess_dataset.py +70 -0
- stouputils/data_science/scripts/routine.py +168 -0
- stouputils/data_science/utils.py +285 -0
- stouputils/decorators.py +605 -0
- stouputils/image.py +441 -0
- stouputils/installer/__init__.py +18 -0
- stouputils/installer/common.py +67 -0
- stouputils/installer/downloader.py +101 -0
- stouputils/installer/linux.py +144 -0
- stouputils/installer/main.py +223 -0
- stouputils/installer/windows.py +136 -0
- stouputils/io.py +486 -0
- stouputils/parallel.py +483 -0
- stouputils/print.py +482 -0
- stouputils/py.typed +1 -0
- stouputils/stouputils/__init__.pyi +15 -0
- stouputils/stouputils/_deprecated.pyi +12 -0
- stouputils/stouputils/all_doctests.pyi +46 -0
- stouputils/stouputils/applications/__init__.pyi +2 -0
- stouputils/stouputils/applications/automatic_docs.pyi +106 -0
- stouputils/stouputils/applications/upscaler/__init__.pyi +3 -0
- stouputils/stouputils/applications/upscaler/config.pyi +18 -0
- stouputils/stouputils/applications/upscaler/image.pyi +109 -0
- stouputils/stouputils/applications/upscaler/video.pyi +60 -0
- stouputils/stouputils/archive.pyi +67 -0
- stouputils/stouputils/backup.pyi +109 -0
- stouputils/stouputils/collections.pyi +86 -0
- stouputils/stouputils/continuous_delivery/__init__.pyi +5 -0
- stouputils/stouputils/continuous_delivery/cd_utils.pyi +129 -0
- stouputils/stouputils/continuous_delivery/github.pyi +162 -0
- stouputils/stouputils/continuous_delivery/pypi.pyi +53 -0
- stouputils/stouputils/continuous_delivery/pyproject.pyi +67 -0
- stouputils/stouputils/continuous_delivery/stubs.pyi +39 -0
- stouputils/stouputils/ctx.pyi +211 -0
- stouputils/stouputils/decorators.pyi +252 -0
- stouputils/stouputils/image.pyi +172 -0
- stouputils/stouputils/installer/__init__.pyi +5 -0
- stouputils/stouputils/installer/common.pyi +39 -0
- stouputils/stouputils/installer/downloader.pyi +24 -0
- stouputils/stouputils/installer/linux.pyi +39 -0
- stouputils/stouputils/installer/main.pyi +57 -0
- stouputils/stouputils/installer/windows.pyi +31 -0
- stouputils/stouputils/io.pyi +213 -0
- stouputils/stouputils/parallel.pyi +216 -0
- stouputils/stouputils/print.pyi +136 -0
- stouputils/stouputils/version_pkg.pyi +15 -0
- stouputils/version_pkg.py +189 -0
- stouputils-1.14.0.dist-info/METADATA +178 -0
- stouputils-1.14.0.dist-info/RECORD +140 -0
- stouputils-1.14.0.dist-info/WHEEL +4 -0
- stouputils-1.14.0.dist-info/entry_points.txt +3 -0
stouputils/__init__.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
""" A collection of utility modules designed to simplify and enhance the development process.
|
|
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
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
# Version (handle case where the package is not installed)
|
|
18
|
+
from importlib.metadata import PackageNotFoundError
|
|
19
|
+
from importlib.metadata import version as importlib_version
|
|
20
|
+
|
|
21
|
+
# Imports
|
|
22
|
+
from ._deprecated import *
|
|
23
|
+
from .all_doctests import *
|
|
24
|
+
from .archive import *
|
|
25
|
+
from .backup import *
|
|
26
|
+
from .collections import *
|
|
27
|
+
from .continuous_delivery import *
|
|
28
|
+
from .ctx import *
|
|
29
|
+
from .decorators import *
|
|
30
|
+
from .image import *
|
|
31
|
+
from .io import *
|
|
32
|
+
from .parallel import *
|
|
33
|
+
from .print import *
|
|
34
|
+
from .version_pkg import *
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
__version__: str = importlib_version("stouputils")
|
|
38
|
+
except PackageNotFoundError:
|
|
39
|
+
__version__: str = "0.0.0-dev"
|
|
40
|
+
|
stouputils/__main__.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
# PYTHON_ARGCOMPLETE_OK
|
|
4
|
+
# Imports
|
|
5
|
+
import argparse
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
import argcomplete
|
|
9
|
+
|
|
10
|
+
from .all_doctests import launch_tests
|
|
11
|
+
from .archive import archive_cli
|
|
12
|
+
from .backup import backup_cli
|
|
13
|
+
from .decorators import handle_error
|
|
14
|
+
from .print import CYAN, GREEN, RESET
|
|
15
|
+
from .version_pkg import show_version_cli
|
|
16
|
+
|
|
17
|
+
# Argument Parser Setup for Auto-Completion
|
|
18
|
+
parser = argparse.ArgumentParser(prog="stouputils", add_help=False)
|
|
19
|
+
parser.add_argument("command", nargs="?", choices=[
|
|
20
|
+
"--version", "-v", "version", "show_version", "all_doctests", "archive", "backup", "build"
|
|
21
|
+
])
|
|
22
|
+
parser.add_argument("args", nargs="*")
|
|
23
|
+
argcomplete.autocomplete(parser)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@handle_error(message="Error while running 'stouputils'")
|
|
27
|
+
def main() -> None:
|
|
28
|
+
second_arg: str = sys.argv[1].lower() if len(sys.argv) >= 2 else ""
|
|
29
|
+
|
|
30
|
+
# Print the version of stouputils and its dependencies
|
|
31
|
+
if second_arg in ("--version", "-v", "version", "show_version"):
|
|
32
|
+
return show_version_cli()
|
|
33
|
+
|
|
34
|
+
# Handle "all_doctests" command
|
|
35
|
+
if second_arg == "all_doctests":
|
|
36
|
+
if launch_tests("." if len(sys.argv) == 2 else sys.argv[2]) > 0:
|
|
37
|
+
sys.exit(1)
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
# Handle "archive" command
|
|
41
|
+
if second_arg == "archive":
|
|
42
|
+
sys.argv.pop(1) # Remove "archive" from argv so archive_cli gets clean arguments
|
|
43
|
+
return archive_cli()
|
|
44
|
+
|
|
45
|
+
# Handle "backup" command
|
|
46
|
+
if second_arg == "backup":
|
|
47
|
+
sys.argv.pop(1) # Remove "backup" from argv so backup_cli gets clean arguments
|
|
48
|
+
return backup_cli()
|
|
49
|
+
|
|
50
|
+
# Handle "build" command
|
|
51
|
+
if second_arg == "build":
|
|
52
|
+
from .continuous_delivery.pypi import pypi_full_routine_using_uv
|
|
53
|
+
return pypi_full_routine_using_uv()
|
|
54
|
+
|
|
55
|
+
# Check if the command is any package name
|
|
56
|
+
if second_arg in (): # type: ignore
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
# Get version
|
|
60
|
+
from importlib.metadata import version
|
|
61
|
+
try:
|
|
62
|
+
pkg_version = version("stouputils")
|
|
63
|
+
except Exception:
|
|
64
|
+
pkg_version = "unknown"
|
|
65
|
+
|
|
66
|
+
# Print help with nice formatting
|
|
67
|
+
separator: str = "─" * 60
|
|
68
|
+
print(f"""
|
|
69
|
+
{CYAN}{separator}{RESET}
|
|
70
|
+
{CYAN}stouputils {GREEN}CLI {CYAN}v{pkg_version}{RESET}
|
|
71
|
+
{CYAN}{separator}{RESET}
|
|
72
|
+
{CYAN}Usage:{RESET} stouputils <command> [options]
|
|
73
|
+
|
|
74
|
+
{CYAN}Available commands:{RESET}
|
|
75
|
+
{GREEN}--version, -v{RESET} [pkg] [-t <depth>] Show version information (optionally for a specific package)
|
|
76
|
+
{GREEN}all_doctests{RESET} [dir] Run all doctests in the specified directory
|
|
77
|
+
{GREEN}archive{RESET} --help Archive utilities (make, repair)
|
|
78
|
+
{GREEN}backup{RESET} --help Backup utilities (delta, consolidate, limit)
|
|
79
|
+
{GREEN}build{RESET} [--no_stubs] [<minor|major>] Build and publish package to PyPI using 'uv' tool (complete routine)
|
|
80
|
+
{CYAN}{separator}{RESET}
|
|
81
|
+
""".strip())
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
main()
|
|
86
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
""" Deprecated functions and classes.
|
|
2
|
+
|
|
3
|
+
This module contains deprecated functions that have been replaced by new implementations
|
|
4
|
+
These functions are retained for backward compatibility and will log deprecation warnings when used.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Imports
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from .decorators import LogLevels, deprecated
|
|
11
|
+
from .io import csv_dump, csv_load, json_dump, json_load
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Deprecated functions
|
|
15
|
+
@deprecated(message="super_csv_dump has been renamed to csv_dump.", version="v1.8.0", error_log=LogLevels.WARNING)
|
|
16
|
+
def super_csv_dump(*args: Any, **kwargs: Any) -> Any:
|
|
17
|
+
""" Deprecated function, use "csv_dump" instead. """
|
|
18
|
+
return csv_dump(*args, **kwargs)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@deprecated(message="super_csv_load has been renamed to csv_load.", version="v1.8.0", error_log=LogLevels.WARNING)
|
|
22
|
+
def super_csv_load(*args: Any, **kwargs: Any) -> Any:
|
|
23
|
+
""" Deprecated function, use "csv_load" instead. """
|
|
24
|
+
return csv_load(*args, **kwargs)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@deprecated(message="super_json_dump has been renamed to json_dump.", version="v1.8.0", error_log=LogLevels.WARNING)
|
|
28
|
+
def super_json_dump(*args: Any, **kwargs: Any) -> Any:
|
|
29
|
+
""" Deprecated function, use "json_dump" instead. """
|
|
30
|
+
return json_dump(*args, **kwargs)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@deprecated(message="super_json_load has been renamed to json_load.", version="v1.8.0", error_log=LogLevels.WARNING)
|
|
34
|
+
def super_json_load(*args: Any, **kwargs: Any) -> Any:
|
|
35
|
+
""" Deprecated function, use "json_load" instead. """
|
|
36
|
+
return json_load(*args, **kwargs)
|
|
37
|
+
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module is used to run all the doctests for all the modules in a given directory.
|
|
3
|
+
|
|
4
|
+
- launch_tests: Main function to launch tests for all modules in the given directory.
|
|
5
|
+
- test_module_with_progress: Test a module with testmod and measure the time taken with progress printing.
|
|
6
|
+
|
|
7
|
+
.. image:: https://raw.githubusercontent.com/Stoupy51/stouputils/refs/heads/main/assets/all_doctests_module.gif
|
|
8
|
+
:alt: stouputils all_doctests examples
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# Imports
|
|
12
|
+
import importlib
|
|
13
|
+
import os
|
|
14
|
+
import pkgutil
|
|
15
|
+
import sys
|
|
16
|
+
from types import ModuleType
|
|
17
|
+
from typing import TYPE_CHECKING
|
|
18
|
+
|
|
19
|
+
from . import decorators
|
|
20
|
+
from .decorators import measure_time
|
|
21
|
+
from .io import clean_path, relative_path
|
|
22
|
+
from .print import error, info, progress, warning
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from doctest import TestResults
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Main program
|
|
29
|
+
def launch_tests(root_dir: str, strict: bool = True) -> int:
|
|
30
|
+
""" Main function to launch tests for all modules in the given directory.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
root_dir (str): Root directory to search for modules
|
|
34
|
+
strict (bool): Modify the force_raise_exception variable to True in the decorators module
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
int: The number of failed tests
|
|
38
|
+
|
|
39
|
+
Examples:
|
|
40
|
+
>>> launch_tests("unknown_dir")
|
|
41
|
+
Traceback (most recent call last):
|
|
42
|
+
...
|
|
43
|
+
ValueError: No modules found in 'unknown_dir'
|
|
44
|
+
|
|
45
|
+
.. code-block:: python
|
|
46
|
+
|
|
47
|
+
> if launch_tests("/path/to/source") > 0:
|
|
48
|
+
sys.exit(1)
|
|
49
|
+
[PROGRESS HH:MM:SS] Importing module 'module1' took 0.001s
|
|
50
|
+
[PROGRESS HH:MM:SS] Importing module 'module2' took 0.002s
|
|
51
|
+
[PROGRESS HH:MM:SS] Importing module 'module3' took 0.003s
|
|
52
|
+
[PROGRESS HH:MM:SS] Importing module 'module4' took 0.004s
|
|
53
|
+
[INFO HH:MM:SS] Testing 4 modules...
|
|
54
|
+
[PROGRESS HH:MM:SS] Testing module 'module1' took 0.005s
|
|
55
|
+
[PROGRESS HH:MM:SS] Testing module 'module2' took 0.006s
|
|
56
|
+
[PROGRESS HH:MM:SS] Testing module 'module3' took 0.007s
|
|
57
|
+
[PROGRESS HH:MM:SS] Testing module 'module4' took 0.008s
|
|
58
|
+
"""
|
|
59
|
+
if strict:
|
|
60
|
+
old_value: bool = strict
|
|
61
|
+
decorators.force_raise_exception = True
|
|
62
|
+
strict = old_value
|
|
63
|
+
|
|
64
|
+
# Get the path of the directory to check modules from
|
|
65
|
+
working_dir: str = clean_path(os.getcwd())
|
|
66
|
+
root_dir = clean_path(os.path.abspath(root_dir))
|
|
67
|
+
dir_to_check: str = os.path.dirname(root_dir) if working_dir != root_dir else root_dir
|
|
68
|
+
|
|
69
|
+
# Get all modules from folder
|
|
70
|
+
sys.path.insert(0, dir_to_check)
|
|
71
|
+
modules_file_paths: list[str] = []
|
|
72
|
+
for directory_path, _, _ in os.walk(root_dir):
|
|
73
|
+
directory_path = clean_path(directory_path)
|
|
74
|
+
for module_info in pkgutil.walk_packages([directory_path]):
|
|
75
|
+
|
|
76
|
+
# Extract root and module name
|
|
77
|
+
module_root: str = str(module_info.module_finder.path) # type: ignore
|
|
78
|
+
module_name: str = module_info.name.split(".")[-1]
|
|
79
|
+
|
|
80
|
+
# Get the absolute path
|
|
81
|
+
absolute_module_path: str = clean_path(os.path.join(module_root, module_name))
|
|
82
|
+
|
|
83
|
+
# Check if the module is in the root directory that we want to check
|
|
84
|
+
if root_dir in absolute_module_path:
|
|
85
|
+
|
|
86
|
+
# Get the path of the module like 'stouputils.io'
|
|
87
|
+
path: str = absolute_module_path.split(dir_to_check, 1)[1].replace("/", ".")[1:]
|
|
88
|
+
|
|
89
|
+
# If the module is not already in the list, add it
|
|
90
|
+
if path not in modules_file_paths:
|
|
91
|
+
modules_file_paths.append(path)
|
|
92
|
+
|
|
93
|
+
# If no modules are found, raise an error
|
|
94
|
+
if not modules_file_paths:
|
|
95
|
+
raise ValueError(f"No modules found in '{relative_path(root_dir)}'")
|
|
96
|
+
|
|
97
|
+
# Find longest module path for alignment
|
|
98
|
+
max_length: int = max(len(path) for path in modules_file_paths)
|
|
99
|
+
|
|
100
|
+
# Dynamically import all modules from iacob package recursively using pkgutil and importlib
|
|
101
|
+
modules: list[ModuleType] = []
|
|
102
|
+
separators: list[str] = []
|
|
103
|
+
for module_path in modules_file_paths:
|
|
104
|
+
separator: str = " " * (max_length - len(module_path))
|
|
105
|
+
|
|
106
|
+
@measure_time(message=f"Importing module '{module_path}' {separator}took")
|
|
107
|
+
def internal(a: str = module_path, b: str = separator) -> None:
|
|
108
|
+
modules.append(importlib.import_module(a))
|
|
109
|
+
separators.append(b)
|
|
110
|
+
|
|
111
|
+
try:
|
|
112
|
+
internal()
|
|
113
|
+
except Exception as e:
|
|
114
|
+
warning(f"Failed to import module '{module_path}': ({type(e).__name__}) {e}")
|
|
115
|
+
|
|
116
|
+
# Run tests for each module
|
|
117
|
+
info(f"Testing {len(modules)} modules...")
|
|
118
|
+
separators = [s + " "*(len("Importing") - len("Testing")) for s in separators]
|
|
119
|
+
results: list[TestResults] = [
|
|
120
|
+
test_module_with_progress(module, separator)
|
|
121
|
+
for module, separator in zip(modules, separators, strict=False)
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
# Display any error lines for each module at the end of the script
|
|
125
|
+
total_failed: int = 0
|
|
126
|
+
for module, result in zip(modules, results, strict=False):
|
|
127
|
+
if result.failed > 0:
|
|
128
|
+
successful_tests: int = result.attempted - result.failed
|
|
129
|
+
error(f"Errors in module {module.__name__} ({successful_tests}/{result.attempted} tests passed)", exit=False)
|
|
130
|
+
total_failed += result.failed
|
|
131
|
+
|
|
132
|
+
# Reset force_raise_exception back
|
|
133
|
+
decorators.force_raise_exception = strict
|
|
134
|
+
|
|
135
|
+
# Final info
|
|
136
|
+
total_tests: int = sum(result.attempted for result in results)
|
|
137
|
+
successful_tests: int = total_tests - total_failed
|
|
138
|
+
if total_failed == 0:
|
|
139
|
+
info(f"All tests passed for all {len(modules)} modules! ({total_tests}/{total_tests} tests passed)")
|
|
140
|
+
else:
|
|
141
|
+
error(f"Some tests failed: {successful_tests}/{total_tests} tests passed in total across {len(modules)} modules", exit=False)
|
|
142
|
+
# Return the number of failed tests
|
|
143
|
+
return total_failed
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def test_module_with_progress(module: ModuleType, separator: str) -> "TestResults":
|
|
147
|
+
""" Test a module with testmod and measure the time taken with progress printing.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
module (ModuleType): Module to test
|
|
151
|
+
separator (str): Separator string for alignment in output
|
|
152
|
+
Returns:
|
|
153
|
+
TestResults: The results of the tests
|
|
154
|
+
"""
|
|
155
|
+
from doctest import TestResults, testmod
|
|
156
|
+
@measure_time(message=f"Testing module '{module.__name__}' {separator}took")
|
|
157
|
+
def internal() -> TestResults:
|
|
158
|
+
return testmod(m=module)
|
|
159
|
+
return internal()
|
|
160
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
""" Application-specific utilities and tools.
|
|
2
|
+
|
|
3
|
+
This module provides higher-level utilities for specific application needs:
|
|
4
|
+
|
|
5
|
+
Automatic Documentation:
|
|
6
|
+
|
|
7
|
+
- Automatic documentation generation with Sphinx: `update_documentation(...)`
|
|
8
|
+
- Support for multi-version documentation
|
|
9
|
+
- GitHub Pages integration
|
|
10
|
+
- Markdown to RST conversion
|
|
11
|
+
|
|
12
|
+
Upscaler:
|
|
13
|
+
|
|
14
|
+
- TODO
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
# ruff: noqa: F403
|
|
18
|
+
|
|
19
|
+
# Imports
|
|
20
|
+
from .automatic_docs import *
|
|
21
|
+
from .upscaler import *
|
|
22
|
+
|