stouputils 1.0.24__tar.gz → 1.0.26__tar.gz

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 (53) hide show
  1. {stouputils-1.0.24 → stouputils-1.0.26}/PKG-INFO +5 -5
  2. {stouputils-1.0.24 → stouputils-1.0.26}/pyproject.toml +18 -4
  3. stouputils-1.0.26/src/stouputils/continuous_delivery/pyproject.py +121 -0
  4. stouputils-1.0.24/.github/workflows/documentation.yml +0 -42
  5. stouputils-1.0.24/.python-version +0 -1
  6. stouputils-1.0.24/all_in_one.py +0 -13
  7. stouputils-1.0.24/assets/all_doctests_module.gif +0 -0
  8. stouputils-1.0.24/assets/archive_module.gif +0 -0
  9. stouputils-1.0.24/assets/backup_module.gif +0 -0
  10. stouputils-1.0.24/assets/collections_module.gif +0 -0
  11. stouputils-1.0.24/assets/continuous_delivery/github_module.gif +0 -0
  12. stouputils-1.0.24/assets/ctx_module.gif +0 -0
  13. stouputils-1.0.24/assets/decorators_module_1.gif +0 -0
  14. stouputils-1.0.24/assets/decorators_module_2.gif +0 -0
  15. stouputils-1.0.24/assets/io_module.gif +0 -0
  16. stouputils-1.0.24/assets/parallel_module.gif +0 -0
  17. stouputils-1.0.24/assets/print_module.gif +0 -0
  18. stouputils-1.0.24/build_all_in_one.py +0 -20
  19. stouputils-1.0.24/copy_in_local.py +0 -12
  20. stouputils-1.0.24/examples/all_doctests.py +0 -13
  21. stouputils-1.0.24/examples/archive/corrupted.zip +0 -0
  22. stouputils-1.0.24/examples/archive.py +0 -24
  23. stouputils-1.0.24/examples/collections.py +0 -28
  24. stouputils-1.0.24/examples/ctx.py +0 -25
  25. stouputils-1.0.24/examples/decorators_1.py +0 -29
  26. stouputils-1.0.24/examples/decorators_2.py +0 -21
  27. stouputils-1.0.24/examples/delta_backup.py +0 -7
  28. stouputils-1.0.24/examples/io.py +0 -33
  29. stouputils-1.0.24/examples/parallel.py +0 -28
  30. stouputils-1.0.24/examples/print.py +0 -27
  31. stouputils-1.0.24/github_release.py +0 -26
  32. stouputils-1.0.24/scripts/create_docs.py +0 -315
  33. stouputils-1.0.24/src/stouputils/continuous_delivery/pyproject.py +0 -69
  34. stouputils-1.0.24/upgrade.py +0 -16
  35. {stouputils-1.0.24 → stouputils-1.0.26}/.gitignore +0 -0
  36. {stouputils-1.0.24 → stouputils-1.0.26}/LICENSE +0 -0
  37. {stouputils-1.0.24 → stouputils-1.0.26}/README.md +0 -0
  38. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/__init__.py +0 -0
  39. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/all_doctests.py +0 -0
  40. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/archive.py +0 -0
  41. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/backup.py +0 -0
  42. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/collections.py +0 -0
  43. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/continuous_delivery/__init__.py +0 -0
  44. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/continuous_delivery/cd_utils.py +0 -0
  45. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/continuous_delivery/github.py +0 -0
  46. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/continuous_delivery/pypi.py +0 -0
  47. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/ctx.py +0 -0
  48. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/decorators.py +0 -0
  49. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/dont_look/zip_file_override.py +0 -0
  50. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/io.py +0 -0
  51. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/parallel.py +0 -0
  52. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/print.py +0 -0
  53. {stouputils-1.0.24 → stouputils-1.0.26}/src/stouputils/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stouputils
3
- Version: 1.0.24
3
+ Version: 1.0.26
4
4
  Summary: Stouputils is a collection of utility modules designed to simplify and enhance the development process. It includes a range of tools for tasks such as execution of doctests, display utilities, decorators, as well as context managers, and many more.
5
5
  Project-URL: Homepage, https://github.com/Stoupy51/stouputils
6
6
  Project-URL: Issues, https://github.com/Stoupy51/stouputils/issues
@@ -10,10 +10,10 @@ Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Requires-Python: >=3.10
13
- Requires-Dist: pyyaml
14
- Requires-Dist: requests>=2.31.0
15
- Requires-Dist: toml
16
- Requires-Dist: tqdm>=4.66.4
13
+ Requires-Dist: pyyaml>=6.0.0
14
+ Requires-Dist: requests>=2.30.0
15
+ Requires-Dist: toml>=0.10.0
16
+ Requires-Dist: tqdm>=4.66.0
17
17
  Description-Content-Type: text/markdown
18
18
 
19
19
 
@@ -1,15 +1,25 @@
1
+
1
2
  [build-system]
