diff --git a/README.md b/README.md index eea47145..88a4df12 100644 --- a/README.md +++ b/README.md @@ -50,18 +50,20 @@ features include: pytask is available on [PyPI](https://pypi.org/project/pytask) and on -[Anaconda.org](https://anaconda.org/conda-forge/pytask). Install the package with +[conda-forge](https://anaconda.org/conda-forge/pytask). Install the package with ```console -$ pip install pytask +$ uv add pytask ``` or ```console -$ conda install -c conda-forge pytask +$ pixi add pytask ``` +or use pip, conda, or mamba if you like. + Color support is automatically available on non-Windows platforms. On Windows, please, use [Windows Terminal](https://github.com/microsoft/terminal), which can be, for example, installed via the [Microsoft Store](https://aka.ms/terminal). diff --git a/docs/Makefile b/docs/Makefile index 8b6275ab..cfabf6b7 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -18,3 +18,6 @@ help: # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +livehtml: + sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/source/_static/md/capture.md b/docs/source/_static/md/capture.md index 71b710bc..a14e22cb 100644 --- a/docs/source/_static/md/capture.md +++ b/docs/source/_static/md/capture.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 2 tasks. @@ -15,33 +15,33 @@ Collected 2 tasks. │ task_capture.py::task_func2 │ F │ └──────────────────────────────┴─────────┘ -────────────────────────────────── Failures ────────────────────────────────── - -─────────────────── Task task_capture.py::task_func2 failed ────────────────── - -╭───────────────────── Traceback (most recent call last) ────────────────────╮ - - ...\git\pytask-examples\task_capture.py:13 in task_func2 - - 10 - 11 def task_func2(): - 12 │ print("Debug statement") - 13 assert False - 14 - 15 -╰────────────────────────────────────────────────────────────────────────────╯ +──────────────────────────────── Failures ─────────────────────────────── + +──────────────── Task task_capture.py::task_func2 failed ──────────────── + +╭─────────────────── Traceback (most recent call last) ─────────────────╮ + + ...\git\pytask-examples\task_capture.py:13 in task_func2 + + 10 + 11 def task_func2(): + 12 │ print("Debug statement") + 13 │ assert False + 14 + 15 +╰───────────────────────────────────────────────────────────────────────╯ AssertionError -──────────────────────── Captured stdout during call ───────────────────────── +────────────────────── Captured stdout during call ────────────────────── Debug Statement -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ───────────╮ 2 Collected tasks 1 Succeeded (50.0%) 1 Failed (50.0%) ╰───────────────────────────────╯ -─────────────────────────── Failed in 0.03 seconds ─────────────────────────── +───────────────────────── Failed in 0.03 seconds ──────────────────────── ``` diff --git a/docs/source/_static/md/clean-dry-run-directories.md b/docs/source/_static/md/clean-dry-run-directories.md index 85cdbff9..8dff0403 100644 --- a/docs/source/_static/md/clean-dry-run-directories.md +++ b/docs/source/_static/md/clean-dry-run-directories.md @@ -3,8 +3,8 @@ ```console $ pytask clean --directories -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -12,7 +12,7 @@ Files which can be removed: Would remove svgs/obsolete_file_1.md Would remove svgs/obsolete_folder -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ``` diff --git a/docs/source/_static/md/clean-dry-run.md b/docs/source/_static/md/clean-dry-run.md index 8c11fad8..3baadb32 100644 --- a/docs/source/_static/md/clean-dry-run.md +++ b/docs/source/_static/md/clean-dry-run.md @@ -3,8 +3,8 @@ ```console $ pytask clean -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -13,7 +13,7 @@ Files which can be removed: Would remove svgs/obsolete_file_1.md Would remove svgs/obsolete_folder/obsolete_file_2.md Would remove svgs/obsolete_folder/obsolete_file_3.md -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ``` diff --git a/docs/source/_static/md/collect-nodes.md b/docs/source/_static/md/collect-nodes.md index 6587f300..cb13848f 100644 --- a/docs/source/_static/md/collect-nodes.md +++ b/docs/source/_static/md/collect-nodes.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -14,7 +14,7 @@ Collected tasks: ├── 📄 <Dependency my_project/in.txt> └── 📄 <Product my_project/out.txt> -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ``` diff --git a/docs/source/_static/md/collect.md b/docs/source/_static/md/collect.md index 3604a872..6fc0a420 100644 --- a/docs/source/_static/md/collect.md +++ b/docs/source/_static/md/collect.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -12,7 +12,7 @@ Collected tasks: └── 🐍 <Module task_module.py> └── 📝 <Function task_module.py::task_write_file> -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ``` diff --git a/docs/source/_static/md/defining-dependencies-products.md b/docs/source/_static/md/defining-dependencies-products.md index 735967af..1112bfc0 100644 --- a/docs/source/_static/md/defining-dependencies-products.md +++ b/docs/source/_static/md/defining-dependencies-products.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 2 task. @@ -15,12 +15,12 @@ Collected 2 task. │ task_plot_data.py::task_plot_data │ . │ └───────────────────────────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ────────────╮ 2 Collected tasks 2 Succeeded (100.0%) ╰────────────────────────────────╯ -───────────────────────── Succeeded in 0.06 seconds ────────────────────────── +─────────────────────── Succeeded in 0.06 seconds ─────────────────────── ``` diff --git a/docs/source/_static/md/dry-run.md b/docs/source/_static/md/dry-run.md index 67d6239d..3bb608e9 100644 --- a/docs/source/_static/md/dry-run.md +++ b/docs/source/_static/md/dry-run.md @@ -3,8 +3,8 @@ ```console $ pytask --dry-run -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -14,12 +14,12 @@ Collected 1 task. │ task_dry_run.py::task_dry_run │ w │ └───────────────────────────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ──────────────╮ 1 Collected task 1 Would be executed (100.0%) ╰──────────────────────────────────╯ -───────────────────────── Succeeded in 0.02 seconds ────────────────────────── +─────────────────────── Succeeded in 0.02 seconds ─────────────────────── ``` diff --git a/docs/source/_static/md/help-page.md b/docs/source/_static/md/help-page.md index 2d9081e5..30354811 100644 --- a/docs/source/_static/md/help-page.md +++ b/docs/source/_static/md/help-page.md @@ -3,29 +3,24 @@ ```console $ pytask --help -
pytask v0.4.0
+
pytask v0.5.3
Usage: pytask [OPTIONS] [COMMAND] [PATHS] -Manage your tasks with pytask. +Manage your tasks with pytask. -╭─ Commands ─────────────────────────────────────────────────────────────────╮ - build * Collect tasks, execute them and report the results. - - This is pytask's default command. pytask collects tasks from the - given paths or the current working directory, executes them - and reports the results. - clean Clean the provided paths by removing files unknown to pytask. - collect Collect tasks and report information about them. - dag Create a visualization of the project's directed acyclic graph. - markers Show all registered markers. - profile Show information about tasks like runtime and memory consumption - of products. -╰────────────────────────────────────────────────────────────────────────────╯ -╭─ Options ──────────────────────────────────────────────────────────────────╮ - --version Show the version and exit. - -h --help Show this message and exit. -╰────────────────────────────────────────────────────────────────────────────╯ -

https://pytask-dev.readthedocs.io

+╭─ Commands ────────────────────────────────────────────────────────────╮ + build * Collect tasks, execute them and report the results. + clean Clean the provided paths by removing files unknown to pytask. + collect Collect tasks and report information about them. + dag Create a visualization of the directed acyclic graph. + markers Show all registered markers. + profile Show information about resource consumption +╰───────────────────────────────────────────────────────────────────────╯ +╭─ Options ─────────────────────────────────────────────────────────────╮ + --version Show the version and exit. + -h --help Show this message and exit. +╰───────────────────────────────────────────────────────────────────────╯ +

https://pytask-dev.readthedocs.io

``` diff --git a/docs/source/_static/md/markers.md b/docs/source/_static/md/markers.md index 478ffe10..5597934e 100644 --- a/docs/source/_static/md/markers.md +++ b/docs/source/_static/md/markers.md @@ -3,38 +3,41 @@ ```console $ pytask markers -┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -┃ Marker ┃ Description ┃ -┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ -│ pytask.mark.persist │ Prevent execution of a task if all │ -│ │ products exist and even ifsomething has │ -│ │ changed (dependencies, source file, │ -│ │ products). This decorator might be │ -│ │ useful for expensive tasks where only │ -│ │ the formatting of the file has changed. │ -│ │ The state of the files which have │ -│ │ changed will also be remembered and │ -│ │ another run will skip the task with │ -│ │ success. │ -│ │ │ -│ pytask.mark.skip │ Skip a task and all its dependent tasks.│ -│ │ │ -│ pytask.mark.skip_ancestor_failed │ Internal decorator applied to tasks if │ -│ │ any of its preceding tasks failed. │ -│ │ │ -│ pytask.mark.skip_unchanged │ Internal decorator applied to tasks │ -│ │ which have already been executed and │ -│ │ have not been changed. │ -│ │ │ -│ pytask.mark.skipif │ Skip a task and all its dependent tasks │ -│ │ if a condition is met. │ -│ │ │ -│ pytask.mark.try_first │ Try to execute a task a early as │ -│ │ possible. │ -│ │ │ -│ pytask.mark.try_last │ Try to execute a task a late as │ -│ │ possible. │ -└──────────────────────────────────┴─────────────────────────────────────────┘ +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Marker ┃ Description ┃ +┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ +│ pytask.mark.persist │ Prevent execution of a task if all │ +│ │ products exist and even if │ +│ │ something has changed │ +│ │ (dependencies, source file, │ +│ │ products). This decorator might be │ +│ │ useful for expensive tasks where │ +│ │ only the formatting of the file has│ +│ │ changed. The state of the files │ +│ │ which have changed will also be │ +│ │ remembered and another run will │ +│ │ skip the task with success. │ +│ │ │ +│ pytask.mark.skip │ Skip a task and all its dependent │ +│ │ tasks. │ +│ │ │ +│ pytask.mark.skip_ancestor_failed │ Internal decorator applied to tasks│ +│ │ if any of its preceding tasks │ +│ │ failed. │ +│ │ │ +│ pytask.mark.skip_unchanged │ Internal decorator applied to tasks│ +│ │ which have already been executed │ +│ │ and have not been changed. │ +│ │ │ +│ pytask.mark.skipif │ Skip a task and all its dependent │ +│ │ tasks if a condition is met. │ +│ │ │ +│ pytask.mark.try_first │ Try to execute a task a early as │ +│ │ possible. │ +│ │ │ +│ pytask.mark.try_last │ Try to execute a task a late as │ +│ │ possible. │ +└──────────────────────────────────┴────────────────────────────────────┘ ``` diff --git a/docs/source/_static/md/migrating-from-scripts-to-pytask.md b/docs/source/_static/md/migrating-from-scripts-to-pytask.md index e67d163a..75e0ea66 100644 --- a/docs/source/_static/md/migrating-from-scripts-to-pytask.md +++ b/docs/source/_static/md/migrating-from-scripts-to-pytask.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -14,12 +14,12 @@ Collected 1 task. │ task_data_preparation.py::task_prepare_data │ . │ └─────────────────────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ────────────╮ 1 Collected tasks 1 Succeeded (100.0%) ╰────────────────────────────────╯ -───────────────────────── Succeeded in 30.6 seconds ────────────────────────── +─────────────────────── Succeeded in 30.6 seconds ────────────────────── ``` diff --git a/docs/source/_static/md/pdb.md b/docs/source/_static/md/pdb.md index ed2164e0..899e47eb 100644 --- a/docs/source/_static/md/pdb.md +++ b/docs/source/_static/md/pdb.md @@ -3,27 +3,27 @@ ```console $ pytask --pdb -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. ->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -╭───────────────────── Traceback (most recent call last) ────────────────────╮ - - .../task_data_preparation.py:23 in task_create_random_data - - 20 │ - 21 │ df = pd.DataFrame({"x": x, "y": y}) - 22 │ - 23 raise Exception - 24 │ - 25 │ df.to_pickle(produces) - 26 -╰────────────────────────────────────────────────────────────────────────────╯ +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +╭─────────────────── Traceback (most recent call last) ─────────────────╮ + + .../task_data_preparation.py:23 in task_create_random_data + + 20 │ + 21 │ df = pd.DataFrame({"x": x, "y": y}) + 22 │ + 23 │ raise Exception + 24 │ + 25 │ df.to_pickle(produces) + 26 +╰───────────────────────────────────────────────────────────────────────╯ Exception ->>>>>>>>>>>>>>>>> PDB post_mortem (IO-capturing turned off) >>>>>>>>>>>>>>>>> +>>>>>>>>>>>>>>>> PDB post_mortem (IO-capturing turned off) >>>>>>>>>>>>>> > ...\git\my_project\task_data_preparation.py(23)task_create_random_data() -> raise Exception diff --git a/docs/source/_static/md/persist-executed.md b/docs/source/_static/md/persist-executed.md index 4565c85a..b23d66f1 100644 --- a/docs/source/_static/md/persist-executed.md +++ b/docs/source/_static/md/persist-executed.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -14,12 +14,12 @@ Collected 1 task. │ task_module.py::task_make_input_bold │ . │ └────────────────────────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ────────────╮ 1 Collected tasks 1 Succeeded (100.0%) ╰────────────────────────────────╯ -───────────────────────── Succeeded in 0.07 seconds ────────────────────────── +─────────────────────── Succeeded in 0.07 seconds ─────────────────────── ``` diff --git a/docs/source/_static/md/persist-persisted.md b/docs/source/_static/md/persist-persisted.md index ca6662b8..88ffa1cc 100644 --- a/docs/source/_static/md/persist-persisted.md +++ b/docs/source/_static/md/persist-persisted.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -14,12 +14,12 @@ Collected 1 task. │ task_module.py::task_make_input_bold │ p │ └────────────────────────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ────────────╮ 1 Collected tasks 1 Persisted (100.0%) ╰────────────────────────────────╯ -────────────────────────── Succeeded in 0.0 seconds ────────────────────────── +──────────────────────── Succeeded in 0.0 seconds ─────────────────────── ``` diff --git a/docs/source/_static/md/persist-skipped.md b/docs/source/_static/md/persist-skipped.md index 4a80cdee..d31249d4 100644 --- a/docs/source/_static/md/persist-skipped.md +++ b/docs/source/_static/md/persist-skipped.md @@ -3,8 +3,8 @@ ```console $ pytask --verbose 2 -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -14,12 +14,12 @@ Collected 1 task. │ task_module.py::task_make_input_bold │ s │ └────────────────────────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭──────────────── Summary ─────────────────╮ 1 Collected tasks 1 Skipped because unchanged (100.0%) ╰──────────────────────────────────────────╯ -────────────────────────── Succeeded in 0.0 seconds ────────────────────────── +──────────────────────── Succeeded in 0.0 seconds ─────────────────────── ``` diff --git a/docs/source/_static/md/profiling-tasks.md b/docs/source/_static/md/profiling-tasks.md index e65a6fd4..215f62eb 100644 --- a/docs/source/_static/md/profiling-tasks.md +++ b/docs/source/_static/md/profiling-tasks.md @@ -3,32 +3,32 @@ ```console $ pytask profile -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +───────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 18 task. -┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓ -┃ Task ┃ Duration (in s) ┃ Size ┃ -┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩ -│ task_apply_bh_to_indicators.py::task_apply_… │ 3.93 │ 123 MB │ -│ task_apply_bh_to_indicators.py::task_apply_… │ 0.09 │ 13 MB │ -│ task_replicate_results_of_bh2007.py::task_r… │ 0.09 │ 13 MB │ -│ task_replicate_results_of_bh2007.py::task_r… │ 8.99 │ 8 MB │ -│ task_merge_indicators.py::task_merge_indica… │ 74.44 │ 499 MB │ -│ task_prepare_bessen_hunt_2007.py::task_prep… │ 80.15 │ 15 MB │ -│ task_prepare_datasets.py::task_copy_files[d… │ 0.11 │ 35 MB │ -│ task_prepare_datasets.py::task_copy_files[d… │ 0.92 │ 35 MB │ -│ task_prepare_datasets.py::task_copy_files[d… │ 0.11 │ 34 MB │ -│ task_prepare_datasets.py::task_copy_files[d… │ 0.12 │ 35 MB │ -│ task_prepare_datasets.py::task_copy_files[d… │ 0.12 │ 35 MB │ -│ task_prepare_datasets.py::task_copy_files[d… │ 0.44 │ 143 MB │ -│ task_prepare_datasets.py::task_copy_files[d… │ 0.73 │ 143 MB │ -│ task_prepare_datasets.py::task_copy_files[d… │ 0.37 │ 114 MB │ -│ task_prepare_datasets.py::task_copy_files[d… │ 0.62 │ 170 MB │ -│ task_visualize_distribution_of_patents.py::… │ 17.3 │ 42 KB │ -│ task_compile_document.py::task_compile_thes… │ 7.08 │ 539 KB │ -│ task_table_bessen_hunt_2007_and_replication… │ 0.09 │ 784 bytes │ -└──────────────────────────────────────────────┴─────────────────┴───────────┘ -────────────────────────────────────────────────────────────────────────────── +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓ +┃ Task ┃ Duration (in s) ┃ Size ┃ +┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩ +│ task_apply_bh_to_indicators.py::task_a… │ 3.93 │ 123 MB │ +│ task_apply_bh_to_indicators.py::task_a… │ 0.09 │ 13 MB │ +│ task_replicate_results_of_bh2007.py::t… │ 0.09 │ 13 MB │ +│ task_replicate_results_of_bh2007.py::t… │ 8.99 │ 8 MB │ +│ task_merge_indicators.py::task_merge_i… │ 74.44 │ 499 MB │ +│ task_prepare_bessen_hunt_2007.py::task… │ 80.15 │ 15 MB │ +│ task_prepare_datasets.py::task_copy_fi… │ 0.11 │ 35 MB │ +│ task_prepare_datasets.py::task_copy_fi… │ 0.92 │ 35 MB │ +│ task_prepare_datasets.py::task_copy_fi… │ 0.11 │ 34 MB │ +│ task_prepare_datasets.py::task_copy_fi… │ 0.12 │ 35 MB │ +│ task_prepare_datasets.py::task_copy_fi… │ 0.12 │ 35 MB │ +│ task_prepare_datasets.py::task_copy_fi… │ 0.44 │ 143 MB │ +│ task_prepare_datasets.py::task_copy_fi… │ 0.73 │ 143 MB │ +│ task_prepare_datasets.py::task_copy_fi… │ 0.37 │ 114 MB │ +│ task_prepare_datasets.py::task_copy_fi… │ 0.62 │ 170 MB │ +│ task_visualize_distribution_of_patents… │ 17.3 │ 42 KB │ +│ task_compile_document.py::task_compile… │ 7.08 │ 539 KB │ +│ task_table_bessen_hunt_2007_and_replic… │ 0.09 │ 784 bytes │ +└─────────────────────────────────────────┴─────────────────┴───────────┘ +───────────────────────────────────────────────────────────────────────── ``` diff --git a/docs/source/_static/md/readme.md b/docs/source/_static/md/readme.md index 63229c53..55d10b44 100644 --- a/docs/source/_static/md/readme.md +++ b/docs/source/_static/md/readme.md @@ -4,7 +4,7 @@ $ pytask ──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. diff --git a/docs/source/_static/md/repeating-tasks.md b/docs/source/_static/md/repeating-tasks.md index 74baa72d..8dabb0b6 100644 --- a/docs/source/_static/md/repeating-tasks.md +++ b/docs/source/_static/md/repeating-tasks.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 10 task. @@ -23,12 +23,12 @@ Collected 10 task. │ task_repeating.py::task_create_random_data[data_9.pkl-9] │ . │ └──────────────────────────────────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ────────────╮ 10 Collected tasks 10 Succeeded (100.0%) ╰────────────────────────────────╯ -───────────────────────── Succeeded in 0.43 seconds ────────────────────────── +─────────────────────── Succeeded in 0.43 seconds ─────────────────────── ``` diff --git a/docs/source/_static/md/show-locals.md b/docs/source/_static/md/show-locals.md index 4e10652f..3cd41633 100644 --- a/docs/source/_static/md/show-locals.md +++ b/docs/source/_static/md/show-locals.md @@ -4,7 +4,7 @@ $ pytask --show-locals ──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. diff --git a/docs/source/_static/md/trace.md b/docs/source/_static/md/trace.md index dd802bd2..69ceb95f 100644 --- a/docs/source/_static/md/trace.md +++ b/docs/source/_static/md/trace.md @@ -4,7 +4,7 @@ $ pytask --trace ──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. diff --git a/docs/source/_static/md/try-first.md b/docs/source/_static/md/try-first.md index e00880e1..6c668ec8 100644 --- a/docs/source/_static/md/try-first.md +++ b/docs/source/_static/md/try-first.md @@ -3,8 +3,8 @@ ```console $ pytask -s -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 2 task. @@ -17,12 +17,12 @@ I'm second │ task_example.py::task_second │ . │ └───────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ────────────╮ 2 Collected tasks 2 Succeeded (100.0%) ╰────────────────────────────────╯ -───────────────────────── Succeeded in 0.11 seconds ────────────────────────── +─────────────────────── Succeeded in 0.11 seconds ────────────────────── ``` diff --git a/docs/source/_static/md/try-last.md b/docs/source/_static/md/try-last.md index fee1d2a1..01d187f5 100644 --- a/docs/source/_static/md/try-last.md +++ b/docs/source/_static/md/try-last.md @@ -3,8 +3,8 @@ ```console $ pytask -s -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ──────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 2 task. @@ -17,12 +17,12 @@ I'm first │ task_example.py::task_second │ . │ └───────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ────────────╮ 2 Collected tasks 2 Succeeded (100.0%) ╰────────────────────────────────╯ -───────────────────────── Succeeded in 0.11 seconds ────────────────────────── +─────────────────────── Succeeded in 0.11 seconds ─────────────────────── ``` diff --git a/docs/source/_static/md/warning.md b/docs/source/_static/md/warning.md index ef7814fb..49dbd3df 100644 --- a/docs/source/_static/md/warning.md +++ b/docs/source/_static/md/warning.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -14,25 +14,25 @@ Collected 1 task. │ task_warning.py::task_warning │ . │ └───────────────────────────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ────────────╮ 1 Collected tasks 1 Succeeded (100.0%) ╰────────────────────────────────╯ -───────────────────────── Succeeded in 0.24 seconds ────────────────────────── -╭───────────────────────────────── Warnings ─────────────────────────────────╮ -│ task_warning.py::task_warning │ -│ ...\my_project\task_warning.py:8: SettingWithCopyWarning: │ -│ A value is trying to be set on a copy of a slice from a DataFrame. │ -│ Try using .loc = value instead │ -│ │ -│ See the caveats in the documentation: │ -│ https://pandas.pydata.org/pandas-docs/stable/user_guide/ │ -│ indexing.html#returning-a-view-versus-a-copy │ -│ df[df["a"] < 5]["b"] = 1 │ -│ │ +─────────────────────── Succeeded in 0.24 seconds ────────────────────── +╭─────────────────────────────── Warnings ──────────────────────────────╮ +│ task_warning.py::task_warning │ +│ ...\my_project\task_warning.py:8: SettingWithCopyWarning: │ +│ A value is trying to be set on a copy of a slice from a DataFrame.│ +│ Try using .loc = value instead │ +│ │ +│ See the caveats in the documentation: │ +│ https://pandas.pydata.org/pandas-docs/stable/user_guide/ │ +│ indexing.html#returning-a-view-versus-a-copy │ +│ df[df["a"] < 5]["b"] = 1 │ +│ │ https://pytask-dev.rtfd.io/en/stable/how_to_guides/capture_warnings.html │ -╰────────────────────────────────────────────────────────────────────────────╯ +╰───────────────────────────────────────────────────────────────────────╯ ``` diff --git a/docs/source/_static/md/write-a-task.md b/docs/source/_static/md/write-a-task.md index 93d74ea2..7d335a61 100644 --- a/docs/source/_static/md/write-a-task.md +++ b/docs/source/_static/md/write-a-task.md @@ -3,8 +3,8 @@ ```console $ pytask -──────────────────────────── Start pytask session ──────────────────────────── -Platform: win32 -- Python 3.10.0, pytask 0.4.0, pluggy 1.3.0 +────────────────────────── Start pytask session ───────────────────────── +Platform: win32 -- Python 3.12.0, pytask 0.5.3, pluggy 1.3.0 Root: C:\Users\pytask-dev\git\my_project Collected 1 task. @@ -14,12 +14,12 @@ Collected 1 task. │ task_data_preparation.py::task_create_random_data │ . │ └───────────────────────────────────────────────────┴─────────┘ -────────────────────────────────────────────────────────────────────────────── +───────────────────────────────────────────────────────────────────────── ╭─────────── Summary ────────────╮ 1 Collected tasks 1 Succeeded (100.0%) ╰────────────────────────────────╯ -───────────────────────── Succeeded in 0.06 seconds ────────────────────────── +─────────────────────── Succeeded in 0.06 seconds ─────────────────────── ``` diff --git a/docs/source/tutorials/defining_dependencies_products.md b/docs/source/tutorials/defining_dependencies_products.md index 076f94b7..88e28c68 100644 --- a/docs/source/tutorials/defining_dependencies_products.md +++ b/docs/source/tutorials/defining_dependencies_products.md @@ -1,13 +1,12 @@ # Defining dependencies and products -Tasks have dependencies and products that you must define to run your tasks. +Define task dependencies and products to run your tasks. -Defining dependencies and products also serves another purpose. By analyzing them, -pytask determines the order to run the tasks. +Defining dependencies and products also determines task execution order. -This tutorial offers you different interfaces. If you are comfortable with type -annotations or are not afraid to try them, look at the `Python 3.10+` or `3.9` tabs. You -find a tutorial on type hints {doc}`here <../type_hints>`. +This tutorial offers you different interfaces. For type annotations, see the +`Python 3.10+` or `3.9` tabs. You find a tutorial on type hints +{doc}`here <../type_hints>`. If you want to avoid type annotations for now, look at the tab named `produces`. @@ -105,8 +104,8 @@ we will define it in `task_plot_data.py`. ````{tab-item} Python 3.10+ :sync: python310plus -To specify that the task relies on the data set `data.pkl`, you can add the path -to the function signature while choosing any argument name, here `path_to_data`. +To specify the task relies on `data.pkl`, add the path +to the function signature with any argument name (here `path_to_data`). pytask assumes that all function arguments that do not have a {class}`~pytask.Product` annotation are dependencies of the task. @@ -120,8 +119,8 @@ annotation are dependencies of the task. ````{tab-item} Python 3.9 :sync: python38plus -To specify that the task relies on the data set `data.pkl`, you can add the path -to the function signature while choosing any argument name, here `path_to_data`. +To specify the task relies on `data.pkl`, add the path +to the function signature with any argument name (here `path_to_data`). pytask assumes that all function arguments that do not have the {class}`~pytask.Product` annotation are dependencies of the task. diff --git a/docs/source/tutorials/installation.md b/docs/source/tutorials/installation.md index 0709a477..3abbda03 100644 --- a/docs/source/tutorials/installation.md +++ b/docs/source/tutorials/installation.md @@ -3,8 +3,28 @@ pytask is available on [PyPI](https://pypi.org/project/pytask) and -[Anaconda.org](https://anaconda.org/conda-forge/pytask). Install the package with one of -two commands. +[conda-forge](https://anaconda.org/conda-forge/pytask). + +## Recommended + +We recommend using modern package managers for faster and more reliable dependency +management: + +```console +$ uv add pytask +``` + +or + +```console +$ pixi add pytask +``` + +Learn more about [uv](https://docs.astral.sh/uv/) and [pixi](https://pixi.sh/). + +## Traditional + +You can also install pytask using traditional package managers: ```console $ pip install pytask @@ -24,12 +44,12 @@ some options. ```{include} ../_static/md/help-page.md ``` -To see command-specific help pages, type +For command-specific help, type ```console $ pytask --help ``` -Color support is automatically available on non-Windows platforms. On Windows, please, -use [Windows Terminal](https://github.com/microsoft/terminal), which can be installed -via the [Microsoft Store](https://aka.ms/terminal). +Non-Windows platforms have automatic color support. On Windows, use +[Windows Terminal](https://github.com/microsoft/terminal), which you can install from +the [Microsoft Store](https://aka.ms/terminal). diff --git a/docs/source/tutorials/invoking_pytask.md b/docs/source/tutorials/invoking_pytask.md index 1f3846b7..f3a5396a 100644 --- a/docs/source/tutorials/invoking_pytask.md +++ b/docs/source/tutorials/invoking_pytask.md @@ -1,6 +1,6 @@ # Invoking pytask -You can invoke pytask on the command line with +Invoke pytask from the command line with ```console $ pytask @@ -15,7 +15,7 @@ $ pytask -h | --help ## Commands -pytask has multiple commands that are listed on the main help page. +pytask has multiple commands listed on the main help page. ```{include} ../_static/md/help-page.md ``` @@ -28,7 +28,7 @@ $ pytask $ pytask build ``` -To display command-specific information, use the help flag after the command. +Display command-specific information by adding the help flag after the command. ```console $ pytask -h/--help @@ -47,10 +47,10 @@ You can also pass any number of paths of directories or modules to the program. $ pytask path/to/task_module.py path/to/folder ``` -Do not use paths to run a subset of tasks in your project. Use -{doc}`expressions ` instead. When pytask collects tasks from subpaths -of your project, it cannot infer the whole structure of dependencies and products and -might run your tasks with missing or outdated dependencies. +Don't use paths to run task subsets. Use {doc}`expressions ` instead. +When pytask collects tasks from subpaths of your project, it cannot infer the whole +structure of dependencies and products and might run your tasks with missing or outdated +dependencies. ## Options @@ -78,7 +78,7 @@ $ pytask --max-failures 2 # Stop after the second failure ### Performing a dry-run -You can do a dry run to see which tasks would be executed without executing them. +Do a dry run to see which tasks will be executed without executing them. ```{include} ../_static/md/dry-run.md ``` diff --git a/docs/source/tutorials/set_up_a_project.md b/docs/source/tutorials/set_up_a_project.md index 7d288c52..f5637627 100644 --- a/docs/source/tutorials/set_up_a_project.md +++ b/docs/source/tutorials/set_up_a_project.md @@ -1,7 +1,7 @@ # Set up a project -Assuming you want to use pytask for a more extensive project, you want to organize the -project as a Python package. This tutorial explains the minimal setup. +To use pytask for larger projects, organize the project as a Python package. This +tutorial explains the minimal setup. If you want to use pytask with a collection of scripts, you can skip this lesson and move to the next section of the tutorials. @@ -25,7 +25,7 @@ my_project └───pyproject.toml ``` -You can replicate the directory structure for your project or you start from pytask's +Replicate this directory structure for your project or start from pytask's [cookiecutter-pytask-project](https://github.com/pytask-dev/cookiecutter-pytask-project) template or any other {doc}`linked template or example project <../how_to_guides/bp_templates_and_projects>`. @@ -64,76 +64,123 @@ practice to store any outputs of the tasks in your project in a different folder Whenever you want to regenerate your project, delete the build directory and rerun pytask. -## `pyproject.toml` +## Configuration Files -The `pyproject.toml` file is the modern configuration file for most Python packages and -apps. It contains +The configuration depends on your package manager choice. Each creates different files +to manage dependencies and project metadata. -1. the configuration for our Python package. -1. pytask's configuration. +`````{tab-set} -Let us start with the configuration of the Python package, which contains general -information about the package, like its name and version, the definition of the package -folder, `src`. +````{tab-item} uv +:sync: uv -```toml -[build-system] -requires = ["setuptools", "setuptools-scm"] -build-backend = "setuptools.build_meta" +Create a `pyproject.toml` file for project configuration and dependencies: +```toml [project] name = "my_project" version = "0.1.0" +requires-python = ">=3.9" +dependencies = ["pytask"] -[tool.setuptools.package-dir] -"" = "src" - -[tool.setuptools.packages.find] -where = ["src"] -namespaces = false +[tool.pytask.ini_options] +paths = ["src/my_project"] ``` -```{seealso} -You can find more extensive information about this metadata in the documentation of -[setuptools](https://setuptools.pypa.io/en/latest/userguide/quickstart.html). -``` +uv automatically handles build system configuration and package discovery. + +```` -Alongside the package information, we include pytask's configuration under the -`[tool.pytask.ini_options]` section. We only tell pytask to look for tasks in -`src/my_project`. +````{tab-item} pixi +:sync: pixi + +Create a `pixi.toml` file for project configuration: ```toml +[project] +name = "my_project" +version = "0.1.0" +requires-python = ">=3.9" +channels = ["conda-forge"] +platforms = ["linux-64", "osx-64", "osx-arm64", "win-64"] + +[dependencies] +pytask = "*" +python = ">=3.9" + [tool.pytask.ini_options] paths = ["src/my_project"] ``` -You will learn more about the configuration later in {doc}`tutorial `. +```` -You can copy the whole content of the `pyproject.toml` here. +````{tab-item} pip +:sync: pip -
+Create a `pyproject.toml` file for project configuration: ```toml [build-system] -requires = ["setuptools", "setuptools-scm"] -build-backend = "setuptools.build_meta" +requires = ["hatchling"] +build-backend = "hatchling.build" [project] name = "my_project" version = "0.1.0" +requires-python = ">=3.9" +dependencies = ["pytask"] + +[tool.pytask.ini_options] +paths = ["src/my_project"] +``` + +Also create a `requirements.txt` file: + +```text +pytask +``` + +```` + +````{tab-item} conda/mamba +:sync: conda + +Create an `environment.yml` file that includes the editable install: + +```yaml +name: my_project +channels: + - conda-forge +dependencies: + - python>=3.9 + - pytask + - pip + - pip: + - -e . +``` -[tool.setuptools.package-dir] -"" = "src" +And a `pyproject.toml` file for project configuration: -[tool.setuptools.packages.find] -where = ["src"] -namespaces = false +```toml +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "my_project" +version = "0.1.0" +requires-python = ">=3.9" [tool.pytask.ini_options] paths = ["src/my_project"] ``` -
+```` +````` + +The `[tool.pytask.ini_options]` section tells pytask to look for tasks in +`src/my_project`. You will learn more about configuration in the +{doc}`configuration tutorial `. ## The `.pytask` directory @@ -142,23 +189,57 @@ interact with it. ## Installation -At last, you can install the package into your environment with +`````{tab-set} + +````{tab-item} uv +:sync: uv + +```console +$ uv sync +``` + +The command installs all packages. uv will ensure that all your dependencies are up-to-date. + +```` + +````{tab-item} pixi +:sync: pixi + +```console +$ pixi install +``` + +pixi automatically creates the environment and installs dependencies. pixi will ensure that all your dependencies are up-to-date. + +```` + +````{tab-item} pip +:sync: pip ```console $ pip install -e . ``` -This command will trigger an editable install of the project, which is a development -mode and it means any changes in the package's source files are immediately available in -the installed version. Again, setuptools makes -[a good job explaining it](https://setuptools.pypa.io/en/latest/userguide/development_mode.html). +This creates an editable install where changes in the package's source files are immediately available in the installed version. + +```` -```{important} -Do not forget to rerun the editable install every time after you recreate your Python -environment. +````{tab-item} conda/mamba +:sync: conda -Also, do not mix it up with the regular installation command `pip install .` because it -will likely not work. Then, paths defined with the variables `SRC` and `BLD` in -`config.py` will look for files relative to the location where your package is installed -like `/home/user/miniconda3/envs/...` and not in the folder you are working in. +```console +$ conda env create -f environment.yml +$ conda activate my_project ``` + +Or with mamba: + +```console +$ mamba env create -f environment.yml +$ mamba activate my_project +``` + +The editable install is automatically handled by the `pip: -e .` entry in `environment.yml`. + +```` +````` diff --git a/docs/source/tutorials/write_a_task.md b/docs/source/tutorials/write_a_task.md index af8f1f59..214a8dd0 100644 --- a/docs/source/tutorials/write_a_task.md +++ b/docs/source/tutorials/write_a_task.md @@ -1,10 +1,10 @@ # Write a task -Starting from the project structure in the {doc}`previous tutorial `, -you will learn how to write your first task. +Using the project structure from the {doc}`previous tutorial `, write +your first task. -The task, `task_create_random_data`, will be defined in -`src/my_project/task_data_preparation.py`, and it will generate a data set stored in +The task `task_create_random_data` is defined in +`src/my_project/task_data_preparation.py` and generates a data set stored in `bld/data.pkl`. The `task_` prefix for modules and task functions is important so that pytask @@ -46,9 +46,9 @@ The task accepts the argument `path` that points to the file where the data set stored. The path is passed to the task via the default value, `BLD / "data.pkl"`. To indicate that this file is a product we add some metadata to the argument. -Look at the type hint `Annotated[Path, Product]`. It uses the -{obj}`~typing.Annotated` syntax. The first entry is the type of the argument, -{class}`~pathlib.Path`. The second entry is {class}`~pytask.Product` that marks this +The type hint `Annotated[Path, Product]` uses +{obj}`~typing.Annotated` syntax. The first entry specifies the argument type +({class}`~pathlib.Path`), and the second entry ({class}`~pytask.Product`) marks this argument as a product. ```{literalinclude} ../../../docs_src/tutorials/write_a_task_py310.py @@ -68,9 +68,9 @@ The task accepts the argument `path` that points to the file where the data set stored. The path is passed to the task via the default value, `BLD / "data.pkl"`. To indicate that this file is a product we add some metadata to the argument. -Look at the type hint `Annotated[Path, Product]`. It uses the -{obj}`~typing.Annotated` syntax. The first entry is the type of the argument, -{class}`~pathlib.Path`. The second entry is {class}`~pytask.Product` that marks this +The type hint `Annotated[Path, Product]` uses +{obj}`~typing.Annotated` syntax. The first entry specifies the argument type +({class}`~pathlib.Path`), and the second entry ({class}`~pytask.Product`) marks this argument as a product. ```{literalinclude} ../../../docs_src/tutorials/write_a_task_py38.py diff --git a/pyproject.toml b/pyproject.toml index 042f00bd..d76c64a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,6 +61,7 @@ docs = [ "sphinx-design>=0.3", "sphinx-toolbox>=4.0.0", "sphinxext-opengraph>=0.10.0", + "sphinx-autobuild>=2024.10.3", ] plugin-list = ["httpx>=0.27.0", "tabulate[widechars]>=0.9.0", "tqdm>=4.66.3"] test = [ diff --git a/src/_pytask/build.py b/src/_pytask/build.py index 5df967e3..f2d8f7e4 100644 --- a/src/_pytask/build.py +++ b/src/_pytask/build.py @@ -325,12 +325,7 @@ def build( # noqa: C901, PLR0912, PLR0913 help="Execute a task even if it succeeded successfully before.", ) def build_command(**raw_config: Any) -> NoReturn: - """Collect tasks, execute them and report the results. - - The default command. pytask collects tasks from the given paths or the - current working directory, executes them and reports the results. - - """ + """Collect tasks, execute them and report the results.""" raw_config["command"] = "build" session = build(**raw_config) sys.exit(session.exit_code) diff --git a/src/_pytask/dag_command.py b/src/_pytask/dag_command.py index f5f7accb..3f14357b 100644 --- a/src/_pytask/dag_command.py +++ b/src/_pytask/dag_command.py @@ -81,7 +81,7 @@ def pytask_extend_command_line_interface(cli: click.Group) -> None: default=_RankDirection.TB, ) def dag(**raw_config: Any) -> int: - """Create a visualization of the project's directed acyclic graph.""" + """Create a visualization of the directed acyclic graph.""" try: pm = storage.get() config = pm.hook.pytask_configure(pm=pm, raw_config=raw_config) diff --git a/src/_pytask/profile.py b/src/_pytask/profile.py index 8785c840..5063e511 100644 --- a/src/_pytask/profile.py +++ b/src/_pytask/profile.py @@ -113,7 +113,7 @@ def _create_or_update_runtime(task_signature: str, start: float, end: float) -> help="Export the profile in the specified format.", ) def profile(**raw_config: Any) -> NoReturn: - """Show information about tasks like runtime and memory consumption of products.""" + """Show information about resource consumption.""" pm = storage.get() raw_config["command"] = "profile" diff --git a/uv.lock b/uv.lock index 86aff736..5a4bca0e 100644 --- a/uv.lock +++ b/uv.lock @@ -3453,6 +3453,7 @@ docs = [ { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-autobuild" }, { name = "sphinx-click" }, { name = "sphinx-copybutton" }, { name = "sphinx-design" }, @@ -3508,6 +3509,7 @@ docs = [ { name = "myst-nb", specifier = ">=1.2.0" }, { name = "myst-parser", specifier = ">=3.0.0" }, { name = "sphinx", specifier = ">=7.0.0" }, + { name = "sphinx-autobuild", specifier = ">=2024.10.3" }, { name = "sphinx-click", specifier = ">=6.0.0" }, { name = "sphinx-copybutton", specifier = ">=0.5.2" }, { name = "sphinx-design", specifier = ">=0.3" }, @@ -4159,6 +4161,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/31/53/136e9eca6e0b9dc0e1962e2c908fbea2e5ac000c2a2fbd9a35797958c48b/sphinx-8.2.3-py3-none-any.whl", hash = "sha256:4405915165f13521d875a8c29c8970800a0141c14cc5416a38feca4ea5d9b9c3", size = 3589741, upload-time = "2025-03-02T22:31:56.836Z" }, ] +[[package]] +name = "sphinx-autobuild" +version = "2024.10.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama" }, + { name = "sphinx", version = "7.4.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "sphinx", version = "8.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.10.*'" }, + { name = "sphinx", version = "8.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "starlette" }, + { name = "uvicorn" }, + { name = "watchfiles" }, + { name = "websockets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a5/2c/155e1de2c1ba96a72e5dba152c509a8b41e047ee5c2def9e9f0d812f8be7/sphinx_autobuild-2024.10.3.tar.gz", hash = "sha256:248150f8f333e825107b6d4b86113ab28fa51750e5f9ae63b59dc339be951fb1", size = 14023, upload-time = "2024-10-02T23:15:30.172Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/c0/eba125db38c84d3c74717008fd3cb5000b68cd7e2cbafd1349c6a38c3d3b/sphinx_autobuild-2024.10.3-py3-none-any.whl", hash = "sha256:158e16c36f9d633e613c9aaf81c19b0fc458ca78b112533b20dafcda430d60fa", size = 11908, upload-time = "2024-10-02T23:15:28.739Z" }, +] + [[package]] name = "sphinx-autodoc-typehints" version = "2.3.0" @@ -4510,6 +4531,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fb/d0/9852f70eb01f814843530c053542b72d30e9fbf74da7abb0107e71938389/standard_imghdr-3.10.14-py3-none-any.whl", hash = "sha256:cdf6883163349624dee9a81d2853a20260337c4cd41c04e99c082e01833a08e2", size = 5598, upload-time = "2024-04-21T18:54:48.587Z" }, ] +[[package]] +name = "starlette" +version = "0.47.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/d0/0332bd8a25779a0e2082b0e179805ad39afad642938b371ae0882e7f880d/starlette-0.47.0.tar.gz", hash = "sha256:1f64887e94a447fed5f23309fb6890ef23349b7e478faa7b24a851cd4eb844af", size = 2582856, upload-time = "2025-05-29T15:45:27.628Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/81/c60b35fe9674f63b38a8feafc414fca0da378a9dbd5fa1e0b8d23fcc7a9b/starlette-0.47.0-py3-none-any.whl", hash = "sha256:9d052d4933683af40ffd47c7465433570b4949dc937e20ad1d73b34e72f10c37", size = 72796, upload-time = "2025-05-29T15:45:26.305Z" }, +] + [[package]] name = "syrupy" version = "4.9.1" @@ -4698,6 +4732,101 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" }, ] +[[package]] +name = "uvicorn" +version = "0.34.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/ad/713be230bcda622eaa35c28f0d328c3675c371238470abdea52417f17a8e/uvicorn-0.34.3.tar.gz", hash = "sha256:35919a9a979d7a59334b6b10e05d77c1d0d574c50e0fc98b8b1a0f165708b55a", size = 76631, upload-time = "2025-06-01T07:48:17.531Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/0d/8adfeaa62945f90d19ddc461c55f4a50c258af7662d34b6a3d5d1f8646f6/uvicorn-0.34.3-py3-none-any.whl", hash = "sha256:16246631db62bdfbf069b0645177d6e8a77ba950cfedbfd093acef9444e4d885", size = 62431, upload-time = "2025-06-01T07:48:15.664Z" }, +] + +[[package]] +name = "watchfiles" +version = "1.0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/03/e2/8ed598c42057de7aa5d97c472254af4906ff0a59a66699d426fc9ef795d7/watchfiles-1.0.5.tar.gz", hash = "sha256:b7529b5dcc114679d43827d8c35a07c493ad6f083633d573d81c660abc5979e9", size = 94537, upload-time = "2025-04-08T10:36:26.722Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/4d/d02e6ea147bb7fff5fd109c694a95109612f419abed46548a930e7f7afa3/watchfiles-1.0.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5c40fe7dd9e5f81e0847b1ea64e1f5dd79dd61afbedb57759df06767ac719b40", size = 405632, upload-time = "2025-04-08T10:34:41.832Z" }, + { url = "https://files.pythonhosted.org/packages/60/31/9ee50e29129d53a9a92ccf1d3992751dc56fc3c8f6ee721be1c7b9c81763/watchfiles-1.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c0db396e6003d99bb2d7232c957b5f0b5634bbd1b24e381a5afcc880f7373fb", size = 395734, upload-time = "2025-04-08T10:34:44.236Z" }, + { url = "https://files.pythonhosted.org/packages/ad/8c/759176c97195306f028024f878e7f1c776bda66ccc5c68fa51e699cf8f1d/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b551d4fb482fc57d852b4541f911ba28957d051c8776e79c3b4a51eb5e2a1b11", size = 455008, upload-time = "2025-04-08T10:34:45.617Z" }, + { url = "https://files.pythonhosted.org/packages/55/1a/5e977250c795ee79a0229e3b7f5e3a1b664e4e450756a22da84d2f4979fe/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:830aa432ba5c491d52a15b51526c29e4a4b92bf4f92253787f9726fe01519487", size = 459029, upload-time = "2025-04-08T10:34:46.814Z" }, + { url = "https://files.pythonhosted.org/packages/e6/17/884cf039333605c1d6e296cf5be35fad0836953c3dfd2adb71b72f9dbcd0/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a16512051a822a416b0d477d5f8c0e67b67c1a20d9acecb0aafa3aa4d6e7d256", size = 488916, upload-time = "2025-04-08T10:34:48.571Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e0/bcb6e64b45837056c0a40f3a2db3ef51c2ced19fda38484fa7508e00632c/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe0cbc787770e52a96c6fda6726ace75be7f840cb327e1b08d7d54eadc3bc85", size = 523763, upload-time = "2025-04-08T10:34:50.268Z" }, + { url = "https://files.pythonhosted.org/packages/24/e9/f67e9199f3bb35c1837447ecf07e9830ec00ff5d35a61e08c2cd67217949/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d363152c5e16b29d66cbde8fa614f9e313e6f94a8204eaab268db52231fe5358", size = 502891, upload-time = "2025-04-08T10:34:51.419Z" }, + { url = "https://files.pythonhosted.org/packages/23/ed/a6cf815f215632f5c8065e9c41fe872025ffea35aa1f80499f86eae922db/watchfiles-1.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ee32c9a9bee4d0b7bd7cbeb53cb185cf0b622ac761efaa2eba84006c3b3a614", size = 454921, upload-time = "2025-04-08T10:34:52.67Z" }, + { url = "https://files.pythonhosted.org/packages/92/4c/e14978599b80cde8486ab5a77a821e8a982ae8e2fcb22af7b0886a033ec8/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29c7fd632ccaf5517c16a5188e36f6612d6472ccf55382db6c7fe3fcccb7f59f", size = 631422, upload-time = "2025-04-08T10:34:53.985Z" }, + { url = "https://files.pythonhosted.org/packages/b2/1a/9263e34c3458f7614b657f974f4ee61fd72f58adce8b436e16450e054efd/watchfiles-1.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e637810586e6fe380c8bc1b3910accd7f1d3a9a7262c8a78d4c8fb3ba6a2b3d", size = 625675, upload-time = "2025-04-08T10:34:55.173Z" }, + { url = "https://files.pythonhosted.org/packages/96/1f/1803a18bd6ab04a0766386a19bcfe64641381a04939efdaa95f0e3b0eb58/watchfiles-1.0.5-cp310-cp310-win32.whl", hash = "sha256:cd47d063fbeabd4c6cae1d4bcaa38f0902f8dc5ed168072874ea11d0c7afc1ff", size = 277921, upload-time = "2025-04-08T10:34:56.318Z" }, + { url = "https://files.pythonhosted.org/packages/c2/3b/29a89de074a7d6e8b4dc67c26e03d73313e4ecf0d6e97e942a65fa7c195e/watchfiles-1.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:86c0df05b47a79d80351cd179893f2f9c1b1cae49d96e8b3290c7f4bd0ca0a92", size = 291526, upload-time = "2025-04-08T10:34:57.95Z" }, + { url = "https://files.pythonhosted.org/packages/39/f4/41b591f59021786ef517e1cdc3b510383551846703e03f204827854a96f8/watchfiles-1.0.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:237f9be419e977a0f8f6b2e7b0475ababe78ff1ab06822df95d914a945eac827", size = 405336, upload-time = "2025-04-08T10:34:59.359Z" }, + { url = "https://files.pythonhosted.org/packages/ae/06/93789c135be4d6d0e4f63e96eea56dc54050b243eacc28439a26482b5235/watchfiles-1.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0da39ff917af8b27a4bdc5a97ac577552a38aac0d260a859c1517ea3dc1a7c4", size = 395977, upload-time = "2025-04-08T10:35:00.522Z" }, + { url = "https://files.pythonhosted.org/packages/d2/db/1cd89bd83728ca37054512d4d35ab69b5f12b8aa2ac9be3b0276b3bf06cc/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfcb3952350e95603f232a7a15f6c5f86c5375e46f0bd4ae70d43e3e063c13d", size = 455232, upload-time = "2025-04-08T10:35:01.698Z" }, + { url = "https://files.pythonhosted.org/packages/40/90/d8a4d44ffe960517e487c9c04f77b06b8abf05eb680bed71c82b5f2cad62/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68b2dddba7a4e6151384e252a5632efcaa9bc5d1c4b567f3cb621306b2ca9f63", size = 459151, upload-time = "2025-04-08T10:35:03.358Z" }, + { url = "https://files.pythonhosted.org/packages/6c/da/267a1546f26465dead1719caaba3ce660657f83c9d9c052ba98fb8856e13/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95cf944fcfc394c5f9de794ce581914900f82ff1f855326f25ebcf24d5397418", size = 489054, upload-time = "2025-04-08T10:35:04.561Z" }, + { url = "https://files.pythonhosted.org/packages/b1/31/33850dfd5c6efb6f27d2465cc4c6b27c5a6f5ed53c6fa63b7263cf5f60f6/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf6cd9f83d7c023b1aba15d13f705ca7b7d38675c121f3cc4a6e25bd0857ee9", size = 523955, upload-time = "2025-04-08T10:35:05.786Z" }, + { url = "https://files.pythonhosted.org/packages/09/84/b7d7b67856efb183a421f1416b44ca975cb2ea6c4544827955dfb01f7dc2/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:852de68acd6212cd6d33edf21e6f9e56e5d98c6add46f48244bd479d97c967c6", size = 502234, upload-time = "2025-04-08T10:35:07.187Z" }, + { url = "https://files.pythonhosted.org/packages/71/87/6dc5ec6882a2254cfdd8b0718b684504e737273903b65d7338efaba08b52/watchfiles-1.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5730f3aa35e646103b53389d5bc77edfbf578ab6dab2e005142b5b80a35ef25", size = 454750, upload-time = "2025-04-08T10:35:08.859Z" }, + { url = "https://files.pythonhosted.org/packages/3d/6c/3786c50213451a0ad15170d091570d4a6554976cf0df19878002fc96075a/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:18b3bd29954bc4abeeb4e9d9cf0b30227f0f206c86657674f544cb032296acd5", size = 631591, upload-time = "2025-04-08T10:35:10.64Z" }, + { url = "https://files.pythonhosted.org/packages/1b/b3/1427425ade4e359a0deacce01a47a26024b2ccdb53098f9d64d497f6684c/watchfiles-1.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ba5552a1b07c8edbf197055bc9d518b8f0d98a1c6a73a293bc0726dce068ed01", size = 625370, upload-time = "2025-04-08T10:35:12.412Z" }, + { url = "https://files.pythonhosted.org/packages/15/ba/f60e053b0b5b8145d682672024aa91370a29c5c921a88977eb565de34086/watchfiles-1.0.5-cp311-cp311-win32.whl", hash = "sha256:2f1fefb2e90e89959447bc0420fddd1e76f625784340d64a2f7d5983ef9ad246", size = 277791, upload-time = "2025-04-08T10:35:13.719Z" }, + { url = "https://files.pythonhosted.org/packages/50/ed/7603c4e164225c12c0d4e8700b64bb00e01a6c4eeea372292a3856be33a4/watchfiles-1.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:b6e76ceb1dd18c8e29c73f47d41866972e891fc4cc7ba014f487def72c1cf096", size = 291622, upload-time = "2025-04-08T10:35:15.071Z" }, + { url = "https://files.pythonhosted.org/packages/a2/c2/99bb7c96b4450e36877fde33690ded286ff555b5a5c1d925855d556968a1/watchfiles-1.0.5-cp311-cp311-win_arm64.whl", hash = "sha256:266710eb6fddc1f5e51843c70e3bebfb0f5e77cf4f27129278c70554104d19ed", size = 283699, upload-time = "2025-04-08T10:35:16.732Z" }, + { url = "https://files.pythonhosted.org/packages/2a/8c/4f0b9bdb75a1bfbd9c78fad7d8854369283f74fe7cf03eb16be77054536d/watchfiles-1.0.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5eb568c2aa6018e26da9e6c86f3ec3fd958cee7f0311b35c2630fa4217d17f2", size = 401511, upload-time = "2025-04-08T10:35:17.956Z" }, + { url = "https://files.pythonhosted.org/packages/dc/4e/7e15825def77f8bd359b6d3f379f0c9dac4eb09dd4ddd58fd7d14127179c/watchfiles-1.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a04059f4923ce4e856b4b4e5e783a70f49d9663d22a4c3b3298165996d1377f", size = 392715, upload-time = "2025-04-08T10:35:19.202Z" }, + { url = "https://files.pythonhosted.org/packages/58/65/b72fb817518728e08de5840d5d38571466c1b4a3f724d190cec909ee6f3f/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e380c89983ce6e6fe2dd1e1921b9952fb4e6da882931abd1824c092ed495dec", size = 454138, upload-time = "2025-04-08T10:35:20.586Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a4/86833fd2ea2e50ae28989f5950b5c3f91022d67092bfec08f8300d8b347b/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe43139b2c0fdc4a14d4f8d5b5d967f7a2777fd3d38ecf5b1ec669b0d7e43c21", size = 458592, upload-time = "2025-04-08T10:35:21.87Z" }, + { url = "https://files.pythonhosted.org/packages/38/7e/42cb8df8be9a37e50dd3a818816501cf7a20d635d76d6bd65aae3dbbff68/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee0822ce1b8a14fe5a066f93edd20aada932acfe348bede8aa2149f1a4489512", size = 487532, upload-time = "2025-04-08T10:35:23.143Z" }, + { url = "https://files.pythonhosted.org/packages/fc/fd/13d26721c85d7f3df6169d8b495fcac8ab0dc8f0945ebea8845de4681dab/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0dbcb1c2d8f2ab6e0a81c6699b236932bd264d4cef1ac475858d16c403de74d", size = 522865, upload-time = "2025-04-08T10:35:24.702Z" }, + { url = "https://files.pythonhosted.org/packages/a1/0d/7f9ae243c04e96c5455d111e21b09087d0eeaf9a1369e13a01c7d3d82478/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2014a2b18ad3ca53b1f6c23f8cd94a18ce930c1837bd891262c182640eb40a6", size = 499887, upload-time = "2025-04-08T10:35:25.969Z" }, + { url = "https://files.pythonhosted.org/packages/8e/0f/a257766998e26aca4b3acf2ae97dff04b57071e991a510857d3799247c67/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6ae86d5cb647bf58f9f655fcf577f713915a5d69057a0371bc257e2553234", size = 454498, upload-time = "2025-04-08T10:35:27.353Z" }, + { url = "https://files.pythonhosted.org/packages/81/79/8bf142575a03e0af9c3d5f8bcae911ee6683ae93a625d349d4ecf4c8f7df/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1a7bac2bde1d661fb31f4d4e8e539e178774b76db3c2c17c4bb3e960a5de07a2", size = 630663, upload-time = "2025-04-08T10:35:28.685Z" }, + { url = "https://files.pythonhosted.org/packages/f1/80/abe2e79f610e45c63a70d271caea90c49bbf93eb00fa947fa9b803a1d51f/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ab626da2fc1ac277bbf752446470b367f84b50295264d2d313e28dc4405d663", size = 625410, upload-time = "2025-04-08T10:35:30.42Z" }, + { url = "https://files.pythonhosted.org/packages/91/6f/bc7fbecb84a41a9069c2c6eb6319f7f7df113adf113e358c57fc1aff7ff5/watchfiles-1.0.5-cp312-cp312-win32.whl", hash = "sha256:9f4571a783914feda92018ef3901dab8caf5b029325b5fe4558c074582815249", size = 277965, upload-time = "2025-04-08T10:35:32.023Z" }, + { url = "https://files.pythonhosted.org/packages/99/a5/bf1c297ea6649ec59e935ab311f63d8af5faa8f0b86993e3282b984263e3/watchfiles-1.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:360a398c3a19672cf93527f7e8d8b60d8275119c5d900f2e184d32483117a705", size = 291693, upload-time = "2025-04-08T10:35:33.225Z" }, + { url = "https://files.pythonhosted.org/packages/7f/7b/fd01087cc21db5c47e5beae507b87965db341cce8a86f9eb12bf5219d4e0/watchfiles-1.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:1a2902ede862969077b97523987c38db28abbe09fb19866e711485d9fbf0d417", size = 283287, upload-time = "2025-04-08T10:35:34.568Z" }, + { url = "https://files.pythonhosted.org/packages/c7/62/435766874b704f39b2fecd8395a29042db2b5ec4005bd34523415e9bd2e0/watchfiles-1.0.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0b289572c33a0deae62daa57e44a25b99b783e5f7aed81b314232b3d3c81a11d", size = 401531, upload-time = "2025-04-08T10:35:35.792Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a6/e52a02c05411b9cb02823e6797ef9bbba0bfaf1bb627da1634d44d8af833/watchfiles-1.0.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a056c2f692d65bf1e99c41045e3bdcaea3cb9e6b5a53dcaf60a5f3bd95fc9763", size = 392417, upload-time = "2025-04-08T10:35:37.048Z" }, + { url = "https://files.pythonhosted.org/packages/3f/53/c4af6819770455932144e0109d4854437769672d7ad897e76e8e1673435d/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9dca99744991fc9850d18015c4f0438865414e50069670f5f7eee08340d8b40", size = 453423, upload-time = "2025-04-08T10:35:38.357Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d1/8e88df58bbbf819b8bc5cfbacd3c79e01b40261cad0fc84d1e1ebd778a07/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:894342d61d355446d02cd3988a7326af344143eb33a2fd5d38482a92072d9563", size = 458185, upload-time = "2025-04-08T10:35:39.708Z" }, + { url = "https://files.pythonhosted.org/packages/ff/70/fffaa11962dd5429e47e478a18736d4e42bec42404f5ee3b92ef1b87ad60/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab44e1580924d1ffd7b3938e02716d5ad190441965138b4aa1d1f31ea0877f04", size = 486696, upload-time = "2025-04-08T10:35:41.469Z" }, + { url = "https://files.pythonhosted.org/packages/39/db/723c0328e8b3692d53eb273797d9a08be6ffb1d16f1c0ba2bdbdc2a3852c/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6f9367b132078b2ceb8d066ff6c93a970a18c3029cea37bfd7b2d3dd2e5db8f", size = 522327, upload-time = "2025-04-08T10:35:43.289Z" }, + { url = "https://files.pythonhosted.org/packages/cd/05/9fccc43c50c39a76b68343484b9da7b12d42d0859c37c61aec018c967a32/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2e55a9b162e06e3f862fb61e399fe9f05d908d019d87bf5b496a04ef18a970a", size = 499741, upload-time = "2025-04-08T10:35:44.574Z" }, + { url = "https://files.pythonhosted.org/packages/23/14/499e90c37fa518976782b10a18b18db9f55ea73ca14641615056f8194bb3/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0125f91f70e0732a9f8ee01e49515c35d38ba48db507a50c5bdcad9503af5827", size = 453995, upload-time = "2025-04-08T10:35:46.336Z" }, + { url = "https://files.pythonhosted.org/packages/61/d9/f75d6840059320df5adecd2c687fbc18960a7f97b55c300d20f207d48aef/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:13bb21f8ba3248386337c9fa51c528868e6c34a707f729ab041c846d52a0c69a", size = 629693, upload-time = "2025-04-08T10:35:48.161Z" }, + { url = "https://files.pythonhosted.org/packages/fc/17/180ca383f5061b61406477218c55d66ec118e6c0c51f02d8142895fcf0a9/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:839ebd0df4a18c5b3c1b890145b5a3f5f64063c2a0d02b13c76d78fe5de34936", size = 624677, upload-time = "2025-04-08T10:35:49.65Z" }, + { url = "https://files.pythonhosted.org/packages/bf/15/714d6ef307f803f236d69ee9d421763707899d6298d9f3183e55e366d9af/watchfiles-1.0.5-cp313-cp313-win32.whl", hash = "sha256:4a8ec1e4e16e2d5bafc9ba82f7aaecfeec990ca7cd27e84fb6f191804ed2fcfc", size = 277804, upload-time = "2025-04-08T10:35:51.093Z" }, + { url = "https://files.pythonhosted.org/packages/a8/b4/c57b99518fadf431f3ef47a610839e46e5f8abf9814f969859d1c65c02c7/watchfiles-1.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:f436601594f15bf406518af922a89dcaab416568edb6f65c4e5bbbad1ea45c11", size = 291087, upload-time = "2025-04-08T10:35:52.458Z" }, + { url = "https://files.pythonhosted.org/packages/c5/95/94f3dd15557f5553261e407551c5e4d340e50161c55aa30812c79da6cb04/watchfiles-1.0.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2cfb371be97d4db374cba381b9f911dd35bb5f4c58faa7b8b7106c8853e5d225", size = 405686, upload-time = "2025-04-08T10:35:53.86Z" }, + { url = "https://files.pythonhosted.org/packages/f4/aa/b99e968153f8b70159ecca7b3daf46a6f46d97190bdaa3a449ad31b921d7/watchfiles-1.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a3904d88955fda461ea2531fcf6ef73584ca921415d5cfa44457a225f4a42bc1", size = 396047, upload-time = "2025-04-08T10:35:55.232Z" }, + { url = "https://files.pythonhosted.org/packages/23/cb/90d3d760ad4bc7290e313fb9236c7d60598627a25a5a72764e48d9652064/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b7a21715fb12274a71d335cff6c71fe7f676b293d322722fe708a9ec81d91f5", size = 456081, upload-time = "2025-04-08T10:35:57.102Z" }, + { url = "https://files.pythonhosted.org/packages/3e/65/79c6cebe5bcb695cdac145946ad5a09b9f66762549e82fb2d064ea960c95/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dfd6ae1c385ab481766b3c61c44aca2b3cd775f6f7c0fa93d979ddec853d29d5", size = 459838, upload-time = "2025-04-08T10:35:58.867Z" }, + { url = "https://files.pythonhosted.org/packages/3f/84/699f52632cdaa777f6df7f6f1cc02a23a75b41071b7e6765b9a412495f61/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b659576b950865fdad31fa491d31d37cf78b27113a7671d39f919828587b429b", size = 489753, upload-time = "2025-04-08T10:36:00.237Z" }, + { url = "https://files.pythonhosted.org/packages/25/68/3241f82ad414fd969de6bf3a93805682e5eb589aeab510322f2aa14462f8/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1909e0a9cd95251b15bff4261de5dd7550885bd172e3536824bf1cf6b121e200", size = 525015, upload-time = "2025-04-08T10:36:02.159Z" }, + { url = "https://files.pythonhosted.org/packages/85/c4/30d879e252f52b01660f545c193e6b81c48aac2e0eeec71263af3add905b/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:832ccc221927c860e7286c55c9b6ebcc0265d5e072f49c7f6456c7798d2b39aa", size = 503816, upload-time = "2025-04-08T10:36:03.869Z" }, + { url = "https://files.pythonhosted.org/packages/6b/7d/fa34750f6f4b1a70d96fa6b685fe2948d01e3936328ea528f182943eb373/watchfiles-1.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85fbb6102b3296926d0c62cfc9347f6237fb9400aecd0ba6bbda94cae15f2b3b", size = 456137, upload-time = "2025-04-08T10:36:05.226Z" }, + { url = "https://files.pythonhosted.org/packages/8f/0c/a1569709aaeccb1dd74b0dd304d0de29e3ea1fdf11e08c78f489628f9ebb/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:15ac96dd567ad6c71c71f7b2c658cb22b7734901546cd50a475128ab557593ca", size = 632673, upload-time = "2025-04-08T10:36:06.752Z" }, + { url = "https://files.pythonhosted.org/packages/90/b6/645eaaca11f3ac625cf3b6e008e543acf0bf2581f68b5e205a13b05618b6/watchfiles-1.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b6227351e11c57ae997d222e13f5b6f1f0700d84b8c52304e8675d33a808382", size = 626659, upload-time = "2025-04-08T10:36:08.18Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c4/e741d9b92b0a2c74b976ff78bbc9a1276b4d904c590878e8fe0ec9fecca5/watchfiles-1.0.5-cp39-cp39-win32.whl", hash = "sha256:974866e0db748ebf1eccab17862bc0f0303807ed9cda465d1324625b81293a18", size = 278471, upload-time = "2025-04-08T10:36:10.546Z" }, + { url = "https://files.pythonhosted.org/packages/50/1b/36b0cb6add99105f78931994b30bc1dd24118c0e659ab6a3ffe0dd8734d4/watchfiles-1.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:9848b21ae152fe79c10dd0197304ada8f7b586d3ebc3f27f43c506e5a52a863c", size = 292027, upload-time = "2025-04-08T10:36:11.901Z" }, + { url = "https://files.pythonhosted.org/packages/1a/03/81f9fcc3963b3fc415cd4b0b2b39ee8cc136c42fb10a36acf38745e9d283/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f59b870db1f1ae5a9ac28245707d955c8721dd6565e7f411024fa374b5362d1d", size = 405947, upload-time = "2025-04-08T10:36:13.721Z" }, + { url = "https://files.pythonhosted.org/packages/54/97/8c4213a852feb64807ec1d380f42d4fc8bfaef896bdbd94318f8fd7f3e4e/watchfiles-1.0.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9475b0093767e1475095f2aeb1d219fb9664081d403d1dff81342df8cd707034", size = 397276, upload-time = "2025-04-08T10:36:15.131Z" }, + { url = "https://files.pythonhosted.org/packages/78/12/d4464d19860cb9672efa45eec1b08f8472c478ed67dcd30647c51ada7aef/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc533aa50664ebd6c628b2f30591956519462f5d27f951ed03d6c82b2dfd9965", size = 455550, upload-time = "2025-04-08T10:36:16.635Z" }, + { url = "https://files.pythonhosted.org/packages/90/fb/b07bcdf1034d8edeaef4c22f3e9e3157d37c5071b5f9492ffdfa4ad4bed7/watchfiles-1.0.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed1cd825158dcaae36acce7b2db33dcbfd12b30c34317a88b8ed80f0541cc57", size = 455542, upload-time = "2025-04-08T10:36:18.655Z" }, + { url = "https://files.pythonhosted.org/packages/5b/84/7b69282c0df2bf2dff4e50be2c54669cddf219a5a5fb077891c00c00e5c8/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:554389562c29c2c182e3908b149095051f81d28c2fec79ad6c8997d7d63e0009", size = 405783, upload-time = "2025-04-08T10:36:20.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ae/03fca0545d99b7ea21df49bead7b51e7dca9ce3b45bb6d34530aa18c16a2/watchfiles-1.0.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a74add8d7727e6404d5dc4dcd7fac65d4d82f95928bbee0cf5414c900e86773e", size = 397133, upload-time = "2025-04-08T10:36:22.439Z" }, + { url = "https://files.pythonhosted.org/packages/1a/07/c2b6390003e933b2e187a3f7070c00bd87da8a58d6f2393e039b06a88c2e/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb1489f25b051a89fae574505cc26360c8e95e227a9500182a7fe0afcc500ce0", size = 456198, upload-time = "2025-04-08T10:36:23.884Z" }, + { url = "https://files.pythonhosted.org/packages/46/d3/ecc62cbd7054f0812f3a7ca7c1c9f7ba99ba45efcfc8297a9fcd2c87b31c/watchfiles-1.0.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0901429650652d3f0da90bad42bdafc1f9143ff3605633c455c999a2d786cac", size = 456511, upload-time = "2025-04-08T10:36:25.42Z" }, +] + [[package]] name = "wcwidth" version = "0.2.13" @@ -4716,6 +4845,82 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, ] +[[package]] +name = "websockets" +version = "15.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016, upload-time = "2025-03-05T20:03:41.606Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/da/6462a9f510c0c49837bbc9345aca92d767a56c1fb2939e1579df1e1cdcf7/websockets-15.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d63efaa0cd96cf0c5fe4d581521d9fa87744540d4bc999ae6e08595a1014b45b", size = 175423, upload-time = "2025-03-05T20:01:35.363Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9f/9d11c1a4eb046a9e106483b9ff69bce7ac880443f00e5ce64261b47b07e7/websockets-15.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ac60e3b188ec7574cb761b08d50fcedf9d77f1530352db4eef1707fe9dee7205", size = 173080, upload-time = "2025-03-05T20:01:37.304Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4f/b462242432d93ea45f297b6179c7333dd0402b855a912a04e7fc61c0d71f/websockets-15.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5756779642579d902eed757b21b0164cd6fe338506a8083eb58af5c372e39d9a", size = 173329, upload-time = "2025-03-05T20:01:39.668Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0c/6afa1f4644d7ed50284ac59cc70ef8abd44ccf7d45850d989ea7310538d0/websockets-15.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdfe3e2a29e4db3659dbd5bbf04560cea53dd9610273917799f1cde46aa725e", size = 182312, upload-time = "2025-03-05T20:01:41.815Z" }, + { url = "https://files.pythonhosted.org/packages/dd/d4/ffc8bd1350b229ca7a4db2a3e1c482cf87cea1baccd0ef3e72bc720caeec/websockets-15.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c2529b320eb9e35af0fa3016c187dffb84a3ecc572bcee7c3ce302bfeba52bf", size = 181319, upload-time = "2025-03-05T20:01:43.967Z" }, + { url = "https://files.pythonhosted.org/packages/97/3a/5323a6bb94917af13bbb34009fac01e55c51dfde354f63692bf2533ffbc2/websockets-15.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac1e5c9054fe23226fb11e05a6e630837f074174c4c2f0fe442996112a6de4fb", size = 181631, upload-time = "2025-03-05T20:01:46.104Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cc/1aeb0f7cee59ef065724041bb7ed667b6ab1eeffe5141696cccec2687b66/websockets-15.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5df592cd503496351d6dc14f7cdad49f268d8e618f80dce0cd5a36b93c3fc08d", size = 182016, upload-time = "2025-03-05T20:01:47.603Z" }, + { url = "https://files.pythonhosted.org/packages/79/f9/c86f8f7af208e4161a7f7e02774e9d0a81c632ae76db2ff22549e1718a51/websockets-15.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0a34631031a8f05657e8e90903e656959234f3a04552259458aac0b0f9ae6fd9", size = 181426, upload-time = "2025-03-05T20:01:48.949Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b9/828b0bc6753db905b91df6ae477c0b14a141090df64fb17f8a9d7e3516cf/websockets-15.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3d00075aa65772e7ce9e990cab3ff1de702aa09be3940d1dc88d5abf1ab8a09c", size = 181360, upload-time = "2025-03-05T20:01:50.938Z" }, + { url = "https://files.pythonhosted.org/packages/89/fb/250f5533ec468ba6327055b7d98b9df056fb1ce623b8b6aaafb30b55d02e/websockets-15.0.1-cp310-cp310-win32.whl", hash = "sha256:1234d4ef35db82f5446dca8e35a7da7964d02c127b095e172e54397fb6a6c256", size = 176388, upload-time = "2025-03-05T20:01:52.213Z" }, + { url = "https://files.pythonhosted.org/packages/1c/46/aca7082012768bb98e5608f01658ff3ac8437e563eca41cf068bd5849a5e/websockets-15.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:39c1fec2c11dc8d89bba6b2bf1556af381611a173ac2b511cf7231622058af41", size = 176830, upload-time = "2025-03-05T20:01:53.922Z" }, + { url = "https://files.pythonhosted.org/packages/9f/32/18fcd5919c293a398db67443acd33fde142f283853076049824fc58e6f75/websockets-15.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:823c248b690b2fd9303ba00c4f66cd5e2d8c3ba4aa968b2779be9532a4dad431", size = 175423, upload-time = "2025-03-05T20:01:56.276Z" }, + { url = "https://files.pythonhosted.org/packages/76/70/ba1ad96b07869275ef42e2ce21f07a5b0148936688c2baf7e4a1f60d5058/websockets-15.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678999709e68425ae2593acf2e3ebcbcf2e69885a5ee78f9eb80e6e371f1bf57", size = 173082, upload-time = "2025-03-05T20:01:57.563Z" }, + { url = "https://files.pythonhosted.org/packages/86/f2/10b55821dd40eb696ce4704a87d57774696f9451108cff0d2824c97e0f97/websockets-15.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d50fd1ee42388dcfb2b3676132c78116490976f1300da28eb629272d5d93e905", size = 173330, upload-time = "2025-03-05T20:01:59.063Z" }, + { url = "https://files.pythonhosted.org/packages/a5/90/1c37ae8b8a113d3daf1065222b6af61cc44102da95388ac0018fcb7d93d9/websockets-15.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d99e5546bf73dbad5bf3547174cd6cb8ba7273062a23808ffea025ecb1cf8562", size = 182878, upload-time = "2025-03-05T20:02:00.305Z" }, + { url = "https://files.pythonhosted.org/packages/8e/8d/96e8e288b2a41dffafb78e8904ea7367ee4f891dafc2ab8d87e2124cb3d3/websockets-15.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66dd88c918e3287efc22409d426c8f729688d89a0c587c88971a0faa2c2f3792", size = 181883, upload-time = "2025-03-05T20:02:03.148Z" }, + { url = "https://files.pythonhosted.org/packages/93/1f/5d6dbf551766308f6f50f8baf8e9860be6182911e8106da7a7f73785f4c4/websockets-15.0.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dd8327c795b3e3f219760fa603dcae1dcc148172290a8ab15158cf85a953413", size = 182252, upload-time = "2025-03-05T20:02:05.29Z" }, + { url = "https://files.pythonhosted.org/packages/d4/78/2d4fed9123e6620cbf1706c0de8a1632e1a28e7774d94346d7de1bba2ca3/websockets-15.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8fdc51055e6ff4adeb88d58a11042ec9a5eae317a0a53d12c062c8a8865909e8", size = 182521, upload-time = "2025-03-05T20:02:07.458Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3b/66d4c1b444dd1a9823c4a81f50231b921bab54eee2f69e70319b4e21f1ca/websockets-15.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:693f0192126df6c2327cce3baa7c06f2a117575e32ab2308f7f8216c29d9e2e3", size = 181958, upload-time = "2025-03-05T20:02:09.842Z" }, + { url = "https://files.pythonhosted.org/packages/08/ff/e9eed2ee5fed6f76fdd6032ca5cd38c57ca9661430bb3d5fb2872dc8703c/websockets-15.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:54479983bd5fb469c38f2f5c7e3a24f9a4e70594cd68cd1fa6b9340dadaff7cf", size = 181918, upload-time = "2025-03-05T20:02:11.968Z" }, + { url = "https://files.pythonhosted.org/packages/d8/75/994634a49b7e12532be6a42103597b71098fd25900f7437d6055ed39930a/websockets-15.0.1-cp311-cp311-win32.whl", hash = "sha256:16b6c1b3e57799b9d38427dda63edcbe4926352c47cf88588c0be4ace18dac85", size = 176388, upload-time = "2025-03-05T20:02:13.32Z" }, + { url = "https://files.pythonhosted.org/packages/98/93/e36c73f78400a65f5e236cd376713c34182e6663f6889cd45a4a04d8f203/websockets-15.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:27ccee0071a0e75d22cb35849b1db43f2ecd3e161041ac1ee9d2352ddf72f065", size = 176828, upload-time = "2025-03-05T20:02:14.585Z" }, + { url = "https://files.pythonhosted.org/packages/51/6b/4545a0d843594f5d0771e86463606a3988b5a09ca5123136f8a76580dd63/websockets-15.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3e90baa811a5d73f3ca0bcbf32064d663ed81318ab225ee4f427ad4e26e5aff3", size = 175437, upload-time = "2025-03-05T20:02:16.706Z" }, + { url = "https://files.pythonhosted.org/packages/f4/71/809a0f5f6a06522af902e0f2ea2757f71ead94610010cf570ab5c98e99ed/websockets-15.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:592f1a9fe869c778694f0aa806ba0374e97648ab57936f092fd9d87f8bc03665", size = 173096, upload-time = "2025-03-05T20:02:18.832Z" }, + { url = "https://files.pythonhosted.org/packages/3d/69/1a681dd6f02180916f116894181eab8b2e25b31e484c5d0eae637ec01f7c/websockets-15.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0701bc3cfcb9164d04a14b149fd74be7347a530ad3bbf15ab2c678a2cd3dd9a2", size = 173332, upload-time = "2025-03-05T20:02:20.187Z" }, + { url = "https://files.pythonhosted.org/packages/a6/02/0073b3952f5bce97eafbb35757f8d0d54812b6174ed8dd952aa08429bcc3/websockets-15.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8b56bdcdb4505c8078cb6c7157d9811a85790f2f2b3632c7d1462ab5783d215", size = 183152, upload-time = "2025-03-05T20:02:22.286Z" }, + { url = "https://files.pythonhosted.org/packages/74/45/c205c8480eafd114b428284840da0b1be9ffd0e4f87338dc95dc6ff961a1/websockets-15.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0af68c55afbd5f07986df82831c7bff04846928ea8d1fd7f30052638788bc9b5", size = 182096, upload-time = "2025-03-05T20:02:24.368Z" }, + { url = "https://files.pythonhosted.org/packages/14/8f/aa61f528fba38578ec553c145857a181384c72b98156f858ca5c8e82d9d3/websockets-15.0.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dee438fed052b52e4f98f76c5790513235efaa1ef7f3f2192c392cd7c91b65", size = 182523, upload-time = "2025-03-05T20:02:25.669Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6d/0267396610add5bc0d0d3e77f546d4cd287200804fe02323797de77dbce9/websockets-15.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d5f6b181bb38171a8ad1d6aa58a67a6aa9d4b38d0f8c5f496b9e42561dfc62fe", size = 182790, upload-time = "2025-03-05T20:02:26.99Z" }, + { url = "https://files.pythonhosted.org/packages/02/05/c68c5adbf679cf610ae2f74a9b871ae84564462955d991178f95a1ddb7dd/websockets-15.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:5d54b09eba2bada6011aea5375542a157637b91029687eb4fdb2dab11059c1b4", size = 182165, upload-time = "2025-03-05T20:02:30.291Z" }, + { url = "https://files.pythonhosted.org/packages/29/93/bb672df7b2f5faac89761cb5fa34f5cec45a4026c383a4b5761c6cea5c16/websockets-15.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3be571a8b5afed347da347bfcf27ba12b069d9d7f42cb8c7028b5e98bbb12597", size = 182160, upload-time = "2025-03-05T20:02:31.634Z" }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395, upload-time = "2025-03-05T20:02:33.017Z" }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841, upload-time = "2025-03-05T20:02:34.498Z" }, + { url = "https://files.pythonhosted.org/packages/cb/9f/51f0cf64471a9d2b4d0fc6c534f323b664e7095640c34562f5182e5a7195/websockets-15.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee443ef070bb3b6ed74514f5efaa37a252af57c90eb33b956d35c8e9c10a1931", size = 175440, upload-time = "2025-03-05T20:02:36.695Z" }, + { url = "https://files.pythonhosted.org/packages/8a/05/aa116ec9943c718905997412c5989f7ed671bc0188ee2ba89520e8765d7b/websockets-15.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5a939de6b7b4e18ca683218320fc67ea886038265fd1ed30173f5ce3f8e85675", size = 173098, upload-time = "2025-03-05T20:02:37.985Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0b/33cef55ff24f2d92924923c99926dcce78e7bd922d649467f0eda8368923/websockets-15.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:746ee8dba912cd6fc889a8147168991d50ed70447bf18bcda7039f7d2e3d9151", size = 173329, upload-time = "2025-03-05T20:02:39.298Z" }, + { url = "https://files.pythonhosted.org/packages/31/1d/063b25dcc01faa8fada1469bdf769de3768b7044eac9d41f734fd7b6ad6d/websockets-15.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:595b6c3969023ecf9041b2936ac3827e4623bfa3ccf007575f04c5a6aa318c22", size = 183111, upload-time = "2025-03-05T20:02:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/93/53/9a87ee494a51bf63e4ec9241c1ccc4f7c2f45fff85d5bde2ff74fcb68b9e/websockets-15.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c714d2fc58b5ca3e285461a4cc0c9a66bd0e24c5da9911e30158286c9b5be7f", size = 182054, upload-time = "2025-03-05T20:02:41.926Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b2/83a6ddf56cdcbad4e3d841fcc55d6ba7d19aeb89c50f24dd7e859ec0805f/websockets-15.0.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f3c1e2ab208db911594ae5b4f79addeb3501604a165019dd221c0bdcabe4db8", size = 182496, upload-time = "2025-03-05T20:02:43.304Z" }, + { url = "https://files.pythonhosted.org/packages/98/41/e7038944ed0abf34c45aa4635ba28136f06052e08fc2168520bb8b25149f/websockets-15.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:229cf1d3ca6c1804400b0a9790dc66528e08a6a1feec0d5040e8b9eb14422375", size = 182829, upload-time = "2025-03-05T20:02:48.812Z" }, + { url = "https://files.pythonhosted.org/packages/e0/17/de15b6158680c7623c6ef0db361da965ab25d813ae54fcfeae2e5b9ef910/websockets-15.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:756c56e867a90fb00177d530dca4b097dd753cde348448a1012ed6c5131f8b7d", size = 182217, upload-time = "2025-03-05T20:02:50.14Z" }, + { url = "https://files.pythonhosted.org/packages/33/2b/1f168cb6041853eef0362fb9554c3824367c5560cbdaad89ac40f8c2edfc/websockets-15.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:558d023b3df0bffe50a04e710bc87742de35060580a293c2a984299ed83bc4e4", size = 182195, upload-time = "2025-03-05T20:02:51.561Z" }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393, upload-time = "2025-03-05T20:02:53.814Z" }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837, upload-time = "2025-03-05T20:02:55.237Z" }, + { url = "https://files.pythonhosted.org/packages/36/db/3fff0bcbe339a6fa6a3b9e3fbc2bfb321ec2f4cd233692272c5a8d6cf801/websockets-15.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f4c04ead5aed67c8a1a20491d54cdfba5884507a48dd798ecaf13c74c4489f5", size = 175424, upload-time = "2025-03-05T20:02:56.505Z" }, + { url = "https://files.pythonhosted.org/packages/46/e6/519054c2f477def4165b0ec060ad664ed174e140b0d1cbb9fafa4a54f6db/websockets-15.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abdc0c6c8c648b4805c5eacd131910d2a7f6455dfd3becab248ef108e89ab16a", size = 173077, upload-time = "2025-03-05T20:02:58.37Z" }, + { url = "https://files.pythonhosted.org/packages/1a/21/c0712e382df64c93a0d16449ecbf87b647163485ca1cc3f6cbadb36d2b03/websockets-15.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a625e06551975f4b7ea7102bc43895b90742746797e2e14b70ed61c43a90f09b", size = 173324, upload-time = "2025-03-05T20:02:59.773Z" }, + { url = "https://files.pythonhosted.org/packages/1c/cb/51ba82e59b3a664df54beed8ad95517c1b4dc1a913730e7a7db778f21291/websockets-15.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d591f8de75824cbb7acad4e05d2d710484f15f29d4a915092675ad3456f11770", size = 182094, upload-time = "2025-03-05T20:03:01.827Z" }, + { url = "https://files.pythonhosted.org/packages/fb/0f/bf3788c03fec679bcdaef787518dbe60d12fe5615a544a6d4cf82f045193/websockets-15.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47819cea040f31d670cc8d324bb6435c6f133b8c7a19ec3d61634e62f8d8f9eb", size = 181094, upload-time = "2025-03-05T20:03:03.123Z" }, + { url = "https://files.pythonhosted.org/packages/5e/da/9fb8c21edbc719b66763a571afbaf206cb6d3736d28255a46fc2fe20f902/websockets-15.0.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac017dd64572e5c3bd01939121e4d16cf30e5d7e110a119399cf3133b63ad054", size = 181397, upload-time = "2025-03-05T20:03:04.443Z" }, + { url = "https://files.pythonhosted.org/packages/2e/65/65f379525a2719e91d9d90c38fe8b8bc62bd3c702ac651b7278609b696c4/websockets-15.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4a9fac8e469d04ce6c25bb2610dc535235bd4aa14996b4e6dbebf5e007eba5ee", size = 181794, upload-time = "2025-03-05T20:03:06.708Z" }, + { url = "https://files.pythonhosted.org/packages/d9/26/31ac2d08f8e9304d81a1a7ed2851c0300f636019a57cbaa91342015c72cc/websockets-15.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363c6f671b761efcb30608d24925a382497c12c506b51661883c3e22337265ed", size = 181194, upload-time = "2025-03-05T20:03:08.844Z" }, + { url = "https://files.pythonhosted.org/packages/98/72/1090de20d6c91994cd4b357c3f75a4f25ee231b63e03adea89671cc12a3f/websockets-15.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2034693ad3097d5355bfdacfffcbd3ef5694f9718ab7f29c29689a9eae841880", size = 181164, upload-time = "2025-03-05T20:03:10.242Z" }, + { url = "https://files.pythonhosted.org/packages/2d/37/098f2e1c103ae8ed79b0e77f08d83b0ec0b241cf4b7f2f10edd0126472e1/websockets-15.0.1-cp39-cp39-win32.whl", hash = "sha256:3b1ac0d3e594bf121308112697cf4b32be538fb1444468fb0a6ae4feebc83411", size = 176381, upload-time = "2025-03-05T20:03:12.77Z" }, + { url = "https://files.pythonhosted.org/packages/75/8b/a32978a3ab42cebb2ebdd5b05df0696a09f4d436ce69def11893afa301f0/websockets-15.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7643a03db5c95c799b89b31c036d5f27eeb4d259c798e878d6937d71832b1e4", size = 176841, upload-time = "2025-03-05T20:03:14.367Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/d40f779fa16f74d3468357197af8d6ad07e7c5a27ea1ca74ceb38986f77a/websockets-15.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0c9e74d766f2818bb95f84c25be4dea09841ac0f734d1966f415e4edfc4ef1c3", size = 173109, upload-time = "2025-03-05T20:03:17.769Z" }, + { url = "https://files.pythonhosted.org/packages/bc/cd/5b887b8585a593073fd92f7c23ecd3985cd2c3175025a91b0d69b0551372/websockets-15.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1009ee0c7739c08a0cd59de430d6de452a55e42d6b522de7aa15e6f67db0b8e1", size = 173343, upload-time = "2025-03-05T20:03:19.094Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ae/d34f7556890341e900a95acf4886833646306269f899d58ad62f588bf410/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d1f20b1c7a2fa82367e04982e708723ba0e7b8d43aa643d3dcd404d74f1475", size = 174599, upload-time = "2025-03-05T20:03:21.1Z" }, + { url = "https://files.pythonhosted.org/packages/71/e6/5fd43993a87db364ec60fc1d608273a1a465c0caba69176dd160e197ce42/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f29d80eb9a9263b8d109135351caf568cc3f80b9928bccde535c235de55c22d9", size = 174207, upload-time = "2025-03-05T20:03:23.221Z" }, + { url = "https://files.pythonhosted.org/packages/2b/fb/c492d6daa5ec067c2988ac80c61359ace5c4c674c532985ac5a123436cec/websockets-15.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b359ed09954d7c18bbc1680f380c7301f92c60bf924171629c5db97febb12f04", size = 174155, upload-time = "2025-03-05T20:03:25.321Z" }, + { url = "https://files.pythonhosted.org/packages/68/a1/dcb68430b1d00b698ae7a7e0194433bce4f07ded185f0ee5fb21e2a2e91e/websockets-15.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:cad21560da69f4ce7658ca2cb83138fb4cf695a2ba3e475e0559e05991aa8122", size = 176884, upload-time = "2025-03-05T20:03:27.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/48/4b67623bac4d79beb3a6bb27b803ba75c1bdedc06bd827e465803690a4b2/websockets-15.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7f493881579c90fc262d9cdbaa05a6b54b3811c2f300766748db79f098db9940", size = 173106, upload-time = "2025-03-05T20:03:29.404Z" }, + { url = "https://files.pythonhosted.org/packages/ed/f0/adb07514a49fe5728192764e04295be78859e4a537ab8fcc518a3dbb3281/websockets-15.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:47b099e1f4fbc95b701b6e85768e1fcdaf1630f3cbe4765fa216596f12310e2e", size = 173339, upload-time = "2025-03-05T20:03:30.755Z" }, + { url = "https://files.pythonhosted.org/packages/87/28/bd23c6344b18fb43df40d0700f6d3fffcd7cef14a6995b4f976978b52e62/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67f2b6de947f8c757db2db9c71527933ad0019737ec374a8a6be9a956786aaf9", size = 174597, upload-time = "2025-03-05T20:03:32.247Z" }, + { url = "https://files.pythonhosted.org/packages/6d/79/ca288495863d0f23a60f546f0905ae8f3ed467ad87f8b6aceb65f4c013e4/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d08eb4c2b7d6c41da6ca0600c077e93f5adcfd979cd777d747e9ee624556da4b", size = 174205, upload-time = "2025-03-05T20:03:33.731Z" }, + { url = "https://files.pythonhosted.org/packages/04/e4/120ff3180b0872b1fe6637f6f995bcb009fb5c87d597c1fc21456f50c848/websockets-15.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b826973a4a2ae47ba357e4e82fa44a463b8f168e1ca775ac64521442b19e87f", size = 174150, upload-time = "2025-03-05T20:03:35.757Z" }, + { url = "https://files.pythonhosted.org/packages/cb/c3/30e2f9c539b8da8b1d76f64012f3b19253271a63413b2d3adb94b143407f/websockets-15.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:21c1fa28a6a7e3cbdc171c694398b6df4744613ce9b36b1a498e816787e28123", size = 176877, upload-time = "2025-03-05T20:03:37.199Z" }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +] + [[package]] name = "wheel" version = "0.45.1"