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.
- stouputils/__init__.py +40 -0
- stouputils/__init__.pyi +14 -0
- stouputils/__main__.py +81 -0
- stouputils/_deprecated.py +37 -0
- stouputils/_deprecated.pyi +12 -0
- stouputils/all_doctests.py +160 -0
- stouputils/all_doctests.pyi +46 -0
- stouputils/applications/__init__.py +22 -0
- stouputils/applications/__init__.pyi +2 -0
- stouputils/applications/automatic_docs.py +634 -0
- stouputils/applications/automatic_docs.pyi +106 -0
- stouputils/applications/upscaler/__init__.py +39 -0
- stouputils/applications/upscaler/__init__.pyi +3 -0
- stouputils/applications/upscaler/config.py +128 -0
- stouputils/applications/upscaler/config.pyi +18 -0
- stouputils/applications/upscaler/image.py +247 -0
- stouputils/applications/upscaler/image.pyi +109 -0
- stouputils/applications/upscaler/video.py +287 -0
- stouputils/applications/upscaler/video.pyi +60 -0
- stouputils/archive.py +344 -0
- stouputils/archive.pyi +67 -0
- stouputils/backup.py +488 -0
- stouputils/backup.pyi +109 -0
- stouputils/collections.py +244 -0
- stouputils/collections.pyi +86 -0
- stouputils/continuous_delivery/__init__.py +27 -0
- stouputils/continuous_delivery/__init__.pyi +5 -0
- stouputils/continuous_delivery/cd_utils.py +243 -0
- stouputils/continuous_delivery/cd_utils.pyi +129 -0
- stouputils/continuous_delivery/github.py +522 -0
- stouputils/continuous_delivery/github.pyi +162 -0
- stouputils/continuous_delivery/pypi.py +91 -0
- stouputils/continuous_delivery/pypi.pyi +43 -0
- stouputils/continuous_delivery/pyproject.py +147 -0
- stouputils/continuous_delivery/pyproject.pyi +67 -0
- stouputils/continuous_delivery/stubs.py +86 -0
- stouputils/continuous_delivery/stubs.pyi +39 -0
- stouputils/ctx.py +408 -0
- stouputils/ctx.pyi +211 -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 +595 -0
- stouputils/decorators.pyi +242 -0
- stouputils/image.py +441 -0
- stouputils/image.pyi +172 -0
- stouputils/installer/__init__.py +18 -0
- stouputils/installer/__init__.pyi +5 -0
- stouputils/installer/common.py +67 -0
- stouputils/installer/common.pyi +39 -0
- stouputils/installer/downloader.py +101 -0
- stouputils/installer/downloader.pyi +24 -0
- stouputils/installer/linux.py +144 -0
- stouputils/installer/linux.pyi +39 -0
- stouputils/installer/main.py +223 -0
- stouputils/installer/main.pyi +57 -0
- stouputils/installer/windows.py +136 -0
- stouputils/installer/windows.pyi +31 -0
- stouputils/io.py +486 -0
- stouputils/io.pyi +213 -0
- stouputils/parallel.py +453 -0
- stouputils/parallel.pyi +211 -0
- stouputils/print.py +527 -0
- stouputils/print.pyi +146 -0
- stouputils/py.typed +1 -0
- stouputils-1.12.1.dist-info/METADATA +179 -0
- stouputils-1.12.1.dist-info/RECORD +138 -0
- stouputils-1.12.1.dist-info/WHEEL +4 -0
- 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'''
|