2
- requires = [ "hatchling",]
3
+ requires = ["hatchling"]
3
4
  build-backend = "hatchling.build"
4
5
 
5
6
  [project]
6
7
  name = "stouputils"
7
- version = "1.0.24"
8
+ version = "1.0.26"
8
9
  description = "Stouputils is a collection of utility modules designed to simplify and enhance the development process. It includes a range of tools for tasks such as execution of doctests, display utilities, decorators, as well as context managers, and many more."
9
10
  readme = "README.md"
10
11
  requires-python = ">=3.10"
11
- classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent",]
12
- dependencies = [ "tqdm>=4.66.4", "requests>=2.31.0", "pyyaml", "toml",]
12
+ classifiers = [
13
+ "Programming Language :: Python :: 3",
14
+ "License :: OSI Approved :: MIT License",
15
+ "Operating System :: OS Independent",
16
+ ]
17
+ dependencies = [
18
+ "tqdm>=4.66.0",
19
+ "requests>=2.30.0",
20
+ "pyyaml>=6.0.0",
21
+ "toml>=0.10.0",
22
+ ]
13
23
  [[project.authors]]
14
24
  name = "Stoupy51"
15
25
  email = "stoupy51@gmail.com"
@@ -20,3 +30,7 @@ Issues = "https://github.com/Stoupy51/stouputils/issues"
20
30
 
21
31
  [tool.pyright]
22
32
  typeCheckingMode = "strict"
