stouputils 1.18.5__tar.gz → 1.19.0__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.
- {stouputils-1.18.5 → stouputils-1.19.0}/PKG-INFO +5 -4
- {stouputils-1.18.5 → stouputils-1.19.0}/README.md +4 -2
- {stouputils-1.18.5 → stouputils-1.19.0}/pyproject.toml +1 -2
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/all_doctests.py +10 -3
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/automatic_docs.py +44 -62
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/automatic_docs.pyi +6 -12
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/print.py +91 -44
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/print.pyi +39 -17
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/__init__.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/__main__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/_deprecated.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/_deprecated.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/all_doctests.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/__init__.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/upscaler/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/upscaler/__init__.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/upscaler/config.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/upscaler/config.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/upscaler/image.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/upscaler/image.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/upscaler/video.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/applications/upscaler/video.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/archive.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/archive.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/backup.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/backup.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/collections.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/collections.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/__init__.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/cd_utils.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/cd_utils.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/github.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/github.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/pypi.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/pypi.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/pyproject.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/pyproject.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/stubs.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/continuous_delivery/stubs.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/ctx.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/ctx.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/config/get.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/config/set.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/auto_contrast.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/axis_flip.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/bias_field_correction.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/binary_threshold.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/blur.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/brightness.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/canny.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/clahe.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/common.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/contrast.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/curvature_flow_filter.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/denoise.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/histogram_equalization.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/invert.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/laplacian.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/median_blur.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/noise.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/normalize.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/random_erase.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/resize.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/rotation.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/salt_pepper.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/sharpening.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/shearing.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/threshold.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/translation.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image/zoom.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image_augmentation.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/image_preprocess.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/prosthesis_detection.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/data_processing/technique.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/dataset/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/dataset/dataset.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/dataset/dataset_loader.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/dataset/grouping_strategy.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/dataset/image_loader.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/dataset/xy_tuple.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/metric_dictionnary.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/metric_utils.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/mlflow_utils.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/abstract_model.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/all.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/base_keras.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras/all.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras/convnext.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras/densenet.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras/efficientnet.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras/mobilenet.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras/resnet.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras/squeezenet.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras/vgg.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras/xception.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras_utils/callbacks/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras_utils/callbacks/colored_progress_bar.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras_utils/callbacks/learning_rate_finder.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras_utils/callbacks/model_checkpoint_v2.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras_utils/callbacks/progressive_unfreezing.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras_utils/callbacks/warmup_scheduler.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras_utils/losses/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras_utils/losses/next_generation_loss.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/keras_utils/visualizations.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/model_interface.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/models/sandbox.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/range_tuple.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/scripts/augment_dataset.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/scripts/exhaustive_process.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/scripts/preprocess_dataset.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/scripts/routine.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/data_science/utils.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/decorators.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/decorators.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/image.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/image.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/__init__.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/common.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/common.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/downloader.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/downloader.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/linux.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/linux.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/main.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/main.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/windows.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/installer/windows.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/io.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/io.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/__init__.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/base.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/base.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/queue.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/queue.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/re_entrant.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/re_entrant.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/redis_fifo.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/redis_fifo.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/shared.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/lock/shared.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/__init__.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/__init__.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/capturer.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/capturer.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/common.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/common.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/multi.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/multi.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/subprocess.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/parallel/subprocess.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/py.typed +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/typing.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/typing.pyi +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/version_pkg.py +0 -0
- {stouputils-1.18.5 → stouputils-1.19.0}/stouputils/version_pkg.pyi +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: stouputils
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.19.0
|
|
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
|
Keywords: utilities,tools,helpers,development,python
|
|
6
6
|
Author: Stoupy51
|
|
@@ -26,7 +26,6 @@ Requires-Dist: tensorflow ; extra == 'data-science'
|
|
|
26
26
|
Requires-Dist: scikit-learn ; extra == 'data-science'
|
|
27
27
|
Requires-Dist: pywavelets ; extra == 'data-science'
|
|
28
28
|
Requires-Dist: mypy ; extra == 'docs'
|
|
29
|
-
Requires-Dist: m2r2 ; extra == 'docs'
|
|
30
29
|
Requires-Dist: myst-parser ; extra == 'docs'
|
|
31
30
|
Requires-Dist: sphinx-copybutton ; extra == 'docs'
|
|
32
31
|
Requires-Dist: sphinx-design ; extra == 'docs'
|
|
@@ -54,9 +53,11 @@ Stouputils is a collection of utility modules designed to simplify and enhance t
|
|
|
54
53
|
It includes a range of tools for tasks such as execution of doctests, display utilities, decorators, as well as context managers.<br>
|
|
55
54
|
Start now by installing the package: `pip install stouputils`.<br>
|
|
56
55
|
|
|
57
|
-
<a href="https://colab.research.google.com/drive/1mJ-KL-zXzIk1oKDxO6FC1SFfm-BVKG-P?usp=sharing" target="_blank" rel="noopener noreferrer" style="text-decoration: none;"
|
|
56
|
+
<a href="https://colab.research.google.com/drive/1mJ-KL-zXzIk1oKDxO6FC1SFfm-BVKG-P?usp=sharing" target="_blank" rel="noopener noreferrer" style="text-decoration: none;">
|
|
57
|
+
<div class="admonition" style="padding-bottom: 1rem;">
|
|
58
58
|
📖 <b>Want to see examples?</b> Check out our <u>Google Colab notebook</u> with practical usage examples!
|
|
59
|
-
</div
|
|
59
|
+
</div>
|
|
60
|
+
</a>
|
|
60
61
|
|
|
61
62
|
## 🚀 Project File Tree
|
|
62
63
|
<html>
|
|
@@ -9,9 +9,11 @@ Stouputils is a collection of utility modules designed to simplify and enhance t
|
|
|
9
9
|
It includes a range of tools for tasks such as execution of doctests, display utilities, decorators, as well as context managers.<br>
|
|
10
10
|
Start now by installing the package: `pip install stouputils`.<br>
|
|
11
11
|
|
|
12
|
-
<a href="https://colab.research.google.com/drive/1mJ-KL-zXzIk1oKDxO6FC1SFfm-BVKG-P?usp=sharing" target="_blank" rel="noopener noreferrer" style="text-decoration: none;"
|
|
12
|
+
<a href="https://colab.research.google.com/drive/1mJ-KL-zXzIk1oKDxO6FC1SFfm-BVKG-P?usp=sharing" target="_blank" rel="noopener noreferrer" style="text-decoration: none;">
|
|
13
|
+
<div class="admonition" style="padding-bottom: 1rem;">
|
|
13
14
|
📖 <b>Want to see examples?</b> Check out our <u>Google Colab notebook</u> with practical usage examples!
|
|
14
|
-
</div
|
|
15
|
+
</div>
|
|
16
|
+
</a>
|
|
15
17
|
|
|
16
18
|
## 🚀 Project File Tree
|
|
17
19
|
<html>
|
|
@@ -8,7 +8,7 @@ module-root = ""
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "stouputils"
|
|
11
|
-
version = "1.
|
|
11
|
+
version = "1.19.0"
|
|
12
12
|
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."
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
keywords = ["utilities", "tools", "helpers", "development", "python"]
|
|
@@ -37,7 +37,6 @@ authors = [
|
|
|
37
37
|
[project.optional-dependencies]
|
|
38
38
|
docs = [
|
|
39
39
|
"mypy",
|
|
40
|
-
"m2r2",
|
|
41
40
|
"myst_parser",
|
|
42
41
|
"sphinx_copybutton",
|
|
43
42
|
"sphinx_design",
|
|
@@ -94,15 +94,22 @@ def launch_tests(root_dir: str, strict: bool = True, pattern: str = "*") -> int:
|
|
|
94
94
|
if not modules_file_paths:
|
|
95
95
|
raise ValueError(f"No modules found in '{relative_path(root_dir)}'")
|
|
96
96
|
|
|
97
|
+
# Sort module by number of submodules and alphabetically
|
|
98
|
+
modules_file_paths.sort(key=lambda x: (x.count('.'), x))
|
|
99
|
+
|
|
97
100
|
# Filter modules based on pattern
|
|
98
101
|
if pattern != "*":
|
|
99
102
|
import fnmatch
|
|
100
|
-
|
|
103
|
+
new_paths: list[str] = [
|
|
101
104
|
path for path in modules_file_paths
|
|
102
105
|
if fnmatch.fnmatch(path, pattern)
|
|
103
106
|
]
|
|
104
|
-
if not
|
|
105
|
-
raise ValueError(
|
|
107
|
+
if not new_paths:
|
|
108
|
+
raise ValueError(
|
|
109
|
+
f"No modules matching pattern '{pattern}' found in '{relative_path(root_dir)}'.\n"
|
|
110
|
+
f"Candidates were: {', '.join(relative_path(p) for p in modules_file_paths)[:500]}..."
|
|
111
|
+
)
|
|
112
|
+
modules_file_paths = new_paths
|
|
106
113
|
|
|
107
114
|
# Find longest module path for alignment
|
|
108
115
|
max_length: int = max(len(path) for path in modules_file_paths)
|
|
@@ -68,8 +68,6 @@ Example of GitHub Actions workflow:
|
|
|
68
68
|
# Imports
|
|
69
69
|
import os
|
|
70
70
|
import shutil
|
|
71
|
-
import subprocess
|
|
72
|
-
import sys
|
|
73
71
|
from collections.abc import Callable
|
|
74
72
|
from typing import Any
|
|
75
73
|
|
|
@@ -79,7 +77,7 @@ from ..io import clean_path, json_dump, super_open
|
|
|
79
77
|
from ..print import info
|
|
80
78
|
|
|
81
79
|
# Constants
|
|
82
|
-
REQUIREMENTS: list[str] = ["
|
|
80
|
+
REQUIREMENTS: list[str] = ["myst_parser"]
|
|
83
81
|
""" List of requirements for automatic_docs to work. """
|
|
84
82
|
|
|
85
83
|
# Functions
|
|
@@ -185,6 +183,12 @@ copybutton_selector = ":not(.prompt) > div.highlight pre"
|
|
|
185
183
|
templates_path: list[str] = ["_templates"]
|
|
186
184
|
exclude_patterns: list[str] = []
|
|
187
185
|
|
|
186
|
+
# Allow both .rst and .md (MyST) sources
|
|
187
|
+
source_suffix = {{
|
|
188
|
+
".rst": "restructuredtext",
|
|
189
|
+
".md": "markdown",
|
|
190
|
+
}}
|
|
191
|
+
|
|
188
192
|
# HTML output options
|
|
189
193
|
html_theme: str = "{html_theme}"
|
|
190
194
|
html_static_path: list[str] = ["_static"]
|
|
@@ -205,7 +209,6 @@ html_theme_options: dict[str, Any] = {{
|
|
|
205
209
|
"github_repo": github_repo,
|
|
206
210
|
"github_version": "main",
|
|
207
211
|
"conf_py_path": "/docs/source/",
|
|
208
|
-
"source_suffix": [".rst", ".md"],
|
|
209
212
|
"default_mode": "dark",
|
|
210
213
|
}
|
|
211
214
|
|
|
@@ -318,23 +321,7 @@ def get_versions_from_github(github_user: str, github_repo: str, recent_minor_ve
|
|
|
318
321
|
version_list = ["latest"]
|
|
319
322
|
return version_list
|
|
320
323
|
|
|
321
|
-
def
|
|
322
|
-
""" Convert markdown content to RST format.
|
|
323
|
-
|
|
324
|
-
Args:
|
|
325
|
-
markdown_content (str): Markdown content
|
|
326
|
-
|
|
327
|
-
Returns:
|
|
328
|
-
str: RST content
|
|
329
|
-
"""
|
|
330
|
-
if not markdown_content:
|
|
331
|
-
return ""
|
|
332
|
-
|
|
333
|
-
# Convert markdown to RST and return it
|
|
334
|
-
import m2r2 # type: ignore
|
|
335
|
-
return m2r2.convert(markdown_content) # type: ignore
|
|
336
|
-
|
|
337
|
-
def generate_index_rst(
|
|
324
|
+
def generate_index_md(
|
|
338
325
|
readme_path: str,
|
|
339
326
|
index_path: str,
|
|
340
327
|
project: str,
|
|
@@ -343,11 +330,14 @@ def generate_index_rst(
|
|
|
343
330
|
get_versions_function: Callable[[str, str, int], list[str]] = get_versions_from_github,
|
|
344
331
|
recent_minor_versions: int = 2,
|
|
345
332
|
) -> None:
|
|
346
|
-
""" Generate index.
|
|
333
|
+
""" Generate `index.md` (MyST) from README.md content.
|
|
334
|
+
|
|
335
|
+
This keeps the README content as Markdown (no conversion) and uses the MyST
|
|
336
|
+
`toctree` directive to include module docs.
|
|
347
337
|
|
|
348
338
|
Args:
|
|
349
339
|
readme_path (str): Path to the README.md file
|
|
350
|
-
index_path (str): Path where index.
|
|
340
|
+
index_path (str): Path where index.md should be created
|
|
351
341
|
project (str): Name of the project
|
|
352
342
|
github_user (str): GitHub username
|
|
353
343
|
github_repo (str): GitHub repository name
|
|
@@ -358,50 +348,44 @@ def generate_index_rst(
|
|
|
358
348
|
with open(readme_path, encoding="utf-8") as f:
|
|
359
349
|
readme_content: str = f.read()
|
|
360
350
|
|
|
361
|
-
# Generate version selector
|
|
362
|
-
version_selector: str = "\n\n**Versions**: "
|
|
363
|
-
|
|
364
|
-
# Get versions from GitHub
|
|
351
|
+
# Generate version selector (markdown links)
|
|
365
352
|
version_list: list[str] = get_versions_function(github_user, github_repo, recent_minor_versions)
|
|
366
|
-
|
|
367
|
-
# Create version links
|
|
368
353
|
version_links: list[str] = []
|
|
369
354
|
for version in version_list:
|
|
370
355
|
if version == "latest":
|
|
371
|
-
version_links.append("
|
|
356
|
+
version_links.append("[latest](../latest/)")
|
|
372
357
|
else:
|
|
373
|
-
version_links.append(f"
|
|
374
|
-
version_selector
|
|
358
|
+
version_links.append(f"[v{version}](../v{version}/)")
|
|
359
|
+
version_selector: str = "\n\n**Versions**: " + ", ".join(version_links)
|
|
375
360
|
|
|
376
|
-
#
|
|
361
|
+
# Module documentation toctree (MyST)
|
|
377
362
|
project_module: str = project.lower()
|
|
378
363
|
module_docs: str = f"""
|
|
379
|
-
|
|
380
|
-
|
|
364
|
+
```{{toctree}}
|
|
365
|
+
:maxdepth: 10
|
|
381
366
|
|
|
382
|
-
|
|
367
|
+
modules/{project_module}
|
|
368
|
+
```
|
|
383
369
|
"""
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
# Convert markdown to RST
|
|
390
|
-
rst_content: str = f"""
|
|
391
|
-
✨ Welcome to {project.capitalize()} Documentation ✨
|
|
392
|
-
{'=' * 100}
|
|
370
|
+
|
|
371
|
+
# Build final markdown content
|
|
372
|
+
md_content: str = f"""
|
|
373
|
+
# ✨ Welcome to {project.capitalize()} Documentation ✨
|
|
374
|
+
|
|
393
375
|
{version_selector}
|
|
394
376
|
|
|
395
|
-
{
|
|
377
|
+
{readme_content}
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Module Documentation
|
|
396
382
|
|
|
397
|
-
📖 Module Documentation
|
|
398
|
-
{'-' * 100}
|
|
399
383
|
{module_docs}
|
|
400
384
|
"""
|
|
401
385
|
|
|
402
|
-
# Write the
|
|
386
|
+
# Write the Markdown file
|
|
403
387
|
with open(index_path, "w", encoding="utf-8") as f:
|
|
404
|
-
f.write(
|
|
388
|
+
f.write(md_content)
|
|
405
389
|
|
|
406
390
|
def generate_documentation(
|
|
407
391
|
source_dir: str,
|
|
@@ -418,9 +402,8 @@ def generate_documentation(
|
|
|
418
402
|
build_dir (str): Build directory
|
|
419
403
|
"""
|
|
420
404
|
# Generate module documentation using sphinx-apidoc
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
"-m", "sphinx.ext.apidoc",
|
|
405
|
+
from sphinx.ext.apidoc import main as sphinx_apidoc_main
|
|
406
|
+
sphinx_apidoc_main([
|
|
424
407
|
"-o", modules_dir,
|
|
425
408
|
"-f", "-e", "-M",
|
|
426
409
|
"--no-toc",
|
|
@@ -428,17 +411,16 @@ def generate_documentation(
|
|
|
428
411
|
"--implicit-namespaces",
|
|
429
412
|
"--module-first",
|
|
430
413
|
project_dir,
|
|
431
|
-
]
|
|
414
|
+
])
|
|
432
415
|
|
|
433
416
|
# Build HTML documentation
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
"-m", "sphinx",
|
|
417
|
+
from sphinx.cmd.build import main as sphinx_build_main
|
|
418
|
+
sphinx_build_main([
|
|
437
419
|
"-b", "html",
|
|
438
420
|
"-a",
|
|
439
421
|
source_dir,
|
|
440
422
|
build_dir,
|
|
441
|
-
]
|
|
423
|
+
])
|
|
442
424
|
|
|
443
425
|
def generate_redirect_html(filepath: str) -> None:
|
|
444
426
|
""" Generate HTML content for redirect page.
|
|
@@ -478,7 +460,7 @@ def update_documentation(
|
|
|
478
460
|
recent_minor_versions: int = 2,
|
|
479
461
|
|
|
480
462
|
get_versions_function: Callable[[str, str, int], list[str]] = get_versions_from_github,
|
|
481
|
-
generate_index_function: Callable[..., None] =
|
|
463
|
+
generate_index_function: Callable[..., None] = generate_index_md,
|
|
482
464
|
generate_docs_function: Callable[..., None] = generate_documentation,
|
|
483
465
|
generate_redirect_function: Callable[[str], None] = generate_redirect_html,
|
|
484
466
|
get_conf_content_function: Callable[..., str] = get_sphinx_conf_content
|
|
@@ -501,7 +483,7 @@ def update_documentation(
|
|
|
501
483
|
recent_minor_versions (int): Number of recent minor versions to show all patches for. Defaults to 2
|
|
502
484
|
|
|
503
485
|
get_versions_function (Callable[[str, str, int], list[str]]): Function to get versions from GitHub
|
|
504
|
-
generate_index_function (Callable[..., None]): Function to generate index.
|
|
486
|
+
generate_index_function (Callable[..., None]): Function to generate index.md
|
|
505
487
|
generate_docs_function (Callable[..., None]): Function to generate documentation
|
|
506
488
|
generate_redirect_function (Callable[[str], None]): Function to create redirect file
|
|
507
489
|
get_conf_content_function (Callable[..., str]): Function to get Sphinx conf.py content
|
|
@@ -573,9 +555,9 @@ a:hover {
|
|
|
573
555
|
}
|
|
574
556
|
""")
|
|
575
557
|
|
|
576
|
-
# Generate index.
|
|
558
|
+
# Generate index.md from README.md (use MyST instead of converting to RST)
|
|
577
559
|
readme_path: str = f"{root_path}/README.md"
|
|
578
|
-
index_path: str = f"{source_dir}/index.
|
|
560
|
+
index_path: str = f"{source_dir}/index.md"
|
|
579
561
|
generate_index_function(
|
|
580
562
|
readme_path=readme_path,
|
|
581
563
|
index_path=index_path,
|
|
@@ -44,21 +44,15 @@ def get_versions_from_github(github_user: str, github_repo: str, recent_minor_ve
|
|
|
44
44
|
\tReturns:
|
|
45
45
|
\t\tlist[str]: List of versions, with 'latest' as first element
|
|
46
46
|
\t"""
|
|
47
|
-
def
|
|
48
|
-
"""
|
|
47
|
+
def generate_index_md(readme_path: str, index_path: str, project: str, github_user: str, github_repo: str, get_versions_function: Callable[[str, str, int], list[str]] = ..., recent_minor_versions: int = 2) -> None:
|
|
48
|
+
""" Generate `index.md` (MyST) from README.md content.
|
|
49
49
|
|
|
50
|
-
\
|
|
51
|
-
\t
|
|
52
|
-
|
|
53
|
-
\tReturns:
|
|
54
|
-
\t\tstr: RST content
|
|
55
|
-
\t"""
|
|
56
|
-
def generate_index_rst(readme_path: str, index_path: str, project: str, github_user: str, github_repo: str, get_versions_function: Callable[[str, str, int], list[str]] = ..., recent_minor_versions: int = 2) -> None:
|
|
57
|
-
""" Generate index.rst from README.md content.
|
|
50
|
+
\tThis keeps the README content as Markdown (no conversion) and uses the MyST
|
|
51
|
+
\t`toctree` directive to include module docs.
|
|
58
52
|
|
|
59
53
|
\tArgs:
|
|
60
54
|
\t\treadme_path (str): Path to the README.md file
|
|
61
|
-
\t\tindex_path (str): Path where index.
|
|
55
|
+
\t\tindex_path (str): Path where index.md should be created
|
|
62
56
|
\t\tproject (str): Name of the project
|
|
63
57
|
\t\tgithub_user (str): GitHub username
|
|
64
58
|
\t\tgithub_repo (str): GitHub repository name
|
|
@@ -99,7 +93,7 @@ def update_documentation(root_path: str, project: str, project_dir: str = '', au
|
|
|
99
93
|
\t\trecent_minor_versions (int): Number of recent minor versions to show all patches for. Defaults to 2
|
|
100
94
|
|
|
101
95
|
\t\tget_versions_function (Callable[[str, str, int], list[str]]): Function to get versions from GitHub
|
|
102
|
-
\t\tgenerate_index_function (Callable[..., None]): Function to generate index.
|
|
96
|
+
\t\tgenerate_index_function (Callable[..., None]): Function to generate index.md
|
|
103
97
|
\t\tgenerate_docs_function (Callable[..., None]): Function to generate documentation
|
|
104
98
|
\t\tgenerate_redirect_function (Callable[[str], None]): Function to create redirect file
|
|
105
99
|
\t\tget_conf_content_function (Callable[..., str]): Function to get Sphinx conf.py content
|
|
@@ -107,45 +107,67 @@ def format_colored(*values: Any) -> str:
|
|
|
107
107
|
Examples:
|
|
108
108
|
>>> # Test function names with parentheses
|
|
109
109
|
>>> result = format_colored("Call print() with 42 items")
|
|
110
|
-
>>> result.count(MAGENTA)
|
|
111
|
-
|
|
110
|
+
>>> result.count(MAGENTA) # print and 42
|
|
111
|
+
2
|
|
112
112
|
|
|
113
113
|
>>> # Test function names without parentheses
|
|
114
114
|
>>> result = format_colored("Use len and sum functions")
|
|
115
|
-
>>> result.count(MAGENTA)
|
|
116
|
-
|
|
115
|
+
>>> result.count(MAGENTA) # len and sum
|
|
116
|
+
2
|
|
117
117
|
|
|
118
118
|
>>> # Test exceptions (bold magenta)
|
|
119
119
|
>>> result = format_colored("Got ValueError when parsing")
|
|
120
|
-
>>> result.count(MAGENTA)
|
|
121
|
-
|
|
120
|
+
>>> result.count(MAGENTA), result.count(BOLD) # ValueError in bold magenta
|
|
121
|
+
(1, 1)
|
|
122
122
|
|
|
123
123
|
>>> # Test file paths
|
|
124
124
|
>>> result = format_colored("Processing ./data.csv file")
|
|
125
|
-
>>> result.count(MAGENTA)
|
|
126
|
-
|
|
125
|
+
>>> result.count(MAGENTA) # ./data.csv
|
|
126
|
+
1
|
|
127
127
|
|
|
128
128
|
>>> # Test file paths with quotes
|
|
129
129
|
>>> result = format_colored('File "/path/to/script.py" line 42')
|
|
130
|
-
>>> result.count(MAGENTA)
|
|
131
|
-
|
|
130
|
+
>>> result.count(MAGENTA) # /path/to/script.py and 42
|
|
131
|
+
2
|
|
132
132
|
|
|
133
133
|
>>> # Test numbers
|
|
134
|
-
>>> result = format_colored("Found 100 items and 3.14 value")
|
|
135
|
-
>>> result.count(MAGENTA)
|
|
136
|
-
|
|
134
|
+
>>> result = format_colored("Found 100 items and 3.14 value, 3.0e+10 is big")
|
|
135
|
+
>>> result.count(MAGENTA) # 100 and 3.14
|
|
136
|
+
3
|
|
137
137
|
|
|
138
138
|
>>> # Test mixed content
|
|
139
139
|
>>> result = format_colored("Call sum() got IndexError at line 256 in utils.py")
|
|
140
|
-
>>> result.count(MAGENTA)
|
|
141
|
-
|
|
142
|
-
>>> result.count(BOLD)
|
|
143
|
-
|
|
140
|
+
>>> result.count(MAGENTA) # sum, IndexError (bold), and 256
|
|
141
|
+
3
|
|
142
|
+
>>> result.count(BOLD) # IndexError is bold
|
|
143
|
+
1
|
|
144
|
+
|
|
145
|
+
>>> # Test keywords always colored
|
|
146
|
+
>>> result = format_colored("Check class dtype type")
|
|
147
|
+
>>> result.count(MAGENTA) # class, dtype, type
|
|
148
|
+
3
|
|
144
149
|
|
|
145
150
|
>>> # Test plain text (no coloring)
|
|
146
151
|
>>> result = format_colored("This is plain text")
|
|
147
152
|
>>> result.count(MAGENTA) == 0 and result == "This is plain text"
|
|
148
153
|
True
|
|
154
|
+
|
|
155
|
+
>>> # Affix punctuation should not be colored (assert exact coloring, punctuation uncolored)
|
|
156
|
+
>>> result = format_colored("<class")
|
|
157
|
+
>>> result == "<" + MAGENTA + "class" + RESET
|
|
158
|
+
True
|
|
159
|
+
>>> result = format_colored("(dtype:")
|
|
160
|
+
>>> result == "(" + MAGENTA + "dtype" + RESET + ":"
|
|
161
|
+
True
|
|
162
|
+
>>> result = format_colored("[1.")
|
|
163
|
+
>>> result == "[" + MAGENTA + "1" + RESET + "."
|
|
164
|
+
True
|
|
165
|
+
|
|
166
|
+
>>> # Test complex
|
|
167
|
+
>>> text = "<class 'numpy.ndarray'>, <id 140357548266896>: (dtype: float32, shape: (6,), min: 0.0, max: 1.0) [1. 0. 0. 0. 1. 0.]"
|
|
168
|
+
>>> result = format_colored(text)
|
|
169
|
+
>>> result.count(MAGENTA) # class, numpy, ndarray, float32, 6, 0.0, 1.0, 1. 0.
|
|
170
|
+
16
|
|
149
171
|
"""
|
|
150
172
|
import builtins
|
|
151
173
|
import re
|
|
@@ -163,6 +185,9 @@ def format_colored(*values: Any) -> str:
|
|
|
163
185
|
and issubclass(getattr(builtins, name), BaseException))
|
|
164
186
|
}
|
|
165
187
|
|
|
188
|
+
# Additional keywords always colored (case-insensitive on stripped words)
|
|
189
|
+
KEYWORDS: set[str] = {"class", "dtype", "type"}
|
|
190
|
+
|
|
166
191
|
def is_filepath(word: str) -> bool:
|
|
167
192
|
""" Check if a word looks like a file path """
|
|
168
193
|
# Remove quotes if present
|
|
@@ -187,7 +212,7 @@ def format_colored(*values: Any) -> str:
|
|
|
187
212
|
|
|
188
213
|
def is_number(word: str) -> bool:
|
|
189
214
|
try:
|
|
190
|
-
float(word.
|
|
215
|
+
float(''.join(c for c in word if c.isdigit() or c in '.-+e'))
|
|
191
216
|
return True
|
|
192
217
|
except ValueError:
|
|
193
218
|
return False
|
|
@@ -201,7 +226,22 @@ def format_colored(*values: Any) -> str:
|
|
|
201
226
|
|
|
202
227
|
def is_exception(word: str) -> bool:
|
|
203
228
|
""" Check if a word is a known exception name """
|
|
204
|
-
return word.
|
|
229
|
+
return ''.join(c for c in word if c.isalnum()) in EXCEPTION_NAMES
|
|
230
|
+
|
|
231
|
+
def is_keyword(word: str) -> bool:
|
|
232
|
+
""" Check if a word is one of the always-colored keywords """
|
|
233
|
+
clean_alnum = ''.join(c for c in word if c.isalnum())
|
|
234
|
+
return clean_alnum in KEYWORDS
|
|
235
|
+
|
|
236
|
+
def split_affixes(w: str) -> tuple[str, str, str]:
|
|
237
|
+
""" Split leading/trailing non-word characters and return (prefix, core, suffix).
|
|
238
|
+
|
|
239
|
+
This preserves punctuation like '<', '(', '[', '"', etc., while operating on the core text.
|
|
240
|
+
"""
|
|
241
|
+
m = re.match(r'^(\W*)(.*?)(\W*)$', w, re.ASCII)
|
|
242
|
+
if m:
|
|
243
|
+
return m.group(1), m.group(2), m.group(3)
|
|
244
|
+
return "", w, ""
|
|
205
245
|
|
|
206
246
|
# Convert all values to strings and join them and split into words while preserving separators
|
|
207
247
|
text: str = " ".join(str(v) for v in values)
|
|
@@ -219,36 +259,43 @@ def format_colored(*values: Any) -> str:
|
|
|
219
259
|
i += 1
|
|
220
260
|
continue
|
|
221
261
|
|
|
222
|
-
#
|
|
262
|
+
# If the whole token looks like a filepath (e.g. './data.csv' or '/path/to/file'), color it as-is
|
|
223
263
|
colored: bool = False
|
|
224
264
|
if is_filepath(word):
|
|
225
265
|
colored_words.append(f"{MAGENTA}{word}{RESET}")
|
|
226
266
|
colored = True
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
#
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
prefix
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
267
|
+
else:
|
|
268
|
+
# Split affixes to preserve punctuation like '<', '(', '[' etc.
|
|
269
|
+
prefix, core, suffix = split_affixes(word)
|
|
270
|
+
|
|
271
|
+
# Try to identify and color the word (operate on core where applicable)
|
|
272
|
+
if is_filepath(core):
|
|
273
|
+
colored_words.append(f"{prefix}{MAGENTA}{core}{RESET}{suffix}")
|
|
274
|
+
colored = True
|
|
275
|
+
elif is_exception(core):
|
|
276
|
+
colored_words.append(f"{prefix}{BOLD}{MAGENTA}{core}{RESET}{suffix}")
|
|
277
|
+
colored = True
|
|
278
|
+
elif is_number(core):
|
|
279
|
+
colored_words.append(f"{prefix}{MAGENTA}{core}{RESET}{suffix}")
|
|
280
|
+
colored = True
|
|
281
|
+
elif is_keyword(core):
|
|
282
|
+
colored_words.append(f"{prefix}{MAGENTA}{core}{RESET}{suffix}")
|
|
283
|
+
colored = True
|
|
284
|
+
elif is_function_name(core)[0]:
|
|
285
|
+
func_name = is_function_name(core)[1]
|
|
286
|
+
# Find where the function name ends in the core
|
|
287
|
+
func_start = core.find(func_name)
|
|
288
|
+
if func_start != -1:
|
|
289
|
+
pre_core = core[:func_start]
|
|
290
|
+
func_end = func_start + len(func_name)
|
|
291
|
+
post_core = core[func_end:]
|
|
292
|
+
colored_words.append(f"{prefix}{pre_core}{MAGENTA}{func_name}{RESET}{post_core}{suffix}")
|
|
293
|
+
else:
|
|
294
|
+
# Fallback if we can't find it (shouldn't happen)
|
|
295
|
+
colored_words.append(f"{prefix}{MAGENTA}{core}{RESET}{suffix}")
|
|
296
|
+
colored = True
|
|
250
297
|
|
|
251
|
-
# If nothing matched, keep the word
|
|
298
|
+
# If nothing matched, keep the original word
|
|
252
299
|
if not colored:
|
|
253
300
|
colored_words.append(word)
|
|
254
301
|
i += 1
|
|
@@ -53,45 +53,67 @@ def format_colored(*values: Any) -> str:
|
|
|
53
53
|
\tExamples:
|
|
54
54
|
\t\t>>> # Test function names with parentheses
|
|
55
55
|
\t\t>>> result = format_colored("Call print() with 42 items")
|
|
56
|
-
\t\t>>> result.count(MAGENTA)
|
|
57
|
-
\t\
|
|
56
|
+
\t\t>>> result.count(MAGENTA) # print and 42
|
|
57
|
+
\t\t2
|
|
58
58
|
|
|
59
59
|
\t\t>>> # Test function names without parentheses
|
|
60
60
|
\t\t>>> result = format_colored("Use len and sum functions")
|
|
61
|
-
\t\t>>> result.count(MAGENTA)
|
|
62
|
-
\t\
|
|
61
|
+
\t\t>>> result.count(MAGENTA) # len and sum
|
|
62
|
+
\t\t2
|
|
63
63
|
|
|
64
64
|
\t\t>>> # Test exceptions (bold magenta)
|
|
65
65
|
\t\t>>> result = format_colored("Got ValueError when parsing")
|
|
66
|
-
\t\t>>> result.count(MAGENTA)
|
|
67
|
-
\t\
|
|
66
|
+
\t\t>>> result.count(MAGENTA), result.count(BOLD) # ValueError in bold magenta
|
|
67
|
+
\t\t(1, 1)
|
|
68
68
|
|
|
69
69
|
\t\t>>> # Test file paths
|
|
70
70
|
\t\t>>> result = format_colored("Processing ./data.csv file")
|
|
71
|
-
\t\t>>> result.count(MAGENTA)
|
|
72
|
-
\t\
|
|
71
|
+
\t\t>>> result.count(MAGENTA) # ./data.csv
|
|
72
|
+
\t\t1
|
|
73
73
|
|
|
74
74
|
\t\t>>> # Test file paths with quotes
|
|
75
75
|
\t\t>>> result = format_colored(\'File "/path/to/script.py" line 42\')
|
|
76
|
-
\t\t>>> result.count(MAGENTA)
|
|
77
|
-
\t\
|
|
76
|
+
\t\t>>> result.count(MAGENTA) # /path/to/script.py and 42
|
|
77
|
+
\t\t2
|
|
78
78
|
|
|
79
79
|
\t\t>>> # Test numbers
|
|
80
|
-
\t\t>>> result = format_colored("Found 100 items and 3.14 value")
|
|
81
|
-
\t\t>>> result.count(MAGENTA)
|
|
82
|
-
\t\
|
|
80
|
+
\t\t>>> result = format_colored("Found 100 items and 3.14 value, 3.0e+10 is big")
|
|
81
|
+
\t\t>>> result.count(MAGENTA) # 100 and 3.14
|
|
82
|
+
\t\t3
|
|
83
83
|
|
|
84
84
|
\t\t>>> # Test mixed content
|
|
85
85
|
\t\t>>> result = format_colored("Call sum() got IndexError at line 256 in utils.py")
|
|
86
|
-
\t\t>>> result.count(MAGENTA)
|
|
87
|
-
\t\
|
|
88
|
-
\t\t>>> result.count(BOLD)
|
|
89
|
-
\t\
|
|
86
|
+
\t\t>>> result.count(MAGENTA) # sum, IndexError (bold), and 256
|
|
87
|
+
\t\t3
|
|
88
|
+
\t\t>>> result.count(BOLD) # IndexError is bold
|
|
89
|
+
\t\t1
|
|
90
|
+
|
|
91
|
+
\t\t>>> # Test keywords always colored
|
|
92
|
+
\t\t>>> result = format_colored("Check class dtype type")
|
|
93
|
+
\t\t>>> result.count(MAGENTA) # class, dtype, type
|
|
94
|
+
\t\t3
|
|
90
95
|
|
|
91
96
|
\t\t>>> # Test plain text (no coloring)
|
|
92
97
|
\t\t>>> result = format_colored("This is plain text")
|
|
93
98
|
\t\t>>> result.count(MAGENTA) == 0 and result == "This is plain text"
|
|
94
99
|
\t\tTrue
|
|
100
|
+
|
|
101
|
+
\t\t>>> # Affix punctuation should not be colored (assert exact coloring, punctuation uncolored)
|
|
102
|
+
\t\t>>> result = format_colored("<class")
|
|
103
|
+
\t\t>>> result == "<" + MAGENTA + "class" + RESET
|
|
104
|
+
\t\tTrue
|
|
105
|
+
\t\t>>> result = format_colored("(dtype:")
|
|
106
|
+
\t\t>>> result == "(" + MAGENTA + "dtype" + RESET + ":"
|
|
107
|
+
\t\tTrue
|
|
108
|
+
\t\t>>> result = format_colored("[1.")
|
|
109
|
+
\t\t>>> result == "[" + MAGENTA + "1" + RESET + "."
|
|
110
|
+
\t\tTrue
|
|
111
|
+
|
|
112
|
+
\t\t>>> # Test complex
|
|
113
|
+
\t\t>>> text = "<class \'numpy.ndarray\'>, <id 140357548266896>: (dtype: float32, shape: (6,), min: 0.0, max: 1.0) [1. 0. 0. 0. 1. 0.]"
|
|
114
|
+
\t\t>>> result = format_colored(text)
|
|
115
|
+
\t\t>>> result.count(MAGENTA) # class, numpy, ndarray, float32, 6, 0.0, 1.0, 1. 0.
|
|
116
|
+
\t\t16
|
|
95
117
|
\t'''
|
|
96
118
|
def colored(*values: Any, file: TextIO | None = None, **print_kwargs: Any) -> None:
|
|
97
119
|
''' Print with Python 3.14 style colored formatting.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|