stouputils 1.12.1__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 (138) hide show
  1. stouputils/__init__.py +40 -0
  2. stouputils/__init__.pyi +14 -0
  3. stouputils/__main__.py +81 -0
  4. stouputils/_deprecated.py +37 -0
  5. stouputils/_deprecated.pyi +12 -0
  6. stouputils/all_doctests.py +160 -0
  7. stouputils/all_doctests.pyi +46 -0
  8. stouputils/applications/__init__.py +22 -0
  9. stouputils/applications/__init__.pyi +2 -0
  10. stouputils/applications/automatic_docs.py +634 -0
  11. stouputils/applications/automatic_docs.pyi +106 -0
  12. stouputils/applications/upscaler/__init__.py +39 -0
  13. stouputils/applications/upscaler/__init__.pyi +3 -0
  14. stouputils/applications/upscaler/config.py +128 -0
  15. stouputils/applications/upscaler/config.pyi +18 -0
  16. stouputils/applications/upscaler/image.py +247 -0
  17. stouputils/applications/upscaler/image.pyi +109 -0
  18. stouputils/applications/upscaler/video.py +287 -0
  19. stouputils/applications/upscaler/video.pyi +60 -0
  20. stouputils/archive.py +344 -0
  21. stouputils/archive.pyi +67 -0
  22. stouputils/backup.py +488 -0
  23. stouputils/backup.pyi +109 -0
  24. stouputils/collections.py +244 -0
  25. stouputils/collections.pyi +86 -0
  26. stouputils/continuous_delivery/__init__.py +27 -0
  27. stouputils/continuous_delivery/__init__.pyi +5 -0
  28. stouputils/continuous_delivery/cd_utils.py +243 -0
  29. stouputils/continuous_delivery/cd_utils.pyi +129 -0
  30. stouputils/continuous_delivery/github.py +522 -0
  31. stouputils/continuous_delivery/github.pyi +162 -0
  32. stouputils/continuous_delivery/pypi.py +91 -0
  33. stouputils/continuous_delivery/pypi.pyi +43 -0
  34. stouputils/continuous_delivery/pyproject.py +147 -0
  35. stouputils/continuous_delivery/pyproject.pyi +67 -0
  36. stouputils/continuous_delivery/stubs.py +86 -0
  37. stouputils/continuous_delivery/stubs.pyi +39 -0
  38. stouputils/ctx.py +408 -0
  39. stouputils/ctx.pyi +211 -0
  40. stouputils/data_science/config/get.py +51 -0
  41. stouputils/data_science/config/set.py +125 -0
  42. stouputils/data_science/data_processing/image/__init__.py +66 -0
  43. stouputils/data_science/data_processing/image/auto_contrast.py +79 -0
  44. stouputils/data_science/data_processing/image/axis_flip.py +58 -0
  45. stouputils/data_science/data_processing/image/bias_field_correction.py +74 -0
  46. stouputils/data_science/data_processing/image/binary_threshold.py +73 -0
  47. stouputils/data_science/data_processing/image/blur.py +59 -0
  48. stouputils/data_science/data_processing/image/brightness.py +54 -0
  49. stouputils/data_science/data_processing/image/canny.py +110 -0
  50. stouputils/data_science/data_processing/image/clahe.py +92 -0
  51. stouputils/data_science/data_processing/image/common.py +30 -0
  52. stouputils/data_science/data_processing/image/contrast.py +53 -0
  53. stouputils/data_science/data_processing/image/curvature_flow_filter.py +74 -0
  54. stouputils/data_science/data_processing/image/denoise.py +378 -0
  55. stouputils/data_science/data_processing/image/histogram_equalization.py +123 -0
  56. stouputils/data_science/data_processing/image/invert.py +64 -0
  57. stouputils/data_science/data_processing/image/laplacian.py +60 -0
  58. stouputils/data_science/data_processing/image/median_blur.py +52 -0
  59. stouputils/data_science/data_processing/image/noise.py +59 -0
  60. stouputils/data_science/data_processing/image/normalize.py +65 -0
  61. stouputils/data_science/data_processing/image/random_erase.py +66 -0
  62. stouputils/data_science/data_processing/image/resize.py +69 -0
  63. stouputils/data_science/data_processing/image/rotation.py +80 -0
  64. stouputils/data_science/data_processing/image/salt_pepper.py +68 -0
  65. stouputils/data_science/data_processing/image/sharpening.py +55 -0
  66. stouputils/data_science/data_processing/image/shearing.py +64 -0
  67. stouputils/data_science/data_processing/image/threshold.py +64 -0
  68. stouputils/data_science/data_processing/image/translation.py +71 -0
  69. stouputils/data_science/data_processing/image/zoom.py +83 -0
  70. stouputils/data_science/data_processing/image_augmentation.py +118 -0
  71. stouputils/data_science/data_processing/image_preprocess.py +183 -0
  72. stouputils/data_science/data_processing/prosthesis_detection.py +359 -0
  73. stouputils/data_science/data_processing/technique.py +481 -0
  74. stouputils/data_science/dataset/__init__.py +45 -0
  75. stouputils/data_science/dataset/dataset.py +292 -0
  76. stouputils/data_science/dataset/dataset_loader.py +135 -0
  77. stouputils/data_science/dataset/grouping_strategy.py +296 -0
  78. stouputils/data_science/dataset/image_loader.py +100 -0
  79. stouputils/data_science/dataset/xy_tuple.py +696 -0
  80. stouputils/data_science/metric_dictionnary.py +106 -0
  81. stouputils/data_science/metric_utils.py +847 -0
  82. stouputils/data_science/mlflow_utils.py +206 -0
  83. stouputils/data_science/models/abstract_model.py +149 -0
  84. stouputils/data_science/models/all.py +85 -0
  85. stouputils/data_science/models/base_keras.py +765 -0
  86. stouputils/data_science/models/keras/all.py +38 -0
  87. stouputils/data_science/models/keras/convnext.py +62 -0
  88. stouputils/data_science/models/keras/densenet.py +50 -0
  89. stouputils/data_science/models/keras/efficientnet.py +60 -0
  90. stouputils/data_science/models/keras/mobilenet.py +56 -0
  91. stouputils/data_science/models/keras/resnet.py +52 -0
  92. stouputils/data_science/models/keras/squeezenet.py +233 -0
  93. stouputils/data_science/models/keras/vgg.py +42 -0
  94. stouputils/data_science/models/keras/xception.py +38 -0
  95. stouputils/data_science/models/keras_utils/callbacks/__init__.py +20 -0
  96. stouputils/data_science/models/keras_utils/callbacks/colored_progress_bar.py +219 -0
  97. stouputils/data_science/models/keras_utils/callbacks/learning_rate_finder.py +148 -0
  98. stouputils/data_science/models/keras_utils/callbacks/model_checkpoint_v2.py +31 -0
  99. stouputils/data_science/models/keras_utils/callbacks/progressive_unfreezing.py +249 -0
  100. stouputils/data_science/models/keras_utils/callbacks/warmup_scheduler.py +66 -0
  101. stouputils/data_science/models/keras_utils/losses/__init__.py +12 -0
  102. stouputils/data_science/models/keras_utils/losses/next_generation_loss.py +56 -0
  103. stouputils/data_science/models/keras_utils/visualizations.py +416 -0
  104. stouputils/data_science/models/model_interface.py +939 -0
  105. stouputils/data_science/models/sandbox.py +116 -0
  106. stouputils/data_science/range_tuple.py +234 -0
  107. stouputils/data_science/scripts/augment_dataset.py +77 -0
  108. stouputils/data_science/scripts/exhaustive_process.py +133 -0
  109. stouputils/data_science/scripts/preprocess_dataset.py +70 -0
  110. stouputils/data_science/scripts/routine.py +168 -0
  111. stouputils/data_science/utils.py +285 -0
  112. stouputils/decorators.py +595 -0
  113. stouputils/decorators.pyi +242 -0
  114. stouputils/image.py +441 -0
  115. stouputils/image.pyi +172 -0
  116. stouputils/installer/__init__.py +18 -0
  117. stouputils/installer/__init__.pyi +5 -0
  118. stouputils/installer/common.py +67 -0
  119. stouputils/installer/common.pyi +39 -0
  120. stouputils/installer/downloader.py +101 -0
  121. stouputils/installer/downloader.pyi +24 -0
  122. stouputils/installer/linux.py +144 -0
  123. stouputils/installer/linux.pyi +39 -0
  124. stouputils/installer/main.py +223 -0
  125. stouputils/installer/main.pyi +57 -0
  126. stouputils/installer/windows.py +136 -0
  127. stouputils/installer/windows.pyi +31 -0
  128. stouputils/io.py +486 -0
  129. stouputils/io.pyi +213 -0
  130. stouputils/parallel.py +453 -0
  131. stouputils/parallel.pyi +211 -0
  132. stouputils/print.py +527 -0
  133. stouputils/print.pyi +146 -0
  134. stouputils/py.typed +1 -0
  135. stouputils-1.12.1.dist-info/METADATA +179 -0
  136. stouputils-1.12.1.dist-info/RECORD +138 -0
  137. stouputils-1.12.1.dist-info/WHEEL +4 -0
  138. stouputils-1.12.1.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,91 @@