33
+
34
+ [tool.hatch.build]
35
+ include = ["src"]
36
+
@@ -0,0 +1,121 @@
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 ..io import super_open
19
+ from typing import Any
20
+ import toml
21
+
22
+ def read_pyproject(pyproject_path: str) -> dict[str, Any]:
23
+ """ Read the pyproject.toml file.
24
+
25
+ Args:
26
+ pyproject_path: Path to the pyproject.toml file.
27
+
28
+ Returns:
29
+ dict[str, Any]: The content of the pyproject.toml file.
30
+ """
31
+ return toml.load(pyproject_path)
32
+
33
+
34
+ def format_toml_lists(content: str) -> str:
35
+ """ Format TOML lists with indentation.
36
+
37
+ Args:
38
+ content (str): The content of the pyproject.toml file.
39
+
40
+ Returns:
41
+ str: The formatted content with properly indented lists.
42
+ """
43
+ # Split the content into individual lines for processing
44
+ lines: list[str] = content.split("\n")
45
+ formatted_lines: list[str] = []
46
+
47
+ for line in lines:
48
+ # Check if line contains a list definition (has both [ ] and = characters)
49
+ if "[" in line and "]" in line and "=" in line:
50
+ # Only process simple lists that have one opening and closing bracket
51
+ if line.count("[") == 1 and line.count("]") == 1:
52
+ # Split into key and values parts
53
+ key, values = line.split("=", 1)
54
+ values = values.strip()
55
+
56
+ # Check if values portion is a list
57
+ if values.startswith("[") and values.endswith("]"):
58
+ # Parse list values, removing empty entries
59
+ values = [v.strip() for v in values[1:-1].split(",") if v.strip()]
60
+
61
+ # For lists with multiple items, format across multiple lines
62
+ if len(values) > 1:
63
+ formatted_lines.append(f"{key}= [")
64
+ for value in values:
65
+ formatted_lines.append(f"\t{value},")
66
+ formatted_lines.append("]")
67
+ # For single item lists, keep on one line
68
+ else:
69
+ formatted_lines.append(f"{key}= [{values[0]}]")
70
+ continue
71
+
72
+ # Keep non-list lines unchanged
73
+ formatted_lines.append(line)
74
+
75
+ # Rejoin all lines with newlines
76
+ return "\n".join(formatted_lines)
77
+
78
+
79
+ def write_pyproject(pyproject_path: str, pyproject_content: dict[str, Any]) -> None:
80
+ """ Write to the pyproject.toml file with properly indented lists. """
81
+ content: str = "\n" + toml.dumps(pyproject_content) + "\n"
82
+ content = format_toml_lists(content) # Apply formatting
83
+
84
+ with super_open(pyproject_path, "w") as file:
85
+ file.write(content)
86
+
87
+
88
+ def increment_version_from_input(version: str) -> str:
89
+ """ Increment the version.
90
+
91
+ Args:
92
+ version: The version to increment. (ex: "0.1.0")
93
+
94
+ Returns:
95
+ str: The incremented version. (ex: "0.1.1")
96
+ """
97
+ version_parts: list[str] = version.split(".")
98
+ version_parts[-1] = str(int(version_parts[-1]) + 1)
99
+ return ".".join(version_parts)
100
+
101
+ def increment_version_from_pyproject(pyproject_path: str) -> None:
102
+ """ Increment the version in the pyproject.toml file.
103
+
104
+ Args:
105
+ pyproject_path: Path to the pyproject.toml file.
106
+ """
107
+ pyproject_content: dict[str, Any] = read_pyproject(pyproject_path)
108
+ pyproject_content["project"]["version"] = increment_version_from_input(pyproject_content["project"]["version"])
109
+ write_pyproject(pyproject_path, pyproject_content)
110
+
111
+ def get_version_from_pyproject(pyproject_path: str) -> str:
112
+ """ Get the version from the pyproject.toml file.
113
+
114
+ Args:
115
+ pyproject_path: Path to the pyproject.toml file.
116
+
117
+ Returns:
118
+ str: The version. (ex: "0.1.0")
119
+ """
120
+ return read_pyproject(pyproject_path)["project"]["version"]
121
+
@@ -1,42 +0,0 @@
1
- name: documentation
2
-
3
- on:
4
- push:
5
- branches:
6
- - main
7
- tags:
8
- - 'v*'
9
- pull_request:
10
- workflow_dispatch:
11
-
12
- permissions:
13
- contents: write
14
-
15
- jobs:
16
- docs:
17
- runs-on: ubuntu-latest
18
- steps:
19
- - uses: actions/checkout@v4
20
- - uses: actions/setup-python@v5
21
- - name: Install dependencies
22
- run: |
23
- pip install hatch stouputils sphinx sphinx_rtd_theme myst_parser furo
24
- hatch build
25
- - name: Build latest docs
26
- if: github.ref == 'refs/heads/main'
27
- run: |
28
- python scripts/create_docs.py
29
- - name: Build version docs
30
- if: startsWith(github.ref, 'refs/tags/v')
31
- run: |
32
- python scripts/create_docs.py ${GITHUB_REF#refs/tags/v}
33
- - name: Deploy to GitHub Pages
34
- uses: peaceiris/actions-gh-pages@v3
35
- if: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') || startsWith(github.ref, 'refs/tags/v') }}
36
- with:
37
- publish_branch: gh-pages
38
- github_token: ${{ secrets.GITHUB_TOKEN }}
39
- publish_dir: docs/build/html
40
- keep_files: true
41
- force_orphan: false
42
-
@@ -1 +0,0 @@
1
- 3.10
@@ -1,13 +0,0 @@
1
-
2
- import os
3
- import sys
4
- commands = [
5
- f"{sys.executable} upgrade.py", # Upgrade the version in pyproject.toml
6
- f"{sys.executable} build_all_in_one.py", # Build the package and upload it
7
- ]
8
-
9
- for command in commands:
10
- if os.system(command) != 0:
11
- print(f"Error while executing '{command}'")
12
- exit(1)
13
-
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,20 +0,0 @@
1
-
2
- # Imports
3
- import stouputils as stp
4
-
5
- # Constants
6
- ROOT: str = stp.get_root_path(__file__)
7
- REPOSITORY: str = "stouputils"
8
- DIST_DIRECTORY: str = f"{ROOT}/dist"
9
- LAST_FILES: int = 1
10
- ENDWITH: str = ".tar.gz"
11
-
12
- if __name__ == "__main__":
13
-
14
- stp.pypi_full_routine(
15
- repository=REPOSITORY,
16
- dist_directory=DIST_DIRECTORY,
17
- last_files=LAST_FILES,
18
- endswith=ENDWITH,
19
- )
20
-
@@ -1,12 +0,0 @@
1
-
2
- import shutil
3
- import os
4
-
5
- source = os.path.dirname(os.path.realpath(__file__)).replace("\\","/") + "/src/stouputils"
6
- destination = "C:/Users/Alexandre-PC/AppData/Local/Programs/Python/Python310/Lib/site-packages/stouputils"
7
-
8
- shutil.rmtree(destination, ignore_errors=True)
9
- shutil.copytree(source, destination)
10
- os.system("clear")
11
- print("\nCopied stouputils to local Python's site-packages\n")
12
-
@@ -1,13 +0,0 @@
1
-
2
- # Imports
3
- import stouputils as stp
4
-
5
- # Main
6
- @stp.measure_time(stp.info, message="All doctests finished")
7
- def main() -> None:
8
- FOLDER_TO_TEST: str = stp.get_root_path(__file__, 1) + "/src"
9
- stp.launch_tests(FOLDER_TO_TEST)
10
-
11
- if __name__ == "__main__":
12
- main()
13
-
@@ -1,24 +0,0 @@
1
-
2
- # Imports
3
- import stouputils as stp
4
- from zipfile import ZipFile, BadZipFile
5
-
6
- # Main
7
- if __name__ == "__main__":
8
- PREFIX: str = "examples/archive"
9
-
10
- ## Repair a corrupted zip file
11
- # Try to read the first file
12
- @stp.handle_error(BadZipFile)
13
- def read_file() -> None:
14
- with ZipFile(f"{PREFIX}/corrupted.zip", "r") as zip_file:
15
- stp.info(zip_file.read("pack.mcmeta"))
16
- read_file()
17
-
18
- # Repair it
19
- stp.repair_zip_file(f"{PREFIX}/corrupted.zip", f"{PREFIX}/repaired.zip")
20
-
21
- # Read the first file
22
- with ZipFile(f"{PREFIX}/repaired.zip", "r") as zip_file:
23
- stp.info(zip_file.read("pack.mcmeta"))
24
-
@@ -1,28 +0,0 @@
1
-
2
- # Imports
3
- import stouputils as stp
4
-
5
- # Main
6
- if __name__ == "__main__":
7
-
8
- # Example with numbers
9
- numbers: list[int] = [1, 2, 3, 2, 1, 4, 3]
10
- unique_numbers: list[int] = stp.unique_list(numbers)
11
- stp.info(f"Original numbers: {numbers}")
12
- stp.info(f"Unique numbers: {unique_numbers}")
13
-
14
- # Example with sets using different methods
15
- s1: set[int] = {1, 2, 3}
16
- s2: set[int] = {2, 3, 4}
17
- s3: set[int] = {1, 2, 3}
18
- sets: list[set[int]] = [s1, s2, s1, s1, s3, s2, s3]
19
-
20
- # Using id method (keeps s1 and s3 as separate objects)
21
- unique_sets_id: list[set[int]] = stp.unique_list(sets, method="id")
22
- stp.info(f"Unique sets (id method): {unique_sets_id}")
23
-
24
- # Using str method (combines s1 and s3 as they have same string representation)
25
- unique_sets_str: list[set[int]] = stp.unique_list(sets, method="str")
26
- stp.info(f"Unique sets (str method): {unique_sets_str}")
27
-
28
-
@@ -1,25 +0,0 @@
1
-
2
- # Imports
3
- import stouputils as stp
4
- import sys
5
- import os
6
-
7
- # Main
8
- if __name__ == "__main__":
9
-
10
- with stp.Muffle(mute_stderr=True):
11
- print("Nothing")
12
- print("here", file=sys.stderr)
13
- stp.info("will be")
14
- stp.info("printed", file=sys.stderr)
15
-
16
- OUTPUT_PATH: str = "_super_idol_de_xiao_rong.log"
17
- with stp.LogToFile(OUTPUT_PATH):
18
- stp.info("""
19
- Why did the programmer always bring a ladder to work?
20
- Because they spent so much time debugging and climbing through their log files!
21
- """)
22
-
23
- stp.breakpoint("Press Enter to continue...")
24
- os.remove(OUTPUT_PATH)
25
-
@@ -1,29 +0,0 @@
1
-
2
- # Imports
3
- import stouputils as stp
4
- import time
5
-
6
- # Main
7
- if __name__ == "__main__":
8
-
9
- # Cache the result of the function and measure the time it takes to execute
10
- @stp.measure_time(stp.progress, "Time taken to execute long_function")
11
- @stp.simple_cache()
12
- def long_function() -> dict[str, int]:
13
- stp.info("Starting long function...")
14
- time.sleep(1)
15
- stp.info("Long function finished!")
16
- return {"a": 1, "b": 2}
17
-
18
- a = long_function() # Takes 1 second
19
- b = long_function() # Takes 0 second
20
- stp.info(f"a: {a}, b: {b}, a is b: {a is b}")
21
- b["c"] = 3
22
- stp.info(f"a has been modified because a is b: {a}")
23
-
24
- # Silent decorator
25
- @stp.silent
26
- def silent_function():
27
- print("ON THE CONSOLE")
28
- silent_function()
29
-
@@ -1,21 +0,0 @@
1
-
2
- # Imports
3
- import stouputils as stp
4
-
5
- # Main
6
- if __name__ == "__main__":
7
-
8
- # Handle exceptions
9
- @stp.handle_error(ZeroDivisionError,
10
- "Debugging: The process of removing software bugs, and putting in new ones",
11
- error_log=stp.LogLevels.WARNING_TRACEBACK
12
- )
13
- def raise_value_error():
14
- return 1 / 0
15
-
16
- @stp.handle_error()
17
- def raise_value_error_2():
18
- return 1 / 0
19
-
20
- raise_value_error() # This will show the error using stp.warning
21
- raise_value_error_2() # This will show the error using stp.error
@@ -1,7 +0,0 @@
1
-
2
- # Example of use:
3
- # py examples/delta_backup.py delta "src" "backup" -x "*pycache*"
4
-
5
- import stouputils as stp
6
- stp.backup_cli()
7
-
@@ -1,33 +0,0 @@
1
-
2
- # Imports
3
- import stouputils as stp
4
- from typing import Any
5
-
6
- # Main
7
- if __name__ == "__main__":
8
-
9
- path: str = "C:\\\\Users\\\\Stoupy\\\\Documents\\\\test.txt"
10
- path = stp.clean_path(path)
11
- stp.info(path)
12
-
13
- tilde_path: str = "~/Desktop/OnlyFansIncome.txt"
14
- tilde_path = stp.replace_tilde(tilde_path)
15
- stp.info(tilde_path)
16
-
17
- this_folder_dont_exist: str = "./this_folder_dont_exist/a/c/feff/efefe/a"
18
- with stp.super_open(this_folder_dont_exist, "w") as file: # Automatically create the folder
19
- file.write("Hello, world!")
20
-
21
- # Copy a file to a folder, or rename the copied file
22
- stp.super_copy("LICENSE", "this_folder_dont_exist/a/") # .../a/LICENSE
23
- stp.super_copy("LICENSE", "this_folder_dont_exist/a/LICENSE_2") # .../a/LICENSE_2
24
- stp.breakpoint("Waiting for input to continue code execution...")
25
-
26
- # Dump a JSON file with a specified indentation depth
27
- data: dict[str, Any] = {"name": "John", "array": [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]}
28
- stp.info("\n", stp.super_json_dump(data, max_level=2))
29
-
30
- # Remove the folder
31
- import shutil
32
- shutil.rmtree("this_folder_dont_exist")
33
-
@@ -1,28 +0,0 @@
1
-
2
- # Imports
3
- import stouputils as stp
4
- import time
5
-
6
- # Functions
7
- def is_even(n: int) -> bool:
8
- return n % 2 == 0
9
-
10
- def multiple_args(a: int, b: int) -> int:
11
- return a * b
12
-
13
- # Main
14
- if __name__ == "__main__":
15
-
16
- # Multi-threading (blazingly fast for IO-bound tasks)
17
- args_1: list[int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
18
- results_1: list[bool] = stp.multithreading(is_even, args_1)
19
- stp.info(f"Results: {results_1}")
20
-
21
- # Multi-processing (better for CPU-bound tasks)
22
- time.sleep(1)
23
- args_2: list[tuple[int, int]] = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
24
- results_2: list[int] = stp.multiprocessing(
25
- multiple_args, args_2, use_starmap=True, desc="Multiple args", max_workers=2, verbose=1
26
- )
27
- stp.info(f"Results: {results_2}")
28
-
@@ -1,27 +0,0 @@
1
-
2
- # Imports
3
- import time
4
- import stouputils as stp
5
-
6
- # Main
7
- if __name__ == "__main__":
8
- stp.info("Hello", "World")
9
- time.sleep(0.5)
10
- stp.info("Hello", "World")
11
- time.sleep(0.5)
12
- stp.info("Hello", "World")
13
- time.sleep(0.5)
14
- stp.info("Not Hello World !")
15
- time.sleep(0.5)
16
- stp.info("Hello", "World")
17
- time.sleep(0.5)
18
- stp.info("Hello", "World")
19
-
20
- # All remaining print functions
21
- stp.debug("Hello", "World")
22
- stp.suggestion("Hello", "World")
23
- stp.progress("Hello", "World")
24
- stp.warning("Hello", "World")
25
- stp.error("Hello", "World", exit=False)
26
- stp.whatisit("Hello", "World")
27
-
@@ -1,26 +0,0 @@
1
-
2
- # Imports
3
- from stouputils import load_credentials, upload_to_github, clean_path
4
- from typing import Any
5
- from upgrade import current_version
6
- import os
7
-
8
- # Constants
9
- ROOT: str = clean_path(os.path.dirname(os.path.abspath(__file__)))
10
- CREDENTIALS_PATH: str = "~/stouputils/credentials.yml"
11
- GITHUB_CONFIG: dict[str, Any] = {
12
- "project_name": "stouputils",
13
- "version": current_version,
14
- "build_folder": f"{ROOT}/dist",
15
- "endswith": [
16
- f"{current_version}.tar.gz",
17
- f"{current_version}-py3-none-any.whl",
18
- ],
19
- }
20
-
21
- # Get credentials
22
- credentials: dict[str, Any] = load_credentials(CREDENTIALS_PATH)
23
-
24
- # Upload to GitHub
25
- changelog: str = upload_to_github(credentials, GITHUB_CONFIG)
26
-
@@ -1,315 +0,0 @@
1
-
2
- # Imports
3
- import os
4
- import shutil
5
- import subprocess
6
- import sys
7
- from stouputils import clean_path, handle_error, warning, simple_cache
8
- from stouputils.continuous_delivery.github import version_to_float
9
- clean_exec: str = clean_path(sys.executable)
10
-
11
- conf_content: str = """
12
- # Imports
13
- import os
14
- import sys
15
- from typing import Any
16
- sys.path.insert(0, os.path.abspath('../..'))
17
- sys.path.insert(0, os.path.abspath('../../src'))
18
- from upgrade import current_version # Get version from pyproject.toml
19
-
20
- # Project information
21
- project: str = 'stouputils'
22
- copyright: str = '2024, Stoupy'
23
- author: str = 'Stoupy'
24
- release: str = current_version
25
-
26
- # General configuration
27
- extensions: list[str] = [
28
- 'sphinx.ext.autodoc',
29
- 'sphinx.ext.napoleon',
30
- 'sphinx.ext.viewcode',
31
- 'sphinx.ext.githubpages',
32
- 'sphinx.ext.intersphinx',
33
- 'furo.sphinxext',
34
- ]
35
-
36
- templates_path: list[str] = ['_templates']
37
- exclude_patterns: list[str] = []
38
-
39
- # HTML output options
40
- html_theme: str = 'furo'
41
- html_static_path: list[str] = ['_static']
42
- html_logo: str = 'https://avatars.githubusercontent.com/u/35665974'
43
- html_title: str = 'stouputils'
44
- html_favicon: str = 'https://avatars.githubusercontent.com/u/35665974'
45
-
46
- # Theme options
47
- html_theme_options: dict[str, Any] = {
48
- 'light_css_variables': {
49
- 'color-brand-primary': '#2980B9',
50
- 'color-brand-content': '#2980B9',
51
- 'color-admonition-background': '#E8F0F8',
52
- },
53
- 'dark_css_variables': {
54
- 'color-brand-primary': '#56B4E9',
55
- 'color-brand-content': '#56B4E9',
56
- 'color-admonition-background': '#1F262B',
57
- },
58
- 'sidebar_hide_name': False,
59
- 'navigation_with_keys': True,
60
- 'announcement': 'This is the latest documentation of stouputils',
61
- 'footer_icons': [
62
- {
63
- 'name': 'GitHub',
64
- 'url': 'https://github.com/Stoupy51/stouputils',
65
- 'html': '<i class="fab fa-github-square"></i>',
66
- 'class': '',
67
- },
68
- ],
69
- }
70
-
71
- # Add any paths that contain custom static files
72
- html_static_path: list[str] = ['_static']
73
-
74
- # Autodoc settings
75
- autodoc_default_options: dict[str, bool | str] = {
76
- 'members': True,
77
- 'member-order': 'bysource',
78
- 'special-members': False,
79
- 'undoc-members': False,
80
- 'private-members': False,
81
- 'show-inheritance': True,
82
- 'ignore-module-all': True,
83
- 'exclude-members': '__weakref__'
84
- }
85
-
86
- # Tell autodoc to prefer source code over installed package
87
- autodoc_mock_imports = []
88
- always_document_param_types = True
89
- add_module_names = False
90
-
91
- # Tell Sphinx to look for source code in src directory
92
- html_context = {
93
- 'display_github': True,
94
- 'github_user': 'Stoupy51',
95
- 'github_repo': 'stouputils',
96
- 'github_version': 'main',
97
- 'conf_py_path': '/docs/source/',
98
- 'source_suffix': '.rst',
99
- 'default_mode': 'dark',
100
- }
101
-
102
- # Only document items with docstrings
103
- def skip_undocumented(app: Any, what: str, name: str, obj: Any, skip: bool, *args: Any, **kwargs: Any) -> bool:
104
- if not obj.__doc__:
105
- return True
106
- return skip
107
-
108
- def setup(app: Any) -> None:
109
- app.connect('autodoc-skip-member', skip_undocumented)
110
- """
111
-
112
- @simple_cache()
113
- def get_versions_from_github() -> list[str]:
114
- """ Get list of versions from GitHub gh-pages branch.
115
-
116
- Returns:
117
- list[str]: List of versions, with 'latest' as first element
118
- """
119
- import requests
120
- version_list: list[str] = []
121
- try:
122
- response = requests.get("https://api.github.com/repos/Stoupy51/stouputils/contents?ref=gh-pages")
123
- if response.status_code == 200:
124
- contents = response.json()
125
- version_list = ["latest"] + sorted(
126
- [d["name"].replace("v", "") for d in contents
127
- if d["type"] == "dir" and d["name"].startswith("v")],
128
- key=version_to_float,
129
- reverse=True
130
- )
131
- except Exception as e:
132
- warning(f"Failed to get versions from GitHub: {e}")
133
- version_list = ["latest"]
134
- return version_list
135
-
136
- def generate_index_rst(readme_path: str, index_path: str) -> None:
137
- """ Generate index.rst from README.md content.
138
-
139
- Args:
140
- readme_path (str): Path to the README.md file
141
- index_path (str): Path where index.rst should be created
142
- """
143
- with open(readme_path, 'r', encoding="utf-8") as f:
144
- readme_content: str = f.read()
145
-
146
- # Convert markdown badges to RST format
147
- badges_rst: str = """
148
- .. image:: https://img.shields.io/github/v/release/Stoupy51/stouputils?logo=github&label=GitHub
149
- :target: https://github.com/Stoupy51/stouputils/releases/latest
150
-
151
- .. image:: https://img.shields.io/pypi/dm/stouputils?logo=python&label=PyPI%20downloads
152
- :target: https://pypi.org/project/stouputils/
153
- """
154
-
155
- # Generate version selector
156
- version_selector: str = """
157
-
158
- **Versions**: """
159
-
160
- # Get versions from GitHub
161
- version_list: list[str] = get_versions_from_github()
162
-
163
- # Create version links
164
- version_links: list[str] = []
165
- for version in version_list:
166
- if version == 'latest':
167
- version_links.append("`latest <../latest/index.html>`_")
168
- else:
169
- version_links.append(f"`v{version} <../v{version}/index.html>`_")
170
-
171
- version_selector += ", ".join(version_links)
172
-
173
- # Extract sections while preserving emojis
174
- overview_section: str = readme_content.split('# 📚 Project Overview')[1].split('\n#')[0].strip()
175
- file_tree_section: str = readme_content.split('# 🚀 Project File Tree')[1].split('\n#')[0].strip()
176
- file_tree_section = file_tree_section.replace('```bash', '').replace('```', '').strip()
177
- file_tree_section = "\n".join([f" {line}" for line in file_tree_section.split('\n')])
178
-
179
- # Generate module documentation section
180
- module_docs: str = ".. toctree::\n :maxdepth: 10\n :caption: Contents:\n\n"
181
-
182
- # Add base module
183
- module_docs += " modules/stouputils\n\n"
184
-
185
- # Generate the RST content with emojis and proper title underlines
186
- rst_content: str = f"""
187
- 🛠️ Welcome to Stouputils Documentation
188
- =======================================
189
-
190
- {badges_rst}
191
-
192
- {version_selector}
193
-
194
- 📚 Overview
195
- -----------
196
- {overview_section.replace("<br>", " ")}
197
-
198
- 🚀 Project Structure
199
- -------------------
200
- .. code-block:: bash
201
-
202
- {file_tree_section}
203
-
204
- 📖 Module Documentation
205
- ----------------------
206
- {module_docs}
207
-
208
- ⚡ Indices and Tables
209
- ===================
210
-
211
- * :ref:`genindex`
212
- * :ref:`modindex`
213
- * :ref:`search`
214
- """
215
-
216
- # Write the RST file
217
- with open(index_path, 'w', encoding="utf-8") as f:
218
- f.write(rst_content)
219
-
220
- def generate_conf_py(conf_path: str) -> None:
221
- """ Generate conf.py file.
222
-
223
- Args:
224
- conf_path (str): Path where conf.py should be created
225
- """
226
- with open(conf_path, 'w', encoding="utf-8") as f:
227
- f.write(conf_content)
228
-
229
- @handle_error()
230
- def update_documentation(version: str | None = None) -> None:
231
- """ Update the Sphinx documentation.
232
- This script will:
233
- 1. Create necessary directories if they don't exist
234
- 2. Generate module documentation using sphinx-apidoc
235
- 3. Build HTML documentation for specific version if provided
236
-
237
- Args:
238
- version (str | None): Version to build documentation for. If None, builds for latest
239
- """
240
- # Get the project root directory (parent of scripts folder)
241
- root_dir: str = clean_path(os.path.dirname(os.path.dirname(__file__)))
242
- docs_dir: str = clean_path(os.path.join(root_dir, "docs"))
243
- source_dir: str = clean_path(os.path.join(docs_dir, "source"))
244
- modules_dir: str = clean_path(os.path.join(source_dir, "modules"))
245
-
246
- # Modify build directory if version is specified
247
- build_dir: str = "html/latest" if not version else f"html/v{version}"
248
-
249
- # Create directories if they don't exist
250
- os.makedirs(modules_dir, exist_ok=True)
251
- os.makedirs(clean_path(os.path.join(source_dir, "_static")), exist_ok=True)
252
- os.makedirs(clean_path(os.path.join(source_dir, "_templates")), exist_ok=True)
253
-
254
- # Generate index.rst from README.md
255
- readme_path: str = clean_path(os.path.join(root_dir, "README.md"))
256
- index_path: str = clean_path(os.path.join(source_dir, "index.rst"))
257
- generate_index_rst(readme_path, index_path)
258
-
259
- # Clean up old module documentation
260
- if os.path.exists(modules_dir):
261
- shutil.rmtree(modules_dir)
262
- os.makedirs(modules_dir)
263
-
264
- # Update conf.py to include version selector
265
- version_list: list[str] = get_versions_from_github()
266
-
267
- # Update html_context in conf.py
268
- global conf_content
269
- conf_content = conf_content.replace(
270
- "html_context = {",
271
- f"""html_context = {{
272
- 'versions': {version_list},
273
- 'current_version': 'latest' if not {repr(version)} else {repr(version)},"""
274
- )
275
-
276
- # Generate docs/source/conf.py
277
- conf_path: str = clean_path(os.path.join(source_dir, "conf.py"))
278
- generate_conf_py(conf_path)
279
-
280
- # Generate module documentation using python -m
281
- subprocess.run([
282
- clean_exec,
283
- "-m", "sphinx.ext.apidoc",
284
- "-o", modules_dir, # Output directory
285
- "-f", # Force overwrite
286
- "-e", # Put documentation for each module on its own page
287
- "-M", # Put module documentation before submodule documentation
288
- "--no-toc", # Don't create a table of contents file
289
- "-P", # Include private modules
290
- "--implicit-namespaces",# Handle implicit namespaces
291
- "--module-first", # Put module documentation before submodule documentation
292
- clean_path(os.path.join(root_dir, "src/stouputils")), # Source code directory
293
- ], check=True)
294
-
295
- # Build HTML documentation using python -m
296
- subprocess.run([
297
- clean_exec,
298
- "-m", "sphinx",
299
- "-b", "html", # Build HTML
300
- "-a", # Write all files
301
- source_dir, # Source directory
302
- clean_path(f"{docs_dir}/build/{build_dir}"), # Output directory
303
- ], check=True)
304
-
305
- print("Documentation updated successfully!")
306
- print(f"You can view the documentation by opening {docs_dir}/build/{build_dir}/index.html")
307
-
308
- if __name__ == "__main__":
309
- if len(sys.argv) == 2:
310
- update_documentation(sys.argv[1].replace("v", "")) # Remove "v" from version just in case
311
- elif len(sys.argv) == 1:
312
- update_documentation()
313
- else:
314
- raise ValueError("Usage: python create_docs.py [version]")
315
-
@@ -1,69 +0,0 @@
1
- """ This module contains utilities for reading and writing pyproject.toml files.
2
-
3
- - read_pyproject: Read the pyproject.toml file.
4
- - write_pyproject: Write to the pyproject.toml file.
5
-
6
- .. image:: https://raw.githubusercontent.com/Stoupy51/stouputils/refs/heads/main/assets/continuous_delivery/pyproject_module.gif
7
- :alt: stouputils pyproject examples
8
- """
9
-
10
- # Imports
11
- from ..io import super_open
12
- from typing import Any
13
- import toml
14
-
15
- def read_pyproject(pyproject_path: str) -> dict[str, Any]:
16
- """ Read the pyproject.toml file.
17
-
18
- Args:
19
- pyproject_path: Path to the pyproject.toml file.
20
-
21
- Returns:
22
- dict[str, Any]: The content of the pyproject.toml file.
23
- """
24
- return toml.load(pyproject_path)
25
-
26
- def write_pyproject(pyproject_path: str, pyproject_content: dict[str, Any]) -> None:
27
- """ Write to the pyproject.toml file.
28
-
29
- Args:
30
- pyproject_path: Path to the pyproject.toml file.
31
- pyproject_content: The content to write to the pyproject.toml file.
32
- """
33
- with super_open(pyproject_path, "w") as file:
34
- toml.dump(pyproject_content, file)
35
-
36
- def increment_version(version: str) -> str:
37
- """ Increment the version.
38
-
39
- Args:
40
- version: The version to increment. (ex: "0.1.0")
41
-
42
- Returns:
43
- str: The incremented version. (ex: "0.1.1")
44
- """
45
- version_parts: list[str] = version.split(".")
46
- version_parts[-1] = str(int(version_parts[-1]) + 1)
47
- return ".".join(version_parts)
48
-
49
- def increment_version_from_pyproject(pyproject_path: str) -> None:
50
- """ Increment the version in the pyproject.toml file.
51
-
52
- Args:
53
- pyproject_path: Path to the pyproject.toml file.
54
- """
55
- pyproject_content = read_pyproject(pyproject_path)
56
- pyproject_content["project"]["version"] = increment_version(pyproject_content["project"]["version"])
57
- write_pyproject(pyproject_path, pyproject_content)
58
-
59
- def get_version_from_pyproject(pyproject_path: str) -> str:
60
- """ Get the version from the pyproject.toml file.
61
-
62
- Args:
63
- pyproject_path: Path to the pyproject.toml file.
64
-
65
- Returns:
66
- str: The version. (ex: "0.1.0")
67
- """
68
- return read_pyproject(pyproject_path)["project"]["version"]
69
-
@@ -1,16 +0,0 @@
1
-
2
- ## Python script that modifies the pyproject.toml to go to the next version
3
- # Imports
4
- import stouputils as stp
5
-
6
- # Constants
7
- ROOT: str = stp.get_root_path(__file__)
8
- PYPROJECT_PATH = f"{ROOT}/pyproject.toml"
9
- CURRENT_VERSION: str = stp.get_version_from_pyproject(PYPROJECT_PATH)
10
-
11
- # Main
12
- if __name__ == "__main__":
13
-
14
- # Increment version
15
- stp.increment_version_from_pyproject(PYPROJECT_PATH)
16
-
File without changes
File without changes
File without changes