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.
Files changed (140) hide show
  1. stouputils/__init__.py +40 -0
  2. stouputils/__main__.py +86 -0
  3. stouputils/_deprecated.py +37 -0
  4. stouputils/all_doctests.py +160 -0
  5. stouputils/applications/__init__.py +22 -0
  6. stouputils/applications/automatic_docs.py +634 -0
  7. stouputils/applications/upscaler/__init__.py +39 -0
  8. stouputils/applications/upscaler/config.py +128 -0
  9. stouputils/applications/upscaler/image.py +247 -0
  10. stouputils/applications/upscaler/video.py +287 -0
  11. stouputils/archive.py +344 -0
  12. stouputils/backup.py +488 -0
  13. stouputils/collections.py +244 -0
  14. stouputils/continuous_delivery/__init__.py +27 -0
  15. stouputils/continuous_delivery/cd_utils.py +243 -0
  16. stouputils/continuous_delivery/github.py +522 -0
  17. stouputils/continuous_delivery/pypi.py +130 -0
  18. stouputils/continuous_delivery/pyproject.py +147 -0
  19. stouputils/continuous_delivery/stubs.py +86 -0
  20. stouputils/ctx.py +408 -0
  21. stouputils/data_science/config/get.py +51 -0
  22. stouputils/data_science/config/set.py +125 -0
  23. stouputils/data_science/data_processing/image/__init__.py +66 -0
  24. stouputils/data_science/data_processing/image/auto_contrast.py +79 -0
  25. stouputils/data_science/data_processing/image/axis_flip.py +58 -0
  26. stouputils/data_science/data_processing/image/bias_field_correction.py +74 -0
  27. stouputils/data_science/data_processing/image/binary_threshold.py +73 -0
  28. stouputils/data_science/data_processing/image/blur.py +59 -0
  29. stouputils/data_science/data_processing/image/brightness.py +54 -0
  30. stouputils/data_science/data_processing/image/canny.py +110 -0
  31. stouputils/data_science/data_processing/image/clahe.py +92 -0
  32. stouputils/data_science/data_processing/image/common.py +30 -0
  33. stouputils/data_science/data_processing/image/contrast.py +53 -0
  34. stouputils/data_science/data_processing/image/curvature_flow_filter.py +74 -0
  35. stouputils/data_science/data_processing/image/denoise.py +378 -0
  36. stouputils/data_science/data_processing/image/histogram_equalization.py +123 -0
  37. stouputils/data_science/data_processing/image/invert.py +64 -0
  38. stouputils/data_science/data_processing/image/laplacian.py +60 -0
  39. stouputils/data_science/data_processing/image/median_blur.py +52 -0
  40. stouputils/data_science/data_processing/image/noise.py +59 -0
  41. stouputils/data_science/data_processing/image/normalize.py +65 -0
  42. stouputils/data_science/data_processing/image/random_erase.py +66 -0
  43. stouputils/data_science/data_processing/image/resize.py +69 -0
  44. stouputils/data_science/data_processing/image/rotation.py +80 -0
  45. stouputils/data_science/data_processing/image/salt_pepper.py +68 -0
  46. stouputils/data_science/data_processing/image/sharpening.py +55 -0
  47. stouputils/data_science/data_processing/image/shearing.py +64 -0
  48. stouputils/data_science/data_processing/image/threshold.py +64 -0
  49. stouputils/data_science/data_processing/image/translation.py +71 -0
  50. stouputils/data_science/data_processing/image/zoom.py +83 -0
  51. stouputils/data_science/data_processing/image_augmentation.py +118 -0
  52. stouputils/data_science/data_processing/image_preprocess.py +183 -0
  53. stouputils/data_science/data_processing/prosthesis_detection.py +359 -0
  54. stouputils/data_science/data_processing/technique.py +481 -0
  55. stouputils/data_science/dataset/__init__.py +45 -0
  56. stouputils/data_science/dataset/dataset.py +292 -0
  57. stouputils/data_science/dataset/dataset_loader.py +135 -0
  58. stouputils/data_science/dataset/grouping_strategy.py +296 -0
  59. stouputils/data_science/dataset/image_loader.py +100 -0
  60. stouputils/data_science/dataset/xy_tuple.py +696 -0
  61. stouputils/data_science/metric_dictionnary.py +106 -0
  62. stouputils/data_science/metric_utils.py +847 -0
  63. stouputils/data_science/mlflow_utils.py +206 -0
  64. stouputils/data_science/models/abstract_model.py +149 -0
  65. stouputils/data_science/models/all.py +85 -0
  66. stouputils/data_science/models/base_keras.py +765 -0
  67. stouputils/data_science/models/keras/all.py +38 -0
  68. stouputils/data_science/models/keras/convnext.py +62 -0
  69. stouputils/data_science/models/keras/densenet.py +50 -0
  70. stouputils/data_science/models/keras/efficientnet.py +60 -0
  71. stouputils/data_science/models/keras/mobilenet.py +56 -0
  72. stouputils/data_science/models/keras/resnet.py +52 -0
  73. stouputils/data_science/models/keras/squeezenet.py +233 -0
  74. stouputils/data_science/models/keras/vgg.py +42 -0
  75. stouputils/data_science/models/keras/xception.py +38 -0
  76. stouputils/data_science/models/keras_utils/callbacks/__init__.py +20 -0
  77. stouputils/data_science/models/keras_utils/callbacks/colored_progress_bar.py +219 -0
  78. stouputils/data_science/models/keras_utils/callbacks/learning_rate_finder.py +148 -0
  79. stouputils/data_science/models/keras_utils/callbacks/model_checkpoint_v2.py +31 -0
  80. stouputils/data_science/models/keras_utils/callbacks/progressive_unfreezing.py +249 -0
  81. stouputils/data_science/models/keras_utils/callbacks/warmup_scheduler.py +66 -0
  82. stouputils/data_science/models/keras_utils/losses/__init__.py +12 -0
  83. stouputils/data_science/models/keras_utils/losses/next_generation_loss.py +56 -0
  84. stouputils/data_science/models/keras_utils/visualizations.py +416 -0
  85. stouputils/data_science/models/model_interface.py +939 -0
  86. stouputils/data_science/models/sandbox.py +116 -0
  87. stouputils/data_science/range_tuple.py +234 -0
  88. stouputils/data_science/scripts/augment_dataset.py +77 -0
  89. stouputils/data_science/scripts/exhaustive_process.py +133 -0
  90. stouputils/data_science/scripts/preprocess_dataset.py +70 -0
  91. stouputils/data_science/scripts/routine.py +168 -0
  92. stouputils/data_science/utils.py +285 -0
  93. stouputils/decorators.py +605 -0
  94. stouputils/image.py +441 -0
  95. stouputils/installer/__init__.py +18 -0
  96. stouputils/installer/common.py +67 -0
  97. stouputils/installer/downloader.py +101 -0
  98. stouputils/installer/linux.py +144 -0
  99. stouputils/installer/main.py +223 -0
  100. stouputils/installer/windows.py +136 -0
  101. stouputils/io.py +486 -0
  102. stouputils/parallel.py +483 -0
  103. stouputils/print.py +482 -0
  104. stouputils/py.typed +1 -0
  105. stouputils/stouputils/__init__.pyi +15 -0
  106. stouputils/stouputils/_deprecated.pyi +12 -0
  107. stouputils/stouputils/all_doctests.pyi +46 -0
  108. stouputils/stouputils/applications/__init__.pyi +2 -0
  109. stouputils/stouputils/applications/automatic_docs.pyi +106 -0
  110. stouputils/stouputils/applications/upscaler/__init__.pyi +3 -0
  111. stouputils/stouputils/applications/upscaler/config.pyi +18 -0
  112. stouputils/stouputils/applications/upscaler/image.pyi +109 -0
  113. stouputils/stouputils/applications/upscaler/video.pyi +60 -0
  114. stouputils/stouputils/archive.pyi +67 -0
  115. stouputils/stouputils/backup.pyi +109 -0
  116. stouputils/stouputils/collections.pyi +86 -0
  117. stouputils/stouputils/continuous_delivery/__init__.pyi +5 -0
  118. stouputils/stouputils/continuous_delivery/cd_utils.pyi +129 -0
  119. stouputils/stouputils/continuous_delivery/github.pyi +162 -0
  120. stouputils/stouputils/continuous_delivery/pypi.pyi +53 -0
  121. stouputils/stouputils/continuous_delivery/pyproject.pyi +67 -0
  122. stouputils/stouputils/continuous_delivery/stubs.pyi +39 -0
  123. stouputils/stouputils/ctx.pyi +211 -0
  124. stouputils/stouputils/decorators.pyi +252 -0
  125. stouputils/stouputils/image.pyi +172 -0
  126. stouputils/stouputils/installer/__init__.pyi +5 -0
  127. stouputils/stouputils/installer/common.pyi +39 -0
  128. stouputils/stouputils/installer/downloader.pyi +24 -0
  129. stouputils/stouputils/installer/linux.pyi +39 -0
  130. stouputils/stouputils/installer/main.pyi +57 -0
  131. stouputils/stouputils/installer/windows.pyi +31 -0
  132. stouputils/stouputils/io.pyi +213 -0
  133. stouputils/stouputils/parallel.pyi +216 -0
  134. stouputils/stouputils/print.pyi +136 -0
  135. stouputils/stouputils/version_pkg.pyi +15 -0
  136. stouputils/version_pkg.py +189 -0
  137. stouputils-1.14.0.dist-info/METADATA +178 -0
  138. stouputils-1.14.0.dist-info/RECORD +140 -0
  139. stouputils-1.14.0.dist-info/WHEEL +4 -0
  140. stouputils-1.14.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,162 @@