1
+ """ This module contains utilities for PyPI.
2
+ (Using build and twine packages)
3
+
4
+ - pypi_full_routine: Upload the most recent file(s) to PyPI after updating pip and required packages and building the package
5
+
6
+ .. image:: https://raw.githubusercontent.com/Stoupy51/stouputils/refs/heads/main/assets/continuous_delivery/pypi_module.gif
7
+ :alt: stouputils pypi examples
8
+ """
9
+
10
+ # Imports
11
+ import os
12
+ import sys
13
+ from collections.abc import Callable
14
+
15
+ from ..decorators import LogLevels, handle_error
16
+
17
+
18
+ def update_pip_and_required_packages() -> int:
19
+ """ Update pip and required packages.
20
+
21
+ Returns:
22
+ int: Return code of the os.system call.
23
+ """
24
+ return os.system(f"{sys.executable} -m pip install --upgrade pip setuptools build twine pkginfo packaging")
25
+
26
+ def build_package() -> int:
27
+ """ Build the package.
28
+
29
+ Returns:
30
+ int: Return code of the os.system call.
31
+ """
32
+ return os.system(f"{sys.executable} -m build")
33
+
34
+ def upload_package(repository: str, filepath: str) -> int:
35
+ """ Upload the package to PyPI.
36
+
37
+ Args:
38
+ repository (str): Repository to upload to.
39
+ filepath (str): Path to the file to upload.
40
+
41
+ Returns:
42
+ int: Return code of the os.system call.
43
+ """
44
+ return os.system(f"{sys.executable} -m twine upload --verbose -r {repository} {filepath}")
45
+
46
+ @handle_error(message="Error while doing the pypi full routine", error_log=LogLevels.ERROR_TRACEBACK)
47
+ def pypi_full_routine(
48
+ repository: str,
49
+ dist_directory: str,
50
+ last_files: int = 1,
51
+ endswith: str = ".tar.gz",
52
+
53
+ update_all_function: Callable[[], int] = update_pip_and_required_packages,
54
+ build_package_function: Callable[[], int] = build_package,
55
+ upload_package_function: Callable[[str, str], int] = upload_package,
56
+ ) -> None:
57
+ """ Upload the most recent file(s) to PyPI after updating pip and required packages and building the package.
58
+
59
+ Args:
60
+ repository (str): Repository to upload to.
61
+ dist_directory (str): Directory to upload from.
62
+ last_files (int): Number of most recent files to upload. Defaults to 1.
63
+ endswith (str): End of the file name to upload. Defaults to ".tar.gz".
64
+ update_all_function (Callable[[], int]): Function to update pip and required packages.
65
+ Defaults to :func:`update_pip_and_required_packages`.
66
+ build_package_function (Callable[[], int]): Function to build the package.
67
+ Defaults to :func:`build_package`.
68
+ upload_package_function (Callable[[str, str], int]): Function to upload the package.
69
+ Defaults to :func:`upload_package`.
70
+
71
+ Returns:
72
+ int: Return code of the command.
73
+ """
74
+ if update_all_function() != 0:
75
+ raise Exception("Error while updating pip and required packages")
76
+
77
+ if build_package_function() != 0:
78
+ raise Exception("Error while building the package")
79
+
80
+ # Get list of tar.gz files in dist directory sorted by modification time
81
+ files: list[str] = sorted(
82
+ [x for x in os.listdir(dist_directory) if x.endswith(endswith)], # Get list of tar.gz files in dist directory
83
+ key=lambda x: os.path.getmtime(f"{dist_directory}/{x}"), # Sort by modification time
84
+ reverse=True # Sort in reverse order
85
+ )
86
+
87
+ # Upload the most recent file(s)
88
+ for file in files[:last_files]:
89
+ upload_package_function(repository, f"{dist_directory}/{file}")
90
+
91
+
@@ -0,0 +1,43 @@
1
+ from ..decorators import LogLevels as LogLevels, handle_error as handle_error
2
+ from collections.abc import Callable as Callable
3
+
4
+ def update_pip_and_required_packages() -> int:
5
+ """ Update pip and required packages.
6
+
7
+ \tReturns:
8
+ \t\tint: Return code of the os.system call.
9
+ \t"""
10
+ def build_package() -> int:
11
+ """ Build the package.
12
+
13
+ \tReturns:
14
+ \t\tint: Return code of the os.system call.
15
+ \t"""
16
+ def upload_package(repository: str, filepath: str) -> int:
17
+ """ Upload the package to PyPI.
18
+
19
+ \tArgs:
20
+ \t\trepository (str): Repository to upload to.
21
+ \t\tfilepath (str): Path to the file to upload.
22
+
23
+ \tReturns:
24
+ \t\tint: Return code of the os.system call.
25
+ \t"""
26
+ 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:
27
+ ''' Upload the most recent file(s) to PyPI after updating pip and required packages and building the package.
28
+
29
+ \tArgs:
30
+ \t\trepository (str): Repository to upload to.
31
+ \t\tdist_directory (str): Directory to upload from.
32
+ \t\tlast_files (int): Number of most recent files to upload. Defaults to 1.
33
+ \t\tendswith (str): End of the file name to upload. Defaults to ".tar.gz".
34
+ \t\tupdate_all_function (Callable[[], int]): Function to update pip and required packages.
35
+ \t\t\tDefaults to :func:`update_pip_and_required_packages`.
36
+ \t\tbuild_package_function (Callable[[], int]): Function to build the package.
37
+ \t\t\tDefaults to :func:`build_package`.
38
+ \t\tupload_package_function (Callable[[str, str], int]): Function to upload the package.
39
+ \t\t\tDefaults to :func:`upload_package`.
40
+
41
+ \tReturns:
42
+ \t\tint: Return code of the command.
43
+ \t'''
@@ -0,0 +1,147 @@
1
+ """ Utilities for reading, writing and managing pyproject.toml files.
2
+
3
+ This module provides functions to handle pyproject.toml files, including reading,
4
+ writing, version management and TOML formatting capabilities.
5
+
6
+ - read_pyproject: Read the pyproject.toml file.
7
+ - write_pyproject: Write to the pyproject.toml file.
8
+ - format_toml_lists: Format TOML lists with proper indentation.
9
+ - increment_version_from_input: Increment the patch version number.
10
+ - increment_version_from_pyproject: Increment version in pyproject.toml.
11
+ - get_version_from_pyproject: Get version from pyproject.toml.
12
+
13
+ .. image:: https://raw.githubusercontent.com/Stoupy51/stouputils/refs/heads/main/assets/continuous_delivery/pyproject_module.gif
14
+ :alt: stouputils pyproject examples
15
+ """
16
+
17
+ # Imports
18
+ from typing import Any
19
+
20
+ from ..io import super_open
21
+
22
+
23
+ def read_pyproject(pyproject_path: str) -> dict[str, Any]:
24
+ """ Read the pyproject.toml file.
25
+
26
+ Args:
27
+ pyproject_path: Path to the pyproject.toml file.
28
+ Returns:
29
+ dict[str, Any]: The content of the pyproject.toml file.
30
+ Example:
31
+ >>> content = read_pyproject("pyproject.toml")
32
+ >>> "." in content["project"]["version"]
33
+ True
34
+ """
35
+ from msgspec import toml
36
+ with open(pyproject_path) as file:
37
+ content = file.read()
38
+ return toml.decode(content)
39
+
40
+
41
+ def format_toml_lists(content: str) -> str:
42
+ """ Format TOML lists with indentation.
43
+
44
+ Args:
45
+ content (str): The content of the pyproject.toml file.
46
+ Returns:
47
+ str: The formatted content with properly indented lists.
48
+ Example:
49
+ >>> toml_content = '''[project]
50
+ ... dependencies = [ "tqdm>=4.0.0", "requests>=2.20.0", "pyyaml>=6.0.0", ]'''
51
+ >>> format_toml_lists(toml_content).replace("\\t", " ") == '''[project]
52
+ ... dependencies = [
53
+ ... "tqdm>=4.0.0",
54
+ ... "requests>=2.20.0",
55
+ ... "pyyaml>=6.0.0",
56
+ ... ]'''
57
+ True
58
+ """
59
+ # Split the content into individual lines for processing
60
+ lines: list[str] = content.split("\n")
61
+ formatted_lines: list[str] = []
62
+
63
+ for line in lines:
64
+ # Check if line contains a list definition (has both [ ] and = characters)
65
+ if "[" in line and "]" in line and "=" in line:
66
+ # Only process simple lists that have one opening and closing bracket
67
+ if line.count("[") == 1 and line.count("]") == 1:
68
+ # Split into key and values parts
69
+ key, values = line.split("=", 1)
70
+ values = values.strip()
71
+
72
+ # Check if values portion is a list
73
+ if values.startswith("[") and values.endswith("]"):
74
+ # Parse list values, removing empty entries
75
+ values = [v.strip() for v in values[1:-1].split(",") if v.strip()]
76
+
77
+ # For lists with multiple items, format across multiple lines
78
+ if len(values) > 1:
79
+ formatted_lines.append(f"{key}= [")
80
+ for value in values:
81
+ formatted_lines.append(f"\t{value},")
82
+ formatted_lines.append("]")
83
+ # For single item lists, keep on one line
84
+ else:
85
+ formatted_lines.append(f"{key}= [{values[0]}]")
86
+ continue
87
+
88
+ # Keep non-list lines unchanged
89
+ formatted_lines.append(line)
90
+
91
+ # Rejoin all lines with newlines
92
+ return "\n".join(formatted_lines)
93
+
94
+
95
+ def write_pyproject(path: str, content: dict[str, Any]) -> None:
96
+ """ Write to the pyproject.toml file with properly indented lists.
97
+
98
+ Args:
99
+ path: Path to the pyproject.toml file.
100
+ content: Content to write to the pyproject.toml file.
101
+ """
102
+ from msgspec.toml import _import_tomli_w # pyright: ignore[reportPrivateUsage]
103
+ toml = _import_tomli_w()
104
+ string: str = "\n" + toml.dumps(content) + "\n"
105
+ string = format_toml_lists(string) # Apply formatting
106
+
107
+ with super_open(path, "w") as file:
108
+ file.write(string)
109
+
110
+
111
+ def increment_version_from_input(version: str) -> str:
112
+ """ Increment the version.
113
+
114
+ Args:
115
+ version: The version to increment. (ex: "0.1.0")
116
+ Returns:
117
+ str: The incremented version. (ex: "0.1.1")
118
+ Example:
119
+ >>> increment_version_from_input("0.1.0")
120
+ '0.1.1'
121
+ >>> increment_version_from_input("1.2.9")
122
+ '1.2.10'
123
+ """
124
+ version_parts: list[str] = version.split(".")
125
+ version_parts[-1] = str(int(version_parts[-1]) + 1)
126
+ return ".".join(version_parts)
127
+
128
+ def increment_version_from_pyproject(path: str) -> None:
129
+ """ Increment the version in the pyproject.toml file.
130
+
131
+ Args:
132
+ path: Path to the pyproject.toml file.
133
+ """
134
+ pyproject_content: dict[str, Any] = read_pyproject(path)
135
+ pyproject_content["project"]["version"] = increment_version_from_input(pyproject_content["project"]["version"])
136
+ write_pyproject(path, pyproject_content)
137
+
138
+ def get_version_from_pyproject(path: str) -> str:
139
+ """ Get the version from the pyproject.toml file.
140
+
141
+ Args:
142
+ path: Path to the pyproject.toml file.
143
+ Returns:
144
+ str: The version. (ex: "0.1.0")
145
+ """
146
+ return read_pyproject(path)["project"]["version"]
147
+
@@ -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,86 @@
1
+ """ This module contains utilities for generating stub files using stubgen.
2
+
3
+ - generate_stubs: Generate stub files for a Python package using stubgen
4
+ - stubs_full_routine: Generate stub files for a Python package
5
+
6
+ """
7
+
8
+ # Imports
9
+ import os
10
+ from collections.abc import Callable
11
+
12
+ from ..decorators import LogLevels, handle_error
13
+
14
+
15
+ def generate_stubs(
16
+ package_name: str,
17
+ extra_args: str = "--include-docstrings --include-private",
18
+ ) -> int:
19
+ """ Generate stub files for a Python package using stubgen.
20
+
21
+ Note: stubgen generates stubs in the 'out' directory by default in the current working directory.
22
+
23
+ Args:
24
+ package_name (str): Name of the package to generate stubs for.
25
+ extra_args (str): Extra arguments to pass to stubgen. Defaults to "--include-docstrings --include-private".
26
+ Returns:
27
+ int: Return code of the os.system call.
28
+ """
29
+ try:
30
+ from mypy.stubgen import main as stubgen_main
31
+ except ImportError as e:
32
+ raise ImportError("mypy is required for array_to_disk function. Please install it via 'pip install mypy'.") from e
33
+ try:
34
+ stubgen_main(["-p", package_name, *extra_args.split()])
35
+ return 0
36
+ except Exception:
37
+ return 1
38
+
39
+ def clean_stubs_directory(output_directory: str, package_name: str) -> None:
40
+ """ Clean the stubs directory by deleting all .pyi files.
41
+
42
+ Args:
43
+ output_directory (str): Directory to clean.
44
+ package_name (str): Package name subdirectory. Only cleans output_directory/package_name.
45
+ """
46
+ target_dir: str = os.path.join(output_directory, package_name)
47
+ if os.path.exists(target_dir):
48
+ for root, _, files in os.walk(target_dir):
49
+ for file in files:
50
+ if file.endswith(".pyi"):
51
+ os.remove(os.path.join(root, file))
52
+
53
+ @handle_error(message="Error while doing the stubs full routine", error_log=LogLevels.ERROR_TRACEBACK)
54
+ def stubs_full_routine(
55
+ package_name: str,
56
+ output_directory: str = "typings",
57
+ extra_args: str = "--include-docstrings --include-private",
58
+ clean_before: bool = False,
59
+
60
+ generate_stubs_function: Callable[[str, str], int] = generate_stubs,
61
+ clean_stubs_function: Callable[[str, str], None] = clean_stubs_directory,
62
+ ) -> None:
63
+ """ Generate stub files for a Python package using stubgen.
64
+
65
+ Note: stubgen generates stubs in the 'out' directory by default in the current working directory.
66
+
67
+ Args:
68
+ package_name (str): Name of the package to generate stubs for.
69
+ output_directory (str): Directory to clean before generating stubs. Defaults to "typings".
70
+ This parameter is used for cleaning the directory before stub generation.
71
+ extra_args (str): Extra arguments to pass to stubgen. Defaults to "--include-docstrings --include-private".
72
+ clean_before (bool): Whether to clean the output directory before generating stubs. Defaults to False.
73
+ generate_stubs_function (Callable[[str, str], int]): Function to generate stubs.
74
+ Defaults to :func:`generate_stubs`.
75
+ clean_stubs_function (Callable[[str], None]): Function to clean the stubs directory.
76
+ Defaults to :func:`clean_stubs_directory`.
77
+ Raises:
78
+ Exception: If stub generation fails.
79
+ """
80
+ if clean_before:
81
+ clean_stubs_function(output_directory, package_name)
82
+ extra_args += f" -o {output_directory}"
83
+
84
+ if generate_stubs_function(package_name, extra_args) != 0:
85
+ raise Exception(f"Error while generating stubs for {package_name}")
86
+
@@ -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'''