1
+ from ..decorators import handle_error as handle_error, measure_time as measure_time
2
+ from ..io import clean_path as clean_path
3
+ from ..print import info as info, progress as progress, warning as warning
4
+ from .cd_utils import clean_version as clean_version, handle_response as handle_response, version_to_float as version_to_float
5
+ from typing import Any
6
+
7
+ GITHUB_API_URL: str
8
+ PROJECT_ENDPOINT: str
9
+ COMMIT_TYPES: dict[str, str]
10
+
11
+ def validate_credentials(credentials: dict[str, dict[str, str]]) -> tuple[str, dict[str, str]]:
12
+ """ Get and validate GitHub credentials
13
+
14
+ \tArgs:
15
+ \t\tcredentials (dict[str, dict[str, str]]):\tCredentials for the GitHub API
16
+ \tReturns:
17
+ \t\ttuple[str, dict[str, str]]:
18
+ \t\t\tstr:\t\t\tOwner (the username of the account to use)
19
+
20
+ \t\t\tdict[str, str]:\tHeaders (for the requests to the GitHub API)
21
+ \t"""
22
+ def validate_config(github_config: dict[str, Any]) -> tuple[str, str, str, list[str]]:
23
+ """ Validate GitHub configuration
24
+
25
+ \tArgs:
26
+ \t\tgithub_config (dict[str, str]):\tConfiguration for the GitHub project
27
+ \tReturns:
28
+ \t\ttuple[str, str, str, list[str]]:
29
+ \t\t\tstr: Project name on GitHub
30
+
31
+ \t\t\tstr: Version of the project
32
+
33
+ \t\t\tstr: Build folder path containing zip files to upload to the release
34
+
35
+ \t\t\tlist[str]: List of zip files to upload to the release
36
+ \t"""
37
+ def handle_existing_tag(owner: str, project_name: str, version: str, headers: dict[str, str]) -> bool:
38
+ """ Check if tag exists and handle deletion if needed
39
+
40
+ \tArgs:
41
+ \t\towner\t\t\t(str):\t\t\t\tGitHub username
42
+ \t\tproject_name\t(str):\t\t\t\tName of the GitHub repository
43
+ \t\tversion\t\t\t(str):\t\t\t\tVersion to check for existing tag
44
+ \t\theaders\t\t\t(dict[str, str]):\tHeaders for GitHub API requests
45
+ \tReturns:
46
+ \t\tbool: True if the tag was deleted or if it was not found, False otherwise
47
+ \t"""
48
+ def delete_existing_release(owner: str, project_name: str, version: str, headers: dict[str, str]) -> None:
49
+ """ Delete existing release for a version
50
+
51
+ \tArgs:
52
+ \t\towner\t\t\t(str):\t\t\t\tGitHub username
53
+ \t\tproject_name\t(str):\t\t\t\tName of the GitHub repository
54
+ \t\tversion\t\t\t(str):\t\t\t\tVersion of the release to delete
55
+ \t\theaders\t\t\t(dict[str, str]):\tHeaders for GitHub API requests
56
+ \t"""
57
+ def delete_existing_tag(tag_url: str, headers: dict[str, str]) -> None:
58
+ """ Delete existing tag
59
+
60
+ \tArgs:
61
+ \t\ttag_url\t(str):\t\t\t\tURL of the tag to delete
62
+ \t\theaders\t(dict[str, str]):\tHeaders for GitHub API requests
63
+ \t"""
64
+ def get_latest_tag(owner: str, project_name: str, version: str, headers: dict[str, str]) -> tuple[str, str] | tuple[None, None]:
65
+ """ Get latest tag information
66
+
67
+ \tArgs:
68
+ \t\towner\t\t\t(str):\t\t\t\tGitHub username
69
+ \t\tproject_name\t(str):\t\t\t\tName of the GitHub repository
70
+ \t\tversion\t\t\t(str):\t\t\t\tVersion to remove from the list of tags
71
+ \t\theaders\t\t\t(dict[str, str]):\tHeaders for GitHub API requests
72
+ \tReturns:
73
+ \t\tstr|None: SHA of the latest tag commit, None if no tags exist
74
+ \t\tstr|None: Version number of the latest tag, None if no tags exist
75
+ \t"""
76
+ def get_commits_since_tag(owner: str, project_name: str, latest_tag_sha: str | None, headers: dict[str, str]) -> list[dict[str, Any]]:
77
+ """ Get commits since last tag
78
+
79
+ \tArgs:
80
+ \t\towner\t\t\t(str):\t\t\t\tGitHub username
81
+ \t\tproject_name\t(str):\t\t\t\tName of the GitHub repository
82
+ \t\tlatest_tag_sha\t(str|None):\t\t\tSHA of the latest tag commit
83
+ \t\theaders\t\t\t(dict[str, str]):\tHeaders for GitHub API requests
84
+ \tReturns:
85
+ \t\tlist[dict]: List of commits since the last tag
86
+ \t"""
87
+ def generate_changelog(commits: list[dict[str, Any]], owner: str, project_name: str, latest_tag_version: str | None, version: str) -> str:
88
+ """ Generate changelog from commits. They must follow the conventional commits convention.
89
+
90
+ \tConvention format: <type>: <description> or <type>(<sub-category>): <description>
91
+
92
+ \tArgs:
93
+ \t\tcommits\t\t\t\t(list[dict]):\tList of commits to generate changelog from
94
+ \t\towner\t\t\t\t(str):\t\t\tGitHub username
95
+ \t\tproject_name\t\t(str):\t\t\tName of the GitHub repository
96
+ \t\tlatest_tag_version\t(str|None):\t\tVersion number of the latest tag
97
+ \t\tversion\t\t\t\t(str):\t\t\tCurrent version being released
98
+ \tReturns:
99
+ \t\tstr: Generated changelog text
100
+ \tSource:
101
+ \t\thttps://www.conventionalcommits.org/en/v1.0.0/
102
+ \t"""
103
+ def create_tag(owner: str, project_name: str, version: str, headers: dict[str, str]) -> None:
104
+ """ Create a new tag
105
+
106
+ \tArgs:
107
+ \t\towner\t\t\t(str):\t\t\t\tGitHub username
108
+ \t\tproject_name\t(str):\t\t\t\tName of the GitHub repository
109
+ \t\tversion\t\t\t(str):\t\t\t\tVersion for the new tag
110
+ \t\theaders\t\t\t(dict[str, str]):\tHeaders for GitHub API requests
111
+ \t"""
112
+ def create_release(owner: str, project_name: str, version: str, changelog: str, headers: dict[str, str]) -> int:
113
+ """ Create a new release
114
+
115
+ \tArgs:
116
+ \t\towner\t\t\t(str):\t\t\t\tGitHub username
117
+ \t\tproject_name\t(str):\t\t\t\tName of the GitHub repository
118
+ \t\tversion\t\t\t(str):\t\t\t\tVersion for the new release
119
+ \t\tchangelog\t\t(str):\t\t\t\tChangelog text for the release
120
+ \t\theaders\t\t\t(dict[str, str]):\tHeaders for GitHub API requests
121
+ \tReturns:
122
+ \t\tint: ID of the created release
123
+ \t"""
124
+ def upload_assets(owner: str, project_name: str, release_id: int, build_folder: str, headers: dict[str, str], endswith: list[str]) -> None:
125
+ """ Upload release assets
126
+
127
+ \tArgs:
128
+ \t\towner\t\t\t(str):\t\t\t\tGitHub username
129
+ \t\tproject_name\t(str):\t\t\t\tName of the GitHub repository
130
+ \t\trelease_id\t\t(int):\t\t\t\tID of the release to upload assets to
131
+ \t\tbuild_folder\t(str):\t\t\t\tFolder containing assets to upload
132
+ \t\theaders\t\t\t(dict[str, str]):\tHeaders for GitHub API requests
133
+ \t\tendswith\t\t(list[str]):\t\tList of files to upload to the release
134
+ \t\t\t(every file ending with one of these strings will be uploaded)
135
+ \t"""
136
+ def upload_to_github(credentials: dict[str, Any], github_config: dict[str, Any]) -> str:
137
+ ''' Upload the project to GitHub using the credentials and the configuration
138
+
139
+ \tArgs:
140
+ \t\tcredentials\t\t(dict[str, Any]):\tCredentials for the GitHub API
141
+ \t\tgithub_config\t(dict[str, Any]):\tConfiguration for the GitHub project
142
+ \tReturns:
143
+ \t\tstr: Generated changelog text
144
+ \tExamples:
145
+
146
+ \t.. code-block:: python
147
+
148
+ \t\t> upload_to_github(
149
+ \t\t\tcredentials={
150
+ \t\t\t\t"github": {
151
+ \t\t\t\t\t"api_key": "ghp_...",
152
+ \t\t\t\t\t"username": "Stoupy"
153
+ \t\t\t\t}
154
+ \t\t\t},
155
+ \t\t\tgithub_config={
156
+ \t\t\t\t"project_name": "stouputils",
157
+ \t\t\t\t"version": "1.0.0",
158
+ \t\t\t\t"build_folder": "build",
159
+ \t\t\t\t"endswith": [".zip"]
160
+ \t\t\t}
161
+ \t\t)
162
+ \t'''
@@ -0,0 +1,53 @@
1
+ from ..decorators import LogLevels as LogLevels, handle_error as handle_error
2
+ from .pyproject import read_pyproject as read_pyproject
3
+ from collections.abc import Callable as Callable
4
+
5
+ def update_pip_and_required_packages() -> int:
6
+ """ Update pip and required packages.
7
+
8
+ \tReturns:
9
+ \t\tint: Return code of the os.system call.
10
+ \t"""
11
+ def build_package() -> int:
12
+ """ Build the package.
13
+
14
+ \tReturns:
15
+ \t\tint: Return code of the os.system call.
16
+ \t"""
17
+ def upload_package(repository: str, filepath: str) -> int:
18
+ """ Upload the package to PyPI.
19
+
20
+ \tArgs:
21
+ \t\trepository (str): Repository to upload to.
22
+ \t\tfilepath (str): Path to the file to upload.
23
+
24
+ \tReturns:
25
+ \t\tint: Return code of the os.system call.
26
+ \t"""
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
+ ''' Upload the most recent file(s) to PyPI after updating pip and required packages and building the package.
29
+
30
+ \tArgs:
31
+ \t\trepository (str): Repository to upload to.
32
+ \t\tdist_directory (str): Directory to upload from.
33
+ \t\tlast_files (int): Number of most recent files to upload. Defaults to 1.
34
+ \t\tendswith (str): End of the file name to upload. Defaults to ".tar.gz".
35
+ \t\tupdate_all_function (Callable[[], int]): Function to update pip and required packages.
36
+ \t\t\tDefaults to :func:`update_pip_and_required_packages`.
37
+ \t\tbuild_package_function (Callable[[], int]): Function to build the package.
38
+ \t\t\tDefaults to :func:`build_package`.
39
+ \t\tupload_package_function (Callable[[str, str], int]): Function to upload the package.
40
+ \t\t\tDefaults to :func:`upload_package`.
41
+
42
+ \tReturns:
43
+ \t\tint: Return code of the command.
44
+ \t'''
45
+ def pypi_full_routine_using_uv() -> None:
46
+ """ Full build and publish routine using 'uv' command line tool.
47
+
48
+ \tSteps:
49
+ \t\t1. Generate stubs unless '--no-stubs' is passed
50
+ \t\t2. Increment version in pyproject.toml (patch by default, minor if 'minor' is passed as last argument, 'major' if 'major' is passed)
51
+ \t\t3. Build the package using 'uv build'
52
+ \t\t4. Upload the most recent file to PyPI using 'uv publish'
53
+ \t"""
@@ -0,0 +1,67 @@
1
+ from ..io import super_open as super_open
2
+ from typing import Any
3
+
4
+ def read_pyproject(pyproject_path: str) -> dict[str, Any]:
5
+ ''' Read the pyproject.toml file.
6
+
7
+ \tArgs:
8
+ \t\tpyproject_path: Path to the pyproject.toml file.
9
+ \tReturns:
10
+ \t\tdict[str, Any]: The content of the pyproject.toml file.
11
+ \tExample:
12
+ \t\t>>> content = read_pyproject("pyproject.toml")
13
+ \t\t>>> "." in content["project"]["version"]
14
+ \t\tTrue
15
+ \t'''
16
+ def format_toml_lists(content: str) -> str:
17
+ ''' Format TOML lists with indentation.
18
+
19
+ \tArgs:
20
+ \t\tcontent (str): The content of the pyproject.toml file.
21
+ \tReturns:
22
+ \t\tstr: The formatted content with properly indented lists.
23
+ \tExample:
24
+ \t\t>>> toml_content = \'\'\'[project]
25
+ \t\t... dependencies = [ "tqdm>=4.0.0", "requests>=2.20.0", "pyyaml>=6.0.0", ]\'\'\'
26
+ \t\t>>> format_toml_lists(toml_content).replace("\\t", " ") == \'\'\'[project]
27
+ \t\t... dependencies = [
28
+ \t\t... "tqdm>=4.0.0",
29
+ \t\t... "requests>=2.20.0",
30
+ \t\t... "pyyaml>=6.0.0",
31
+ \t\t... ]\'\'\'
32
+ \t\tTrue
33
+ \t'''
34
+ def write_pyproject(path: str, content: dict[str, Any]) -> None:
35
+ """ Write to the pyproject.toml file with properly indented lists.
36
+
37
+ \tArgs:
38
+ \t\tpath: Path to the pyproject.toml file.
39
+ \t\tcontent: Content to write to the pyproject.toml file.
40
+ \t"""
41
+ def increment_version_from_input(version: str) -> str:
42
+ ''' Increment the version.
43
+
44
+ \tArgs:
45
+ \t\tversion: The version to increment. (ex: "0.1.0")
46
+ \tReturns:
47
+ \t\tstr: The incremented version. (ex: "0.1.1")
48
+ \tExample:
49
+ \t\t>>> increment_version_from_input("0.1.0")
50
+ \t\t\'0.1.1\'
51
+ \t\t>>> increment_version_from_input("1.2.9")
52
+ \t\t\'1.2.10\'
53
+ \t'''
54
+ def increment_version_from_pyproject(path: str) -> None:
55
+ """ Increment the version in the pyproject.toml file.
56
+
57
+ \tArgs:
58
+ \t\tpath: Path to the pyproject.toml file.
59
+ \t"""
60
+ def get_version_from_pyproject(path: str) -> str:
61
+ ''' Get the version from the pyproject.toml file.
62
+
63
+ \tArgs:
64
+ \t\tpath: Path to the pyproject.toml file.
65
+ \tReturns:
66
+ \t\tstr: The version. (ex: "0.1.0")
67
+ \t'''
@@ -0,0 +1,39 @@
1
+ from ..decorators import LogLevels as LogLevels, handle_error as handle_error
2
+ from collections.abc import Callable as Callable
3
+
4
+ def generate_stubs(package_name: str, extra_args: str = '--include-docstrings --include-private') -> int:
5
+ ''' Generate stub files for a Python package using stubgen.
6
+
7
+ \tNote: stubgen generates stubs in the \'out\' directory by default in the current working directory.
8
+
9
+ \tArgs:
10
+ \t\tpackage_name (str): Name of the package to generate stubs for.
11
+ \t\textra_args (str): Extra arguments to pass to stubgen. Defaults to "--include-docstrings --include-private".
12
+ \tReturns:
13
+ \t\tint: Return code of the os.system call.
14
+ \t'''
15
+ def clean_stubs_directory(output_directory: str, package_name: str) -> None:
16
+ """ Clean the stubs directory by deleting all .pyi files.
17
+
18
+ \tArgs:
19
+ \t\toutput_directory (str): Directory to clean.
20
+ \t\tpackage_name (str): Package name subdirectory. Only cleans output_directory/package_name.
21
+ \t"""
22
+ def stubs_full_routine(package_name: str, output_directory: str = 'typings', extra_args: str = '--include-docstrings --include-private', clean_before: bool = False, generate_stubs_function: Callable[[str, str], int] = ..., clean_stubs_function: Callable[[str, str], None] = ...) -> None:
23
+ ''' Generate stub files for a Python package using stubgen.
24
+
25
+ \tNote: stubgen generates stubs in the \'out\' directory by default in the current working directory.
26
+
27
+ \tArgs:
28
+ \t\tpackage_name (str): Name of the package to generate stubs for.
29
+ \t\toutput_directory (str): Directory to clean before generating stubs. Defaults to "typings".
30
+ \t\t\tThis parameter is used for cleaning the directory before stub generation.
31
+ \t\textra_args (str): Extra arguments to pass to stubgen. Defaults to "--include-docstrings --include-private".
32
+ \t\tclean_before (bool): Whether to clean the output directory before generating stubs. Defaults to False.
33
+ \t\tgenerate_stubs_function (Callable[[str, str], int]): Function to generate stubs.
34
+ \t\t\tDefaults to :func:`generate_stubs`.
35
+ \t\tclean_stubs_function (Callable[[str], None]): Function to clean the stubs directory.
36
+ \t\t\tDefaults to :func:`clean_stubs_directory`.
37
+ \tRaises:
38
+ \t\tException: If stub generation fails.
39
+ \t'''
@@ -0,0 +1,211 @@
1
+ import abc
2
+ from .io import super_open as super_open
3
+ from .print import TeeMultiOutput as TeeMultiOutput, debug as debug
4
+ from collections.abc import Callable as Callable
5
+ from contextlib import AbstractAsyncContextManager, AbstractContextManager
6
+ from typing import Any, IO, TextIO, TypeVar
7
+
8
+ T = TypeVar('T')
9
+
10
+ class AbstractBothContextManager[T](AbstractContextManager[T], AbstractAsyncContextManager[T], metaclass=abc.ABCMeta):
11
+ """ Abstract base class for context managers that support both synchronous and asynchronous usage. """
12
+
13
+ class LogToFile(AbstractBothContextManager['LogToFile']):
14
+ ''' Context manager to log to a file.
15
+
16
+ \tThis context manager allows you to temporarily log output to a file while still printing normally.
17
+ \tThe file will receive log messages without ANSI color codes.
18
+
19
+ \tArgs:
20
+ \t\tpath (str): Path to the log file
21
+ \t\tmode (str): Mode to open the file in (default: "w")
22
+ \t\tencoding (str): Encoding to use for the file (default: "utf-8")
23
+ \t\ttee_stdout (bool): Whether to redirect stdout to the file (default: True)
24
+ \t\ttee_stderr (bool): Whether to redirect stderr to the file (default: True)
25
+ \t\tignore_lineup (bool): Whether to ignore lines containing LINE_UP escape sequence in files (default: False)
26
+ \t\trestore_on_exit (bool): Whether to restore original stdout/stderr on exit (default: False)
27
+ \t\t\tThis ctx uses TeeMultiOutput which handles closed files gracefully, so restoring is not mandatory.
28
+
29
+ \tExamples:
30
+ \t\t.. code-block:: python
31
+
32
+ \t\t\t> import stouputils as stp
33
+ \t\t\t> with stp.LogToFile("output.log"):
34
+ \t\t\t> stp.info("This will be logged to output.log and printed normally")
35
+ \t\t\t> print("This will also be logged")
36
+
37
+ \t\t\t> with stp.LogToFile("output.log") as log_ctx:
38
+ \t\t\t> stp.warning("This will be logged to output.log and printed normally")
39
+ \t\t\t> log_ctx.change_file("new_file.log")
40
+ \t\t\t> print("This will be logged to new_file.log")
41
+ \t'''
42
+ path: str
43
+ mode: str
44
+ encoding: str
45
+ tee_stdout: bool
46
+ tee_stderr: bool
47
+ ignore_lineup: bool
48
+ restore_on_exit: bool
49
+ file: IO[Any]
50
+ original_stdout: TextIO
51
+ original_stderr: TextIO
52
+ def __init__(self, path: str, mode: str = 'w', encoding: str = 'utf-8', tee_stdout: bool = True, tee_stderr: bool = True, ignore_lineup: bool = True, restore_on_exit: bool = False) -> None: ...
53
+ def __enter__(self) -> LogToFile:
54
+ """ Enter context manager which opens the log file and redirects stdout/stderr """
55
+ def __exit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any | None) -> None:
56
+ """ Exit context manager which closes the log file and restores stdout/stderr """
57
+ async def __aenter__(self) -> LogToFile:
58
+ """ Enter async context manager which opens the log file and redirects stdout/stderr """
59
+ async def __aexit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any | None) -> None:
60
+ """ Exit async context manager which closes the log file and restores stdout/stderr """
61
+ def change_file(self, new_path: str) -> None:
62
+ """ Change the log file to a new path.
63
+
64
+ \t\tArgs:
65
+ \t\t\tnew_path (str): New path to the log file
66
+ \t\t"""
67
+ @staticmethod
68
+ def common(logs_folder: str, filepath: str, func: Callable[..., Any], *args: Any, **kwargs: Any) -> Any:
69
+ ''' Common code used at the beginning of a program to launch main function
70
+
71
+ \t\tArgs:
72
+ \t\t\tlogs_folder (str): Folder to store logs in
73
+ \t\t\tfilepath (str): Path to the main function
74
+ \t\t\tfunc (Callable[..., Any]): Main function to launch
75
+ \t\t\t*args (tuple[Any, ...]): Arguments to pass to the main function
76
+ \t\t\t**kwargs (dict[str, Any]): Keyword arguments to pass to the main function
77
+ \t\tReturns:
78
+ \t\t\tAny: Return value of the main function
79
+
80
+ \t\tExamples:
81
+ \t\t\t>>> if __name__ == "__main__":
82
+ \t\t\t... LogToFile.common(f"{ROOT}/logs", __file__, main)
83
+ \t\t'''
84
+
85
+ class MeasureTime(AbstractBothContextManager['MeasureTime']):
86
+ ''' Context manager to measure execution time.
87
+
88
+ \tThis context manager measures the execution time of the code block it wraps
89
+ \tand prints the result using a specified print function.
90
+
91
+ \tArgs:
92
+ \t\tprint_func (Callable): Function to use to print the execution time (e.g. debug, info, warning, error, etc.).
93
+ \t\tmessage (str): Message to display with the execution time. Defaults to "Execution time".
94
+ \t\tperf_counter (bool): Whether to use time.perf_counter_ns or time.time_ns. Defaults to True.
95
+
96
+ \tExamples:
97
+ \t\t.. code-block:: python
98
+
99
+ \t\t\t> import time
100
+ \t\t\t> import stouputils as stp
101
+ \t\t\t> with stp.MeasureTime(stp.info, message="My operation"):
102
+ \t\t\t... time.sleep(0.5)
103
+ \t\t\t> # [INFO HH:MM:SS] My operation: 500.123ms (500123456ns)
104
+
105
+ \t\t\t> with stp.MeasureTime(): # Uses debug by default
106
+ \t\t\t... time.sleep(0.1)
107
+ \t\t\t> # [DEBUG HH:MM:SS] Execution time: 100.456ms (100456789ns)
108
+ \t'''
109
+ print_func: Callable[..., None]
110
+ message: str
111
+ perf_counter: bool
112
+ ns: Callable[[], int]
113
+ start_ns: int
114
+ def __init__(self, print_func: Callable[..., None] = ..., message: str = 'Execution time', perf_counter: bool = True) -> None: ...
115
+ def __enter__(self) -> MeasureTime:
116
+ """ Enter context manager, record start time """
117
+ def __exit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any | None) -> None:
118
+ """ Exit context manager, calculate duration and print """
119
+ async def __aenter__(self) -> MeasureTime:
120
+ """ Enter async context manager, record start time """
121
+ async def __aexit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any | None) -> None:
122
+ """ Exit async context manager, calculate duration and print """
123
+
124
+ class Muffle(AbstractBothContextManager['Muffle']):
125
+ ''' Context manager that temporarily silences output.
126
+ \t(No thread-safety guaranteed)
127
+
128
+ \tAlternative to stouputils.decorators.silent()
129
+
130
+ \tExamples:
131
+ \t\t>>> with Muffle():
132
+ \t\t... print("This will not be printed")
133
+ \t'''
134
+ mute_stderr: bool
135
+ original_stdout: IO[Any]
136
+ original_stderr: IO[Any]
137
+ def __init__(self, mute_stderr: bool = False) -> None: ...
138
+ def __enter__(self) -> Muffle:
139
+ """ Enter context manager which redirects stdout and stderr to devnull """
140
+ def __exit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any | None) -> None:
141
+ """ Exit context manager which restores original stdout and stderr """
142
+ async def __aenter__(self) -> Muffle:
143
+ """ Enter async context manager which redirects stdout and stderr to devnull """
144
+ async def __aexit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any | None) -> None:
145
+ """ Exit async context manager which restores original stdout and stderr """
146
+
147
+ class DoNothing(AbstractBothContextManager['DoNothing']):
148
+ ''' Context manager that does nothing.
149
+
150
+ \tThis is a no-op context manager that can be used as a placeholder
151
+ \tor for conditional context management.
152
+
153
+ \tDifferent from contextlib.nullcontext because it handles args and kwargs,
154
+ \talong with **async** context management.
155
+
156
+ \tExamples:
157
+ \t\t>>> with DoNothing():
158
+ \t\t... print("This will be printed normally")
159
+ \t\tThis will be printed normally
160
+
161
+ \t\t>>> # Conditional context management
162
+ \t\t>>> some_condition = True
163
+ \t\t>>> ctx = DoNothing() if some_condition else Muffle()
164
+ \t\t>>> with ctx:
165
+ \t\t... print("May or may not be printed depending on condition")
166
+ \t\tMay or may not be printed depending on condition
167
+ \t'''
168
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
169
+ """ No initialization needed, this is a no-op context manager """
170
+ def __enter__(self) -> DoNothing:
171
+ """ Enter context manager (does nothing) """
172
+ def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
173
+ """ Exit context manager (does nothing) """
174
+ async def __aenter__(self) -> DoNothing:
175
+ """ Enter async context manager (does nothing) """
176
+ async def __aexit__(self, *excinfo: Any) -> None:
177
+ """ Exit async context manager (does nothing) """
178
+ NullContextManager = DoNothing
179
+
180
+ class SetMPStartMethod(AbstractBothContextManager['SetMPStartMethod']):
181
+ ''' Context manager to temporarily set multiprocessing start method.
182
+
183
+ \tThis context manager allows you to temporarily change the multiprocessing start method
184
+ \tand automatically restores the original method when exiting the context.
185
+
186
+ \tArgs:
187
+ \t\tstart_method (str): The start method to use: "spawn", "fork", or "forkserver"
188
+
189
+ \tExamples:
190
+ \t\t.. code-block:: python
191
+
192
+ \t\t\t> import multiprocessing as mp
193
+ \t\t\t> import stouputils as stp
194
+ \t\t\t> # Temporarily use spawn method
195
+ \t\t\t> with stp.SetMPStartMethod("spawn"):
196
+ \t\t\t> ... # Your multiprocessing code here
197
+ \t\t\t> ... pass
198
+
199
+ \t\t\t> # Original method is automatically restored
200
+ \t'''
201
+ start_method: str | None
202
+ old_method: str | None
203
+ def __init__(self, start_method: str | None) -> None: ...
204
+ def __enter__(self) -> SetMPStartMethod:
205
+ """ Enter context manager which sets the start method """
206
+ def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
207
+ """ Exit context manager which restores the original start method """
208
+ async def __aenter__(self) -> SetMPStartMethod:
209
+ """ Enter async context manager which sets the start method """
210
+ async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
211
+ """ Exit async context manager which restores the original start method """