From 1e1af05530ad89f1f9e20b3d499cdc361b684f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Tue, 24 Dec 2024 15:29:25 +0100 Subject: [PATCH 01/90] Update pyproject description --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 212569cb..18592ef9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "judge0" -version = "0.0.3" -description = "The official Python library for Judge0." +version = "0.0.4-dev" +description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.9" authors = [{ name = "Judge0", email = "contact@judge0.com" }] From 79aac51bd56aec693206a4c630b1441a214ffb33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Thu, 26 Dec 2024 00:04:34 +0100 Subject: [PATCH 02/90] Add .python-version to gitignore. --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 82f92755..13480660 100644 --- a/.gitignore +++ b/.gitignore @@ -85,7 +85,7 @@ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: -# .python-version +.python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. From 49f61a8d85224f5b7f68dfc4979379844a3ed54d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sat, 28 Dec 2024 18:47:43 +0100 Subject: [PATCH 03/90] Add pygments style to docs conf. --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index a9ae07cb..49c7ab8a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -41,6 +41,7 @@ "versioning.html", ], } +pygments_style = "sphinx" sys.path.insert(0, os.path.abspath("../../src/")) # Adjust as needed From f87358f99b40aa258a0926d7952ff0099cba802d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sat, 28 Dec 2024 18:50:58 +0100 Subject: [PATCH 04/90] Change permalinks in docs headers. --- docs/source/conf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 49c7ab8a..83e54e45 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -10,6 +10,8 @@ import os import sys +from sphinxawesome_theme.postprocess import Icons + project = "Judge0 Python SDK" copyright = "2024, Judge0" author = "Judge0" @@ -45,6 +47,8 @@ sys.path.insert(0, os.path.abspath("../../src/")) # Adjust as needed +# -- Awesome theme config -- +html_permalinks_icon = Icons.permalinks_icon autodoc_default_options = { "members": True, From dac233da696304b9125dd1811e308fea618a8d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sat, 28 Dec 2024 19:16:04 +0100 Subject: [PATCH 05/90] Add reverse version sorting. --- docs/source/_templates/versioning.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/source/_templates/versioning.html b/docs/source/_templates/versioning.html index ef74ed44..1b8de300 100644 --- a/docs/source/_templates/versioning.html +++ b/docs/source/_templates/versioning.html @@ -1,7 +1,10 @@ {% if versions %} +{% set master_version = versions | selectattr('name', 'equalto', 'master') | list %} +{% set other_versions = versions | rejectattr('name', 'equalto', 'master') | sort(attribute='name', reverse=true) %} +{% set sorted_versions = master_version + other_versions %}

{{ _('Versions') }}

    - {%- for item in versions %} + {%- for item in sorted_versions %}
  • {{ item.name }}
  • {%- endfor %}
From 97aa8e30337bcee1ebccde395b5fc447c1a21b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sat, 28 Dec 2024 19:41:50 +0100 Subject: [PATCH 06/90] Update workflow to point the index to latest release. --- .github/workflows/docs.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4b2aa464..6a6a8e9a 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -34,12 +34,22 @@ jobs: - name: Build documentation run: sphinx-multiversion docs/source docs/build/html --keep-going --no-color + - name: Get the latest tag + run: | + # Fetch all tags + git fetch --tags + # Get the latest tag + latest_tag=$(git tag --sort=-creatordate | head -n 1) + # Remove the 'v' prefix if it exists + latest_tag_no_v=${latest_tag#v} + echo "LATEST_RELEASE=$latest_tag_no_v" >> $GITHUB_ENV + - name: Generate index.html for judge0.github.io/judge0-python. run: | echo ' - + ' > docs/build/html/index.html From dfaf7d55efe3cf6cc6a66cefdad9bcc703cc9e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sat, 28 Dec 2024 19:48:14 +0100 Subject: [PATCH 07/90] Update with explicitly set env variable in the step. --- .github/workflows/docs.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6a6a8e9a..11f7c0cb 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -49,9 +49,11 @@ jobs: echo ' - + ' > docs/build/html/index.html + env: + latest_release: ${{ env.LATEST_RELEASE }} - name: Upload artifacts uses: actions/upload-artifact@v4 From 6c3b8b77a15fcefa8cfecf1712e850892a5ed89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sat, 28 Dec 2024 19:49:37 +0100 Subject: [PATCH 08/90] Fix unexpected EOF. --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 11f7c0cb..1c954670 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -49,7 +49,7 @@ jobs: echo ' - + ' > docs/build/html/index.html env: From 335ee1ba91f167eb4b6748dfa65d495d7d0ee2ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sat, 28 Dec 2024 19:58:03 +0100 Subject: [PATCH 09/90] Don't remove the v from the tag when building index for docs. --- .github/workflows/docs.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 1c954670..4a70709c 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -40,9 +40,7 @@ jobs: git fetch --tags # Get the latest tag latest_tag=$(git tag --sort=-creatordate | head -n 1) - # Remove the 'v' prefix if it exists - latest_tag_no_v=${latest_tag#v} - echo "LATEST_RELEASE=$latest_tag_no_v" >> $GITHUB_ENV + echo "LATEST_RELEASE=$latest_tag" >> $GITHUB_ENV - name: Generate index.html for judge0.github.io/judge0-python. run: | From 9a7519817d176dba6f5b49458d1ffa9395153d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Mon, 30 Dec 2024 12:06:46 +0100 Subject: [PATCH 10/90] Add text to Getting Involved section on index page. --- docs/source/index.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 3510578a..257efdaf 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -34,7 +34,20 @@ Examples. Getting Involved ================ -TODO +Getting involved in any open-source project is simple and rewarding, with +multiple ways to contribute to its growth and success. You can help by: + +1. `reporting bugs `_ by + creating a detailed issue describing the problem, along with any relevant code or + steps to reproduce it, so it can be addressed effectively, +2. creating a `pull request `_ for + an existing issue; we welcome improvements, fixes, and new features that align + with the project's goals, and +3. you can show support by starring the `repository `_, + letting us know that we’re doing a good job and helping us gain visibility within + the open-source community. + +Every contribution, big or small, is valuable! .. toctree:: :caption: API From 334d6fa2d1e92b2dd7f6309e78ce50a0d86feb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Mon, 30 Dec 2024 12:44:10 +0100 Subject: [PATCH 11/90] Add retry module to docs. --- docs/source/api/retry.rst | 6 +++++ docs/source/index.rst | 1 + pyproject.toml | 4 +++- src/judge0/retry.py | 50 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 docs/source/api/retry.rst diff --git a/docs/source/api/retry.rst b/docs/source/api/retry.rst new file mode 100644 index 00000000..22977dc1 --- /dev/null +++ b/docs/source/api/retry.rst @@ -0,0 +1,6 @@ +Retry Module +============ + +.. automodule:: judge0.retry + :members: + :member-order: bysource \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index 257efdaf..2c50fdfb 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -59,6 +59,7 @@ Every contribution, big or small, is valuable! api/submission api/clients api/types + api/retry .. toctree:: :caption: Getting Involved diff --git a/pyproject.toml b/pyproject.toml index 18592ef9..edfcfdd7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,6 @@ test = [ docs = ["sphinx==7.4.7"] [tool.flake8] -docstring-convention = "numpy" extend-ignore = [ 'D100', 'D101', @@ -56,8 +55,11 @@ extend-ignore = [ 'D103', 'D104', 'D105', + 'D107', 'D205', + "D209", 'D400', 'F821', ] +docstring-convention = "numpy" max-line-length = 88 diff --git a/src/judge0/retry.py b/src/judge0/retry.py index 20b42ef7..f4bff5b1 100644 --- a/src/judge0/retry.py +++ b/src/judge0/retry.py @@ -3,62 +3,106 @@ class RetryStrategy(ABC): + """Abstract base class that defines the interface for any retry strategy. + + See :obj:`MaxRetries`, :obj:`MaxWaitTime`, and :obj:`RegularPeriodRetry` for + example implementations. + """ + @abstractmethod def is_done(self) -> bool: + """Check if the retry strategy has exhausted its retries.""" pass @abstractmethod def wait(self) -> None: + """Delay implementation before the next retry attempt.""" pass + @abstractmethod def step(self) -> None: + """Update internal attributes of the retry strategy.""" pass class MaxRetries(RetryStrategy): """Check for submissions status every 100 ms and retry a maximum of - `max_retries` times.""" + `max_retries` times. + + Parameters + ---------- + max_retries : int + Max number of retries. + """ def __init__(self, max_retries: int = 20): + if max_retries < 1: + raise ValueError("max_retries must be at least 1.") self.n_retries = 0 self.max_retries = max_retries def step(self): + """Increment the number of retries by one.""" self.n_retries += 1 def wait(self): + """Wait for 0.1 seconds between retries.""" time.sleep(0.1) def is_done(self) -> bool: + """Check if the number of retries is bigger or equal to specified + maximum number of retries.""" return self.n_retries >= self.max_retries class MaxWaitTime(RetryStrategy): """Check for submissions status every 100 ms and wait for all submissions - a maximum of `max_wait_time` (seconds).""" + a maximum of `max_wait_time` (seconds). + + Parameters + ---------- + max_wait_time_sec : float + Maximum waiting time (in seconds). + """ def __init__(self, max_wait_time_sec: float = 5 * 60): self.max_wait_time_sec = max_wait_time_sec self.total_wait_time = 0 def step(self): + """Add 0.1 seconds to total waiting time.""" self.total_wait_time += 0.1 def wait(self): + """Wait (sleep) for 0.1 seconds.""" time.sleep(0.1) def is_done(self): + """Check if the total waiting time is bigger or equal to the specified + maximum waiting time.""" return self.total_wait_time >= self.max_wait_time_sec class RegularPeriodRetry(RetryStrategy): - """Check for submissions status periodically for indefinite amount of time.""" + """Check for submissions status periodically for indefinite amount of time. + + Parameters + ---------- + wait_time_sec : float + Wait time between retries (in seconds). + """ def __init__(self, wait_time_sec: float = 0.1): self.wait_time_sec = wait_time_sec def wait(self): + """Wait for `wait_time_sec` seconds.""" time.sleep(self.wait_time_sec) def is_done(self) -> bool: + """Return False, as this retry strategy is indefinite.""" return False + + def step(self) -> None: + """Satisfy the interface with a dummy implementation.""" + pass From c498a23f7cf371fbe95e664e60191a3ad3b35687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Mon, 30 Dec 2024 12:49:20 +0100 Subject: [PATCH 12/90] Add errors module to docs. Add docstrings in common module. --- docs/source/api/errors.rst | 5 +++++ docs/source/index.rst | 1 + src/judge0/common.py | 2 ++ 3 files changed, 8 insertions(+) create mode 100644 docs/source/api/errors.rst diff --git a/docs/source/api/errors.rst b/docs/source/api/errors.rst new file mode 100644 index 00000000..b976cd16 --- /dev/null +++ b/docs/source/api/errors.rst @@ -0,0 +1,5 @@ +Errors Module +============= + +.. automodule:: judge0.errors + :members: diff --git a/docs/source/index.rst b/docs/source/index.rst index 2c50fdfb..6cb851f6 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -60,6 +60,7 @@ Every contribution, big or small, is valuable! api/clients api/types api/retry + api/errors .. toctree:: :caption: Getting Involved diff --git a/src/judge0/common.py b/src/judge0/common.py index 57ad8387..c25ee549 100644 --- a/src/judge0/common.py +++ b/src/judge0/common.py @@ -6,6 +6,7 @@ def encode(content: Union[bytes, str, Encodeable]) -> str: + """Encode content to base64 string.""" if isinstance(content, bytes): return b64encode(content).decode() if isinstance(content, str): @@ -16,6 +17,7 @@ def encode(content: Union[bytes, str, Encodeable]) -> str: def decode(content: Union[bytes, str]) -> str: + """Decode base64 encoded content.""" if isinstance(content, bytes): return b64decode( content.decode(errors="backslashreplace"), validate=True From b97d17141c8fdf7abf595bb6194dd39c67d42a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Mon, 30 Dec 2024 12:55:19 +0100 Subject: [PATCH 13/90] Add version to dunder init. Update version in pyproject toml. --- pyproject.toml | 2 +- src/judge0/__init__.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index edfcfdd7..4974a30a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.0.4-dev" +version = "0.1.0.dev0" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.9" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index df0f78ac..391e926d 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -27,6 +27,8 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission +__version__ = "0.1.0.dev0" + __all__ = [ "ATD", "ATDJudge0CE", From 4b88795a071cd94c5e9fcb01a5a7304323d137c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Mon, 30 Dec 2024 13:18:34 +0100 Subject: [PATCH 14/90] Update base types docs. Add scroll to top button in docs. --- docs/source/api/types.rst | 39 ++++++++++++++++++++++++++++++++++++++- docs/source/conf.py | 3 +++ src/judge0/base_types.py | 20 +++++++++++++++++--- src/judge0/common.py | 6 +++--- 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/docs/source/api/types.rst b/docs/source/api/types.rst index 219d7ed0..bf0f62ab 100644 --- a/docs/source/api/types.rst +++ b/docs/source/api/types.rst @@ -1,6 +1,43 @@ Types Module ============ -.. automodule:: judge0.base_types +Types +----- + +.. autoclass:: judge0.base_types.Config + :members: + :member-order: bysource + +.. autoclass:: judge0.base_types.Encodable + :members: + +.. autoclass:: judge0.base_types.Flavor + :members: + :member-order: bysource + +.. autoclass:: judge0.base_types.Language + :members: + :member-order: bysource + +.. autoclass:: judge0.base_types.LanguageAlias :members: + :member-order: bysource +.. autoclass:: judge0.base_types.Status + :members: + :member-order: bysource + +.. autoclass:: judge0.base_types.TestCase + :members: + :member-order: bysource + +Type aliases +------------ + +.. autoclass:: judge0.base_types.TestCaseType + :members: + :member-order: bysource + +.. autoclass:: judge0.base_types.TestCases + :members: + :member-order: bysource \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 83e54e45..697f9f50 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -35,6 +35,9 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = "sphinxawesome_theme" +html_theme_options = { + "show_scrolltop": True, +} html_show_sphinx = False html_sidebars = { "**": [ diff --git a/src/judge0/base_types.py b/src/judge0/base_types.py index 8b892bad..5e7a57c9 100644 --- a/src/judge0/base_types.py +++ b/src/judge0/base_types.py @@ -1,7 +1,7 @@ import copy from dataclasses import dataclass -from enum import IntEnum, auto +from enum import auto, IntEnum from typing import Optional, Protocol, runtime_checkable, Sequence, Union from pydantic import BaseModel @@ -14,6 +14,8 @@ @dataclass(frozen=True) class TestCase: + """Dataclass for test case.""" + input: Optional[str] = None expected_output: Optional[str] = None @@ -21,7 +23,18 @@ class TestCase: def from_record( cls, test_case: Union[TestCaseType, None] ) -> Union["TestCase", None]: - """Create a TestCase from built-in types.""" + """Create a TestCase from built-in types. + + Parameters + ---------- + test_case: :obj:`TestCaseType` or None + Test case data. + + Returns + ------- + TestCase or None + Created TestCase object or None if test_case is None. + """ if isinstance(test_case, (tuple, list)): test_case = { field: value @@ -42,7 +55,7 @@ def from_record( @runtime_checkable -class Encodeable(Protocol): +class Encodable(Protocol): def encode(self) -> bytes: """Serialize the object to bytes.""" ... @@ -59,6 +72,7 @@ class Language(BaseModel): class LanguageAlias(IntEnum): """Language enumeration.""" + ASSEMBLY = auto() BASH = auto() BASIC = auto() diff --git a/src/judge0/common.py b/src/judge0/common.py index c25ee549..e8ab58e2 100644 --- a/src/judge0/common.py +++ b/src/judge0/common.py @@ -2,16 +2,16 @@ from itertools import islice from typing import Union -from judge0.base_types import Encodeable +from judge0.base_types import Encodable -def encode(content: Union[bytes, str, Encodeable]) -> str: +def encode(content: Union[bytes, str, Encodable]) -> str: """Encode content to base64 string.""" if isinstance(content, bytes): return b64encode(content).decode() if isinstance(content, str): return b64encode(content.encode()).decode() - if isinstance(content, Encodeable): + if isinstance(content, Encodable): return b64encode(content.encode()).decode() raise ValueError(f"Unsupported type. Expected bytes or str, got {type(content)}!") From 58194f3011d7ae914745cb4fbd9c8a4c766116fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Mon, 30 Dec 2024 13:27:10 +0100 Subject: [PATCH 15/90] Add filesystem to docs. --- docs/source/api/filesystem.rst | 6 ++++++ docs/source/api/types.rst | 4 ++++ docs/source/index.rst | 7 ++++--- src/judge0/filesystem.py | 20 ++++++++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 docs/source/api/filesystem.rst diff --git a/docs/source/api/filesystem.rst b/docs/source/api/filesystem.rst new file mode 100644 index 00000000..73eafb65 --- /dev/null +++ b/docs/source/api/filesystem.rst @@ -0,0 +1,6 @@ +Filesystem Module +================= + +.. automodule:: judge0.filesystem + :members: + :member-order: bysource diff --git a/docs/source/api/types.rst b/docs/source/api/types.rst index bf0f62ab..8cb94ccb 100644 --- a/docs/source/api/types.rst +++ b/docs/source/api/types.rst @@ -34,6 +34,10 @@ Types Type aliases ------------ +.. autoclass:: judge0.base_types.Iterable + :members: + :member-order: bysource + .. autoclass:: judge0.base_types.TestCaseType :members: :member-order: bysource diff --git a/docs/source/index.rst b/docs/source/index.rst index 6cb851f6..d31c6019 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -56,11 +56,12 @@ Every contribution, big or small, is valuable! :hidden: api/api - api/submission api/clients - api/types - api/retry api/errors + api/filesystem + api/retry + api/submission + api/types .. toctree:: :caption: Getting Involved diff --git a/src/judge0/filesystem.py b/src/judge0/filesystem.py index 6773680c..27fae223 100644 --- a/src/judge0/filesystem.py +++ b/src/judge0/filesystem.py @@ -11,6 +11,16 @@ class File(BaseModel): + """File object for storing file content. + + Parameters + ---------- + name : str + File name. + content : str or bytes, optional + File content. If str is provided, it will be encoded to bytes. + """ + name: str content: Optional[Union[str, bytes]] = None @@ -29,6 +39,15 @@ def __str__(self): class Filesystem(BaseModel): + """Filesystem object for storing multiple files. + + Parameters + ---------- + content : str or bytes or File or Iterable[File] or Filesystem, optional + Filesystem content. If str or bytes is provided, it will be decoded to + files. + """ + files: list[File] = [] def __init__(self, **data): @@ -66,6 +85,7 @@ def __repr__(self) -> str: return f"{self.__class__.__name__}(content={content_encoded!r})" def encode(self) -> bytes: + """Encode Filesystem object to bytes.""" zip_buffer = io.BytesIO() with zipfile.ZipFile(zip_buffer, "w") as zip_file: for file in self.files: From 6491bc55721b82557e80f75ff15a7aaf097164f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Mon, 30 Dec 2024 13:37:49 +0100 Subject: [PATCH 16/90] Add link to examples. --- docs/source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index d31c6019..0db57436 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -29,7 +29,7 @@ Want to learn more To learn what is happening behind the scenes and how to best use Judge0 Python SDK to facilitate the development of your own product see In Depth guide and -Examples. +`examples `_. Getting Involved ================ From a2c5e45569a148210e15a4951cb8c21521110559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Tue, 31 Dec 2024 11:07:07 +0100 Subject: [PATCH 17/90] Use None for base client HOME_URL. --- src/judge0/clients.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/judge0/clients.py b/src/judge0/clients.py index 311d26bd..ac5af89f 100644 --- a/src/judge0/clients.py +++ b/src/judge0/clients.py @@ -46,8 +46,9 @@ def __init__( self.languages = self.get_languages() self.config = self.get_config_info() except Exception as e: + home_url = getattr(self, "HOME_URL", None) raise RuntimeError( - f"Authentication failed. Visit {self.HOME_URL} to get or " + f"Authentication failed. Visit {home_url} to get or " "review your authentication credentials." ) from e From 8338f218fe7fa7b1266a60e3f74f7f93837a615b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Tue, 31 Dec 2024 11:25:58 +0100 Subject: [PATCH 18/90] Update docs in base types module. --- src/judge0/base_types.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/judge0/base_types.py b/src/judge0/base_types.py index 5e7a57c9..dc18bdd7 100644 --- a/src/judge0/base_types.py +++ b/src/judge0/base_types.py @@ -14,7 +14,7 @@ @dataclass(frozen=True) class TestCase: - """Dataclass for test case.""" + """Test case data model.""" input: Optional[str] = None expected_output: Optional[str] = None @@ -62,6 +62,11 @@ def encode(self) -> bytes: class Language(BaseModel): + """Language data model. + + Stores information about a language supported by Judge0. + """ + id: int name: str is_archived: Optional[bool] = None @@ -71,7 +76,12 @@ class Language(BaseModel): class LanguageAlias(IntEnum): - """Language enumeration.""" + """Language alias enumeration. + + Enumerates the programming languages supported by Judge0 client. Language + alias is resolved to the latest version of the language supported by the + selected client. + """ ASSEMBLY = auto() BASH = auto() @@ -143,14 +153,20 @@ class LanguageAlias(IntEnum): class Flavor(IntEnum): - """Judge0 flavor enumeration.""" + """Flavor enumeration. + + Enumerates the flavors supported by Judge0 client. + """ CE = 0 EXTRA_CE = 1 class Status(IntEnum): - """Status enumeration.""" + """Status enumeration. + + Enumerates possible status codes of a submission. + """ IN_QUEUE = 1 PROCESSING = 2 @@ -172,7 +188,10 @@ def __str__(self): class Config(BaseModel): - """Client config data.""" + """Client config data model. + + Stores configuration data for the Judge0 client. + """ allow_enable_network: bool allow_enable_per_process_and_thread_memory_limit: bool From 86d935a2788ff4b09d1d3b677261a31c34afea13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Tue, 31 Dec 2024 11:36:45 +0100 Subject: [PATCH 19/90] Minor docs update. --- src/judge0/api.py | 8 +++-- src/judge0/clients.py | 74 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/judge0/api.py b/src/judge0/api.py index 92b91b12..6c084713 100644 --- a/src/judge0/api.py +++ b/src/judge0/api.py @@ -353,10 +353,12 @@ def async_execute( resolved. submissions : Submission or Submissions, optional Submission or submissions for execution. - source_code: str, optional + source_code : str, optional A source code of a program. - test_cases: TestCaseType or TestCases, optional + test_cases : TestCaseType or TestCases, optional A single test or a list of test cases + **kwargs : dict + Additional keyword arguments to pass to the Submission constructor. Returns ------- @@ -405,6 +407,8 @@ def sync_execute( A source code of a program. test_cases: TestCaseType or TestCases, optional A single test or a list of test cases + **kwargs : dict + Additional keyword arguments to pass to the Submission constructor. Returns ------- diff --git a/src/judge0/clients.py b/src/judge0/clients.py index ac5af89f..621b8447 100644 --- a/src/judge0/clients.py +++ b/src/judge0/clients.py @@ -356,7 +356,19 @@ def get_submissions( class ATD(Client): - """Base class for all AllThingsDev clients.""" + """Base class for all AllThingsDev clients. + + Parameters + ---------- + endpoint : str + Default request endpoint. + host_header_value : str + Value for the x-apihub-host header. + api_key : str + AllThingsDev API key. + **kwargs : dict + Additional keyword arguments for the base Client. + """ API_KEY_ENV: ClassVar[str] = "JUDGE0_ATD_API_KEY" @@ -376,7 +388,15 @@ def _update_endpoint_header(self, header_value): class ATDJudge0CE(ATD): - """AllThingsDev client for CE flavor.""" + """AllThingsDev client for CE flavor. + + Parameters + ---------- + api_key : str + AllThingsDev API key. + **kwargs : dict + Additional keyword arguments for the base Client. + """ DEFAULT_ENDPOINT: ClassVar[str] = ( "https://judge0-ce.proxy-production.allthingsdev.co" @@ -460,7 +480,15 @@ def get_submissions( class ATDJudge0ExtraCE(ATD): - """AllThingsDev client for Extra CE flavor.""" + """AllThingsDev client for Extra CE flavor. + + Parameters + ---------- + api_key : str + AllThingsDev API key. + **kwargs : dict + Additional keyword arguments for the base Client. + """ DEFAULT_ENDPOINT: ClassVar[str] = ( "https://judge0-extra-ce.proxy-production.allthingsdev.co" @@ -545,7 +573,19 @@ def get_submissions( class Rapid(Client): - """Base class for all RapidAPI clients.""" + """Base class for all RapidAPI clients. + + Parameters + ---------- + endpoint : str + Default request endpoint. + host_header_value : str + Value for the x-rapidapi-host header. + api_key : str + RapidAPI API key. + **kwargs : dict + Additional keyword arguments for the base Client. + """ API_KEY_ENV: ClassVar[str] = "JUDGE0_RAPID_API_KEY" @@ -562,7 +602,15 @@ def __init__(self, endpoint, host_header_value, api_key, **kwargs): class RapidJudge0CE(Rapid): - """RapidAPI client for CE flavor.""" + """RapidAPI client for CE flavor. + + Parameters + ---------- + api_key : str + RapidAPI API key. + **kwargs : dict + Additional keyword arguments for the base Client. + """ DEFAULT_ENDPOINT: ClassVar[str] = "https://judge0-ce.p.rapidapi.com" DEFAULT_HOST: ClassVar[str] = "judge0-ce.p.rapidapi.com" @@ -578,7 +626,15 @@ def __init__(self, api_key, **kwargs): class RapidJudge0ExtraCE(Rapid): - """RapidAPI client for Extra CE flavor.""" + """RapidAPI client for Extra CE flavor. + + Parameters + ---------- + api_key : str + RapidAPI API key. + **kwargs : dict + Additional keyword arguments for the base Client. + """ DEFAULT_ENDPOINT: ClassVar[str] = "https://judge0-extra-ce.p.rapidapi.com" DEFAULT_HOST: ClassVar[str] = "judge0-extra-ce.p.rapidapi.com" @@ -602,6 +658,8 @@ class Sulu(Client): Default request endpoint. api_key : str, optional Sulu API key. + **kwargs : dict + Additional keyword arguments for the base Client. """ API_KEY_ENV: ClassVar[str] = "JUDGE0_SULU_API_KEY" @@ -622,6 +680,8 @@ class SuluJudge0CE(Sulu): ---------- api_key : str, optional Sulu API key. + **kwargs : dict + Additional keyword arguments for the base Client. """ DEFAULT_ENDPOINT: ClassVar[str] = "https://judge0-ce.p.sulu.sh" @@ -642,6 +702,8 @@ class SuluJudge0ExtraCE(Sulu): ---------- api_key : str Sulu API key. + **kwargs : dict + Additional keyword arguments for the base Client. """ DEFAULT_ENDPOINT: ClassVar[str] = "https://judge0-extra-ce.p.sulu.sh" From 3c2fb61ff51057988b98701dea68bf23c440735c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Tue, 31 Dec 2024 12:32:02 +0100 Subject: [PATCH 20/90] Update contributing guide. --- .../contributors_guide/contributing.rst | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 2a19fb5b..5cee988e 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -25,4 +25,46 @@ Preparing the development setup .. code-block:: console $ pip install -e .[test] + $ pip install -r docs/requirements.txt # needed for building the docs $ pre-commit install + +Building documentation +---------------------- + +Documentation is built using Sphinx. To build the documentation, run the + +.. code-block:: console + + $ cd docs + $ make html + +You should inspect the changes in the documentation by opening the +``docs/build/html/index.html`` file in your browser. + +You'll see a different output since the documentation is build with +`sphinx-multiversion `_ extension. + +Testing +------- + +If you implemented a feature or fixed a bug, please add tests for it. + +Unfortunately, at the moment you cannot run full test suite because it requires +access to API keys for all implemented API hubs (ATD, Sulu, and RapidAPI) and +a private Judge0 instance. To partially address this situation, you can run and +test your implemented feature and tests locally and use the GitHub CI pipeline +to run the full test suite. + +To run the tests locally, you can use the following command: + +.. code-block:: console + + $ pytest -svv tests -k '' + +To make the test compatible with the CI pipeline, you should use one of the +client fixtures: + +.. code-block:: python + + def test_my_test(request): + client = request.getfixturevalue("judge0_ce_client") # or judge0_extra_ce_client From ae10b877dff737f5c6ed63fd3e2b9632a0e1b4b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Tue, 31 Dec 2024 13:17:14 +0100 Subject: [PATCH 21/90] Change client order --- src/judge0/clients.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/judge0/clients.py b/src/judge0/clients.py index 621b8447..2d8366a9 100644 --- a/src/judge0/clients.py +++ b/src/judge0/clients.py @@ -715,5 +715,5 @@ def __init__(self, api_key=None, **kwargs): super().__init__(self.DEFAULT_ENDPOINT, api_key, **kwargs) -CE = (RapidJudge0CE, SuluJudge0CE, ATDJudge0CE) -EXTRA_CE = (RapidJudge0ExtraCE, SuluJudge0ExtraCE, ATDJudge0ExtraCE) +CE = (SuluJudge0CE, RapidJudge0CE, ATDJudge0CE) +EXTRA_CE = (SuluJudge0ExtraCE, RapidJudge0ExtraCE, ATDJudge0ExtraCE) From 50947518275817cbfba0cbe8ddf16922bdf5b6dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Tue, 31 Dec 2024 14:05:50 +0100 Subject: [PATCH 22/90] Add logo --- docs/assets/logo.png | Bin 0 -> 31233 bytes docs/source/conf.py | 32 ++++++++++++++++++++++++++++++++ docs/source/index.rst | 6 +++--- 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 docs/assets/logo.png diff --git a/docs/assets/logo.png b/docs/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9661bbb3b66cba7024393224b4afefdedb102674 GIT binary patch literal 31233 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

VJca6nosg~zu%#x_>VE4K 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 literal 0 HcmV?d00001 diff --git a/docs/source/conf.py b/docs/source/conf.py index 697f9f50..0807b9f0 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -34,9 +34,39 @@ # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output +html_title = project html_theme = "sphinxawesome_theme" html_theme_options = { "show_scrolltop": True, + "extra_header_link_icons": { + "repository on GitHub": { + "link": "https://github.com/judge0/judge0-python", + "icon": ( + '' + '' + ), + }, + }, } html_show_sphinx = False html_sidebars = { @@ -46,6 +76,8 @@ "versioning.html", ], } +html_logo = "../assets/logo.png" +html_favicon = html_logo pygments_style = "sphinx" sys.path.insert(0, os.path.abspath("../../src/")) # Adjust as needed diff --git a/docs/source/index.rst b/docs/source/index.rst index 0db57436..a4345356 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,6 +1,6 @@ -=============================== -Judge0 Python SDK documentation -=============================== +================= +Judge0 Python SDK +================= Getting Started =============== From fa0c502daff57d9617d1370d9b83dfe6b4a33bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Tue, 31 Dec 2024 14:27:21 +0100 Subject: [PATCH 23/90] Update release notes guide. --- .../contributors_guide/release_notes.rst | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/source/contributors_guide/release_notes.rst b/docs/source/contributors_guide/release_notes.rst index ec66b1c6..da50b25b 100644 --- a/docs/source/contributors_guide/release_notes.rst +++ b/docs/source/contributors_guide/release_notes.rst @@ -1,4 +1,32 @@ How to create a release ======================= -TODO \ No newline at end of file +Creating a release is a simple process that involves a few steps: + +#. **Prepare the release**: + #. Create a separate branch for the release. Name the branch ``release-x.y.z`` + where ``x.y.z`` is the version number. + #. Update the version number in ``judge0/__init__.py``. + #. Update the version number in ``judge0/pyproject.toml``. + #. Sync the branch with any changes from the master branch. + #. Create a pull request for the release branch. Make sure that all tests pass. + #. Merge the pull request. + #. Pull the changes to your local repository and tag the commit (``git tag vX.Y.Z``) with the version number. + #. Push the tags to the remote repository (``git push origin master --tags``). +#. **Create release (notes) on GitHub**. + #. Go to the `releases page `_ on GitHub. + #. Release title should be ``Judge0 Python SDK vX.Y.Z``. + #. Release notes should include a changes from the previous release to the newest release. + #. Use the `template `_ from the repo to organize the changes. + #. Create the release. ("Set as a pre-release" should NOT be checked.) +#. **Release on PyPI**: + #. Use the `GitHub Actions workflow `_ to create a release on PyPI. + #. Select `Run workflow` and as `Target repository` select `pypi`. + #. Click the `Run workflow` button. + +After the release is successfully published on PyPI, create a new pull request +that updates the working version in ``judge0/__init__.py`` and ``judge0/pyproject.toml`` +to the minor version. Merge the pull request and you're done! For example, if the +new release was ``1.2.2``, the working version should be updated to ``1.3.0.dev0``. + +You've successfully created a release! Congratulations! 🎉 \ No newline at end of file From 9fc2353a41ec571128cb6540d633c3ea6f3a79ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Tue, 31 Dec 2024 15:23:29 +0100 Subject: [PATCH 24/90] Update contributing guide. Update tests to use default client fixtures. --- .../contributors_guide/contributing.rst | 47 +++++++++++---- tests/conftest.py | 60 +++++++++++++++---- tests/test_api_test_cases.py | 6 +- tests/test_submission.py | 8 +-- 4 files changed, 92 insertions(+), 29 deletions(-) diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 5cee988e..61cc2279 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -47,24 +47,47 @@ You'll see a different output since the documentation is build with Testing ------- -If you implemented a feature or fixed a bug, please add tests for it. +.. warning:: + If you are implementing features or fixing bugs, you are expected to have + all of the three API keys (ATD, Sulu, and RapidAPI) setup and set in you + environment variables - ``JUDGE0_SULU_API_KEY``, ``JUDGE0_RAPID_API_KEY``, + and ``JUDGE0_ATD_API_KEY``. -Unfortunately, at the moment you cannot run full test suite because it requires -access to API keys for all implemented API hubs (ATD, Sulu, and RapidAPI) and -a private Judge0 instance. To partially address this situation, you can run and -test your implemented feature and tests locally and use the GitHub CI pipeline -to run the full test suite. +Every bug fix or new feature should have tests for it. The tests are located in +the ``tests`` directory and are written using `pytest `_. -To run the tests locally, you can use the following command: +While working with the tests, you should use the following fixtures: -.. code-block:: console +* ``default_ce_client`` - a client, chosen based on the environment variables set, that uses the CE flavor of the client. +* ``default_extra_ce_client`` - a client, chosen based on the environment variables set, that uses the Extra CE flavor of the client. - $ pytest -svv tests -k '' +The ``default_ce_client`` and ``default_extra_ce_client`` are fixtures that +return a client based on the environment variables set. This enables you to +run the full test suite locally, but also to run the tests on the CI pipeline +without changing the tests. -To make the test compatible with the CI pipeline, you should use one of the -client fixtures: +You can use the fixtures in your tests like this: .. code-block:: python def test_my_test(request): - client = request.getfixturevalue("judge0_ce_client") # or judge0_extra_ce_client + client = request.getfixturevalue("default_ce_client") # or default_extra_ce_client + +To run the tests locally, you can use the following command: + +.. code-block:: console + + $ pytest -svv tests -k '' + +This will enable you to run a single test, without incurring the cost of +running the full test suite. If you want to run the full test suite, you can +use the following command: + +.. code-block:: console + + $ pytest -svv tests + +or you can create a draft PR and let the CI pipeline run the tests for you. +The CI pipeline will run the tests on every PR, using a private instance +of Judge0, so you can be sure that your changes are not breaking the existing +functionality. diff --git a/tests/conftest.py b/tests/conftest.py index b1bd6120..0ceddb23 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,11 +13,15 @@ def judge0_ce_client(): api_key = os.getenv("JUDGE0_TEST_API_KEY") api_key_header = os.getenv("JUDGE0_TEST_API_KEY_HEADER") endpoint = os.getenv("JUDGE0_TEST_CE_ENDPOINT") - client = clients.Client( - endpoint=endpoint, - auth_headers={api_key_header: api_key}, - ) - return client + + if api_key is None or api_key_header is None or endpoint is None: + return None + else: + client = clients.Client( + endpoint=endpoint, + auth_headers={api_key_header: api_key}, + ) + return client @pytest.fixture(scope="session") @@ -25,11 +29,15 @@ def judge0_extra_ce_client(): api_key = os.getenv("JUDGE0_TEST_API_KEY") api_key_header = os.getenv("JUDGE0_TEST_API_KEY_HEADER") endpoint = os.getenv("JUDGE0_TEST_EXTRA_CE_ENDPOINT") - client = clients.Client( - endpoint=endpoint, - auth_headers={api_key_header: api_key}, - ) - return client + + if api_key is None or api_key_header is None or endpoint is None: + return None + else: + client = clients.Client( + endpoint=endpoint, + auth_headers={api_key_header: api_key}, + ) + return client @pytest.fixture(scope="session") @@ -63,6 +71,12 @@ def rapid_extra_ce_client(): @pytest.fixture(scope="session") def sulu_ce_client(): api_key = os.getenv("JUDGE0_SULU_API_KEY") + if api_key is None: + pytest.fail( + "Sulu API key is not available for testing. Make sure to have " + "JUDGE0_SULU_API_KEY in your environment variables." + ) + client = clients.SuluJudge0CE(api_key) return client @@ -70,5 +84,31 @@ def sulu_ce_client(): @pytest.fixture(scope="session") def sulu_extra_ce_client(): api_key = os.getenv("JUDGE0_SULU_API_KEY") + if api_key is None: + pytest.fail( + "Sulu API key is not available for testing. Make sure to have " + "JUDGE0_SULU_API_KEY in your environment variables." + ) + client = clients.SuluJudge0ExtraCE(api_key) return client + + +@pytest.fixture(scope="session") +def default_ce_client(judge0_ce_client, sulu_ce_client): + if judge0_ce_client is not None: + return judge0_ce_client + if sulu_ce_client is not None: + return sulu_ce_client + + pytest.fail("No default CE client available for testing.") + + +@pytest.fixture(scope="session") +def default_extra_ce_client(judge0_extra_ce_client, sulu_extra_ce_client): + if judge0_extra_ce_client is not None: + return judge0_extra_ce_client + if sulu_extra_ce_client is not None: + return sulu_extra_ce_client + + pytest.fail("No default Extra CE client available for testing.") diff --git a/tests/test_api_test_cases.py b/tests/test_api_test_cases.py index 0d08f5f8..c4963e9e 100644 --- a/tests/test_api_test_cases.py +++ b/tests/test_api_test_cases.py @@ -207,7 +207,7 @@ def test_single_test_case_in_iterable(self, test_cases, stdin, expected_output): def test_test_cases_from_run( source_code_or_submissions, test_cases, expected_status, request ): - client = request.getfixturevalue("judge0_ce_client") + client = request.getfixturevalue("default_ce_client") if isinstance(source_code_or_submissions, str): submissions = judge0.run( @@ -254,7 +254,7 @@ def test_test_cases_from_run( ], ) def test_no_test_cases(submissions, expected_status, request): - client = request.getfixturevalue("judge0_ce_client") + client = request.getfixturevalue("default_ce_client") submissions = judge0.run( client=client, @@ -269,7 +269,7 @@ def test_no_test_cases(submissions, expected_status, request): @pytest.mark.parametrize("n_submissions", [42, 84]) def test_batched_test_cases(n_submissions, request): - client = request.getfixturevalue("judge0_ce_client") + client = request.getfixturevalue("default_ce_client") submissions = [ Submission(source_code=f"print({i})", expected_output=f"{i}") for i in range(n_submissions) diff --git a/tests/test_submission.py b/tests/test_submission.py index ddae1401..ec1885b2 100644 --- a/tests/test_submission.py +++ b/tests/test_submission.py @@ -52,7 +52,7 @@ def test_from_json(): def test_status_before_and_after_submission(request): - client = request.getfixturevalue("judge0_ce_client") + client = request.getfixturevalue("default_ce_client") submission = Submission(source_code='print("Hello World!")') assert submission.status is None @@ -65,7 +65,7 @@ def test_status_before_and_after_submission(request): def test_is_done(request): - client = request.getfixturevalue("judge0_ce_client") + client = request.getfixturevalue("default_ce_client") submission = Submission(source_code='print("Hello World!")') assert submission.status is None @@ -77,7 +77,7 @@ def test_is_done(request): def test_language_before_and_after_execution(request): - client = request.getfixturevalue("judge0_ce_client") + client = request.getfixturevalue("default_ce_client") code = """\ public class Main { public static void main(String[] args) { @@ -97,7 +97,7 @@ def test_language_before_and_after_execution(request): def test_language_executable(request): - client = request.getfixturevalue("judge0_ce_client") + client = request.getfixturevalue("default_ce_client") code = b64decode( "f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAAABAAAAAAABAAAAAAAAAAEAQAAAAAAAAAAAAAEAAOAABAEAABAADAAEAAAAFAAAAABAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAJQAAAAAAAAAlAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADHAjVANsAG+GABAAInHDwUx/41HPA8FAGhlbGxvLCB3b3JsZAoALnNoc3RydGFiAC50ZXh0AC5yb2RhdGEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAAAGAAAAAAAAAAAAQAAAAAAAABAAAAAAAAAXAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABEAAAABAAAAAgAAAAAAAAAYAEAAAAAAABgQAAAAAAAADQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAlEAAAAAAAABkAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA" # noqa: E501 ) From ad9f6e96852287c2814ead9a3992e94c21f6be92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 19:24:25 +0100 Subject: [PATCH 25/90] Add placeholder for client resolution docs. --- docs/source/contributors_guide/contributing.rst | 4 ++++ docs/source/in_depth/client_resolution.rst | 4 ++++ docs/source/index.rst | 12 +++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 docs/source/in_depth/client_resolution.rst diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 61cc2279..546c6cfe 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -41,6 +41,10 @@ Documentation is built using Sphinx. To build the documentation, run the You should inspect the changes in the documentation by opening the ``docs/build/html/index.html`` file in your browser. +.. note:: + If you are having trouble with the documentation and are seeing unexpected + output, delete the ``docs/build`` directory and rerun the ``make html`` command. + You'll see a different output since the documentation is build with `sphinx-multiversion `_ extension. diff --git a/docs/source/in_depth/client_resolution.rst b/docs/source/in_depth/client_resolution.rst new file mode 100644 index 00000000..dfdd5321 --- /dev/null +++ b/docs/source/in_depth/client_resolution.rst @@ -0,0 +1,4 @@ +Client Resolution +================= + +TODO: Describe the approach to client resolution. See `_get_implicit_client`. \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index a4345356..0e3027d0 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -63,6 +63,16 @@ Every contribution, big or small, is valuable! api/submission api/types + +.. toctree:: + :caption: In Depth + :glob: + :titlesonly: + :hidden: + + in_depth/client_resolution + + .. toctree:: :caption: Getting Involved :glob: @@ -70,4 +80,4 @@ Every contribution, big or small, is valuable! :hidden: contributors_guide/contributing - contributors_guide/release_notes \ No newline at end of file + contributors_guide/release_notes From df50bfa9c06c9c9fc90624516c2015737d85b06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 19:27:31 +0100 Subject: [PATCH 26/90] Add placeholder for API overview. --- docs/source/in_depth/overview.rst | 8 ++++++++ docs/source/index.rst | 1 + 2 files changed, 9 insertions(+) create mode 100644 docs/source/in_depth/overview.rst diff --git a/docs/source/in_depth/overview.rst b/docs/source/in_depth/overview.rst new file mode 100644 index 00000000..d7dd136b --- /dev/null +++ b/docs/source/in_depth/overview.rst @@ -0,0 +1,8 @@ +Overview +======== + +TODO: + +* add a brief overview of the most important classes (Client, Submission, etc.) +* add a brief overview of the most important functions (create_submission, get_submission, etc.) +* write about the difference between high-level api and low-level api \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index 0e3027d0..4f983252 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -70,6 +70,7 @@ Every contribution, big or small, is valuable! :titlesonly: :hidden: + in_depth/overview in_depth/client_resolution From 896ce80b0d44753ff18dd605ef80e9aa583fdaf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 19:41:54 +0100 Subject: [PATCH 27/90] Add main nav links. Add indication of external links. --- docs/source/conf.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index 0807b9f0..ea153536 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -67,6 +67,11 @@ ), }, }, + "awesome_external_links": True, + "main_nav_links": { + "Home": "https://judge0.github.io/judge0-python/", + "Judge0": "https://judge0.com/", + }, } html_show_sphinx = False html_sidebars = { From 711b778e39674936b526a5805de133d08ae4c269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 20:40:51 +0100 Subject: [PATCH 28/90] Refactor _get_implict_client. Add ability to load custom clients from get_client. Refactor env variable to read auth headers as dict. --- .github/workflows/test.yml | 8 ++--- src/judge0/__init__.py | 74 +++++++++++++++++++++++++++++--------- tests/conftest.py | 26 +++++--------- 3 files changed, 70 insertions(+), 38 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3c33777d..d68acfc4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,10 +32,10 @@ jobs: JUDGE0_ATD_API_KEY: ${{ secrets.JUDGE0_ATD_API_KEY }} JUDGE0_RAPID_API_KEY: ${{ secrets.JUDGE0_RAPID_API_KEY }} JUDGE0_SULU_API_KEY: ${{ secrets.JUDGE0_SULU_API_KEY }} - JUDGE0_TEST_API_KEY: ${{ secrets.JUDGE0_TEST_API_KEY }} - JUDGE0_TEST_API_KEY_HEADER: ${{ secrets.JUDGE0_TEST_API_KEY_HEADER }} - JUDGE0_TEST_CE_ENDPOINT: ${{ secrets.JUDGE0_TEST_CE_ENDPOINT }} - JUDGE0_TEST_EXTRA_CE_ENDPOINT: ${{ secrets.JUDGE0_TEST_EXTRA_CE_ENDPOINT }} + JUDGE0_CE_AUTH_HEADERS: ${{ secrets.JUDGE0_CE_AUTH_HEADERS }} + JUDGE0_EXTRA_CE_AUTH_HEADERS: ${{ secrets.JUDGE0_EXTRA_CE_AUTH_HEADERS }} + JUDGE0_CE_ENDPOINT: ${{ secrets.JUDGE0_CE_ENDPOINT }} + JUDGE0_EXTRA_CE_ENDPOINT: ${{ secrets.JUDGE0_EXTRA_CE_ENDPOINT }} run: | source venv/bin/activate pytest -vv tests/ diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 391e926d..0fb78d9f 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -1,5 +1,7 @@ import os +from typing import Union + from .api import ( async_execute, async_run, @@ -73,8 +75,6 @@ def _get_implicit_client(flavor: Flavor) -> Client: if flavor == Flavor.EXTRA_CE and JUDGE0_IMPLICIT_EXTRA_CE_CLIENT is not None: return JUDGE0_IMPLICIT_EXTRA_CE_CLIENT - from .clients import CE, EXTRA_CE - try: from dotenv import load_dotenv @@ -82,27 +82,18 @@ def _get_implicit_client(flavor: Flavor) -> Client: except: # noqa: E722 pass - if flavor == Flavor.CE: - client_classes = CE - else: - client_classes = EXTRA_CE + # Let's check if we can find a self-hosted client. + client = _get_custom_client(flavor) # Try to find one of the predefined keys JUDGE0_{SULU,RAPID,ATD}_API_KEY # in environment variables. - client = None - for client_class in client_classes: - api_key = os.getenv(client_class.API_KEY_ENV) - if api_key is not None: - client = client_class(api_key) - break + if client is None: + client = _get_predefined_client(flavor) # If we didn't find any of the possible predefined keys, initialize # the preview Sulu client based on the flavor. if client is None: - if flavor == Flavor.CE: - client = SuluJudge0CE(retry_strategy=RegularPeriodRetry(0.5)) - else: - client = SuluJudge0ExtraCE(retry_strategy=RegularPeriodRetry(0.5)) + client = _get_preview_client(flavor) if flavor == Flavor.CE: JUDGE0_IMPLICIT_CE_CLIENT = client @@ -112,6 +103,57 @@ def _get_implicit_client(flavor: Flavor) -> Client: return client +def _get_preview_client(flavor: Flavor) -> Union[SuluJudge0CE, SuluJudge0ExtraCE]: + if flavor == Flavor.CE: + return SuluJudge0CE(retry_strategy=RegularPeriodRetry(0.5)) + else: + return SuluJudge0ExtraCE(retry_strategy=RegularPeriodRetry(0.5)) + + +def _get_custom_client(flavor: Flavor) -> Union[Client, None]: + ce_endpoint = os.getenv("JUDGE0_CE_ENDPOINT") + ce_auth_header = os.getenv("JUDGE0_CE_AUTH_HEADERS") + extra_ce_endpoint = os.getenv("JUDGE0_EXTRA_CE_ENDPOINT") + extra_ce_auth_header = os.getenv("JUDGE0_EXTRA_CE_AUTH_HEADERS") + + if flavor == Flavor.CE and ce_endpoint is not None and ce_auth_header is not None: + return Client( + endpoint=ce_endpoint, + auth_headers=eval(ce_auth_header), + ) + + if ( + flavor == Flavor.EXTRA_CE + and extra_ce_endpoint is not None + and extra_ce_auth_header is not None + ): + return Client( + endpoint=extra_ce_endpoint, + auth_headers=eval(extra_ce_auth_header), + ) + + return None + + +def _get_predefined_client(flavor: Flavor) -> Union[Client, None]: + from .clients import CE, EXTRA_CE + + if flavor == Flavor.CE: + client_classes = CE + else: + client_classes = EXTRA_CE + + for client_class in client_classes: + api_key = os.getenv(client_class.API_KEY_ENV) + if api_key is not None: + client = client_class(api_key) + break + else: + client = None + + return client + + CE = Flavor.CE EXTRA_CE = Flavor.EXTRA_CE diff --git a/tests/conftest.py b/tests/conftest.py index 0ceddb23..d06dcb2b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,34 +10,24 @@ @pytest.fixture(scope="session") def judge0_ce_client(): - api_key = os.getenv("JUDGE0_TEST_API_KEY") - api_key_header = os.getenv("JUDGE0_TEST_API_KEY_HEADER") - endpoint = os.getenv("JUDGE0_TEST_CE_ENDPOINT") + endpoint = os.getenv("JUDGE0_CE_ENDPOINT") + auth_headers = os.getenv("JUDGE0_CE_AUTH_HEADERS") - if api_key is None or api_key_header is None or endpoint is None: + if endpoint is None or auth_headers is None: return None else: - client = clients.Client( - endpoint=endpoint, - auth_headers={api_key_header: api_key}, - ) - return client + return clients.Client(endpoint=endpoint, auth_headers=eval(auth_headers)) @pytest.fixture(scope="session") def judge0_extra_ce_client(): - api_key = os.getenv("JUDGE0_TEST_API_KEY") - api_key_header = os.getenv("JUDGE0_TEST_API_KEY_HEADER") - endpoint = os.getenv("JUDGE0_TEST_EXTRA_CE_ENDPOINT") + endpoint = os.getenv("JUDGE0_EXTRA_CE_ENDPOINT") + auth_headers = os.getenv("JUDGE0_EXTRA_CE_AUTH_HEADERS") - if api_key is None or api_key_header is None or endpoint is None: + if endpoint is None or auth_headers is None: return None else: - client = clients.Client( - endpoint=endpoint, - auth_headers={api_key_header: api_key}, - ) - return client + return clients.Client(endpoint=endpoint, auth_headers=eval(auth_headers)) @pytest.fixture(scope="session") From b893b18cabc65c1b18cf81b15284a6db5bfe362f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 20:44:37 +0100 Subject: [PATCH 29/90] Add ability to run test CI from console. --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d68acfc4..991d2d19 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,7 @@ name: Test judge0-python on: + workflow_dispatch: push: branches: ["master"] paths: ["src/**", "tests/**"] From 340e0e01c72700dc7303bf34ae0c77ec1d3c76ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 21:07:12 +0100 Subject: [PATCH 30/90] Use json.loads instead of eval. --- src/judge0/__init__.py | 6 ++++-- tests/conftest.py | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 0fb78d9f..34de57d4 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -111,6 +111,8 @@ def _get_preview_client(flavor: Flavor) -> Union[SuluJudge0CE, SuluJudge0ExtraCE def _get_custom_client(flavor: Flavor) -> Union[Client, None]: + from json import loads + ce_endpoint = os.getenv("JUDGE0_CE_ENDPOINT") ce_auth_header = os.getenv("JUDGE0_CE_AUTH_HEADERS") extra_ce_endpoint = os.getenv("JUDGE0_EXTRA_CE_ENDPOINT") @@ -119,7 +121,7 @@ def _get_custom_client(flavor: Flavor) -> Union[Client, None]: if flavor == Flavor.CE and ce_endpoint is not None and ce_auth_header is not None: return Client( endpoint=ce_endpoint, - auth_headers=eval(ce_auth_header), + auth_headers=loads(ce_auth_header), ) if ( @@ -129,7 +131,7 @@ def _get_custom_client(flavor: Flavor) -> Union[Client, None]: ): return Client( endpoint=extra_ce_endpoint, - auth_headers=eval(extra_ce_auth_header), + auth_headers=loads(extra_ce_auth_header), ) return None diff --git a/tests/conftest.py b/tests/conftest.py index d06dcb2b..48aea373 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +import json import os import pytest @@ -16,7 +17,7 @@ def judge0_ce_client(): if endpoint is None or auth_headers is None: return None else: - return clients.Client(endpoint=endpoint, auth_headers=eval(auth_headers)) + return clients.Client(endpoint=endpoint, auth_headers=json.loads(auth_headers)) @pytest.fixture(scope="session") @@ -27,7 +28,7 @@ def judge0_extra_ce_client(): if endpoint is None or auth_headers is None: return None else: - return clients.Client(endpoint=endpoint, auth_headers=eval(auth_headers)) + return clients.Client(endpoint=endpoint, auth_headers=json.loads(auth_headers)) @pytest.fixture(scope="session") From bb29acc2325375d80dc29839a99d59b34ecf3f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 21:21:54 +0100 Subject: [PATCH 31/90] Change default language to PYTHON_FOR_ML --- src/judge0/submission.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/judge0/submission.py b/src/judge0/submission.py index 55b76602..78d14700 100644 --- a/src/judge0/submission.py +++ b/src/judge0/submission.py @@ -128,7 +128,7 @@ class Submission(BaseModel): source_code: Optional[Union[str, bytes]] = Field(default=None, repr=True) language: Union[LanguageAlias, int] = Field( - default=LanguageAlias.PYTHON, + default=LanguageAlias.PYTHON_FOR_ML, repr=True, ) additional_files: Optional[Union[str, Filesystem]] = Field(default=None, repr=True) From 56f695359025bc01d9a37709c6ee46060235c44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 21:45:59 +0100 Subject: [PATCH 32/90] Rename fixtures. Refactor tests to explicitly set Submission language. --- .../contributors_guide/contributing.rst | 8 ++-- src/judge0/__init__.py | 10 ++--- tests/conftest.py | 38 +++++++++++++----- tests/test_api_test_cases.py | 39 ++++++++++++++----- tests/test_submission.py | 16 +++++--- 5 files changed, 77 insertions(+), 34 deletions(-) diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 546c6cfe..552471d5 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -62,10 +62,10 @@ the ``tests`` directory and are written using `pytest Client: # Let's check if we can find a self-hosted client. client = _get_custom_client(flavor) - # Try to find one of the predefined keys JUDGE0_{SULU,RAPID,ATD}_API_KEY - # in environment variables. + # Try to find one of the API keys JUDGE0_{SULU,RAPID,ATD}_API_KEY + # for hub clients. if client is None: - client = _get_predefined_client(flavor) + client = _get_hub_client(flavor) - # If we didn't find any of the possible predefined keys, initialize + # If we didn't find any of the possible keys, initialize # the preview Sulu client based on the flavor. if client is None: client = _get_preview_client(flavor) @@ -137,7 +137,7 @@ def _get_custom_client(flavor: Flavor) -> Union[Client, None]: return None -def _get_predefined_client(flavor: Flavor) -> Union[Client, None]: +def _get_hub_client(flavor: Flavor) -> Union[Client, None]: from .clients import CE, EXTRA_CE if flavor == Flavor.CE: diff --git a/tests/conftest.py b/tests/conftest.py index 48aea373..c1684352 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -10,7 +10,7 @@ @pytest.fixture(scope="session") -def judge0_ce_client(): +def custom_ce_client(): endpoint = os.getenv("JUDGE0_CE_ENDPOINT") auth_headers = os.getenv("JUDGE0_CE_AUTH_HEADERS") @@ -21,7 +21,7 @@ def judge0_ce_client(): @pytest.fixture(scope="session") -def judge0_extra_ce_client(): +def custom_extra_ce_client(): endpoint = os.getenv("JUDGE0_EXTRA_CE_ENDPOINT") auth_headers = os.getenv("JUDGE0_EXTRA_CE_AUTH_HEADERS") @@ -86,20 +86,38 @@ def sulu_extra_ce_client(): @pytest.fixture(scope="session") -def default_ce_client(judge0_ce_client, sulu_ce_client): - if judge0_ce_client is not None: - return judge0_ce_client +def ce_client( + custom_ce_client, + sulu_ce_client, + rapid_ce_client, + atd_ce_client, +): + if custom_ce_client is not None: + return custom_ce_client if sulu_ce_client is not None: return sulu_ce_client + if rapid_ce_client is not None: + return rapid_ce_client + if atd_ce_client is not None: + return atd_ce_client - pytest.fail("No default CE client available for testing.") + pytest.fail("No CE client available for testing.") @pytest.fixture(scope="session") -def default_extra_ce_client(judge0_extra_ce_client, sulu_extra_ce_client): - if judge0_extra_ce_client is not None: - return judge0_extra_ce_client +def extra_ce_client( + custom_extra_ce_client, + sulu_extra_ce_client, + rapid_extra_ce_client, + atd_extra_ce_client, +): + if custom_extra_ce_client is not None: + return custom_extra_ce_client if sulu_extra_ce_client is not None: return sulu_extra_ce_client + if rapid_extra_ce_client is not None: + return rapid_extra_ce_client + if atd_extra_ce_client is not None: + return atd_extra_ce_client - pytest.fail("No default Extra CE client available for testing.") + pytest.fail("No Extra CE client available for testing.") diff --git a/tests/test_api_test_cases.py b/tests/test_api_test_cases.py index c4963e9e..8dea1e6a 100644 --- a/tests/test_api_test_cases.py +++ b/tests/test_api_test_cases.py @@ -2,8 +2,9 @@ import judge0 import pytest -from judge0 import Status, Submission, TestCase from judge0.api import create_submissions_from_test_cases +from judge0.base_types import LanguageAlias, Status, TestCase +from judge0.submission import Submission @pytest.mark.parametrize( @@ -172,14 +173,20 @@ def test_single_test_case_in_iterable(self, test_cases, stdin, expected_output): [Status.ACCEPTED, Status.ACCEPTED], ], [ - Submission(source_code="print(f'Hello, {input()}')"), + Submission( + source_code="print(f'Hello, {input()}')", + language=LanguageAlias.PYTHON, + ), [ TestCase("Judge0", "Hello, Judge0"), ], [Status.ACCEPTED], ], [ - Submission(source_code="print(f'Hello, {input()}')"), + Submission( + source_code="print(f'Hello, {input()}')", + language=LanguageAlias.PYTHON, + ), [ TestCase("Judge0", "Hello, Judge0"), TestCase("pytest", "Hi, pytest"), @@ -188,8 +195,14 @@ def test_single_test_case_in_iterable(self, test_cases, stdin, expected_output): ], [ [ - Submission(source_code="print(f'Hello, {input()}')"), - Submission(source_code="print(f'Hello, {input()}')"), + Submission( + source_code="print(f'Hello, {input()}')", + language=LanguageAlias.PYTHON, + ), + Submission( + source_code="print(f'Hello, {input()}')", + language=LanguageAlias.PYTHON, + ), ], [ TestCase("Judge0", "Hello, Judge0"), @@ -207,13 +220,14 @@ def test_single_test_case_in_iterable(self, test_cases, stdin, expected_output): def test_test_cases_from_run( source_code_or_submissions, test_cases, expected_status, request ): - client = request.getfixturevalue("default_ce_client") + client = request.getfixturevalue("ce_client") if isinstance(source_code_or_submissions, str): submissions = judge0.run( client=client, source_code=source_code_or_submissions, test_cases=test_cases, + language=LanguageAlias.PYTHON, ) else: submissions = judge0.run( @@ -231,6 +245,7 @@ def test_test_cases_from_run( [ Submission( source_code="print(f'Hello, {input()}')", + language=LanguageAlias.PYTHON, stdin="Judge0", expected_output="Hello, Judge0", ), @@ -240,11 +255,13 @@ def test_test_cases_from_run( [ Submission( source_code="print(f'Hello, {input()}')", + language=LanguageAlias.PYTHON, stdin="Judge0", expected_output="Hello, Judge0", ), Submission( source_code="print(f'Hello, {input()}')", + language=LanguageAlias.PYTHON, stdin="pytest", expected_output="Hello, pytest", ), @@ -254,7 +271,7 @@ def test_test_cases_from_run( ], ) def test_no_test_cases(submissions, expected_status, request): - client = request.getfixturevalue("default_ce_client") + client = request.getfixturevalue("ce_client") submissions = judge0.run( client=client, @@ -269,9 +286,13 @@ def test_no_test_cases(submissions, expected_status, request): @pytest.mark.parametrize("n_submissions", [42, 84]) def test_batched_test_cases(n_submissions, request): - client = request.getfixturevalue("default_ce_client") + client = request.getfixturevalue("ce_client") submissions = [ - Submission(source_code=f"print({i})", expected_output=f"{i}") + Submission( + source_code=f"print({i})", + language=LanguageAlias.PYTHON, + expected_output=f"{i}", + ) for i in range(n_submissions) ] diff --git a/tests/test_submission.py b/tests/test_submission.py index ec1885b2..86750344 100644 --- a/tests/test_submission.py +++ b/tests/test_submission.py @@ -52,8 +52,10 @@ def test_from_json(): def test_status_before_and_after_submission(request): - client = request.getfixturevalue("default_ce_client") - submission = Submission(source_code='print("Hello World!")') + client = request.getfixturevalue("ce_client") + submission = Submission( + source_code='print("Hello World!")', language=LanguageAlias.PYTHON + ) assert submission.status is None @@ -65,8 +67,10 @@ def test_status_before_and_after_submission(request): def test_is_done(request): - client = request.getfixturevalue("default_ce_client") - submission = Submission(source_code='print("Hello World!")') + client = request.getfixturevalue("ce_client") + submission = Submission( + source_code='print("Hello World!")', language=LanguageAlias.PYTHON + ) assert submission.status is None @@ -77,7 +81,7 @@ def test_is_done(request): def test_language_before_and_after_execution(request): - client = request.getfixturevalue("default_ce_client") + client = request.getfixturevalue("ce_client") code = """\ public class Main { public static void main(String[] args) { @@ -97,7 +101,7 @@ def test_language_before_and_after_execution(request): def test_language_executable(request): - client = request.getfixturevalue("default_ce_client") + client = request.getfixturevalue("ce_client") code = b64decode( "f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAAABAAAAAAABAAAAAAAAAAEAQAAAAAAAAAAAAAEAAOAABAEAABAADAAEAAAAFAAAAABAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAJQAAAAAAAAAlAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADHAjVANsAG+GABAAInHDwUx/41HPA8FAGhlbGxvLCB3b3JsZAoALnNoc3RydGFiAC50ZXh0AC5yb2RhdGEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAAAGAAAAAAAAAAAAQAAAAAAAABAAAAAAAAAXAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABEAAAABAAAAAgAAAAAAAAAYAEAAAAAAABgQAAAAAAAADQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAlEAAAAAAAABkAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA" # noqa: E501 ) From 4a2e4f14341222df9bab335702a3a23452ad8a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 22:14:35 +0100 Subject: [PATCH 33/90] Refactor fixtures. Add preview client as possible fixture for ce and extra ce client. --- tests/conftest.py | 72 +++++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index c1684352..4e1547c5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,7 +4,7 @@ import pytest from dotenv import load_dotenv -from judge0 import clients +from judge0 import clients, RegularPeriodRetry load_dotenv() @@ -34,55 +34,71 @@ def custom_extra_ce_client(): @pytest.fixture(scope="session") def atd_ce_client(): api_key = os.getenv("JUDGE0_ATD_API_KEY") - client = clients.ATDJudge0CE(api_key) - return client + + if api_key is None: + return None + else: + return clients.ATDJudge0CE(api_key) @pytest.fixture(scope="session") def atd_extra_ce_client(): api_key = os.getenv("JUDGE0_ATD_API_KEY") - client = clients.ATDJudge0ExtraCE(api_key) - return client + + if api_key is None: + return None + else: + return clients.ATDJudge0ExtraCE(api_key) @pytest.fixture(scope="session") def rapid_ce_client(): api_key = os.getenv("JUDGE0_RAPID_API_KEY") - client = clients.RapidJudge0CE(api_key) - return client + + if api_key is None: + return None + else: + return clients.RapidJudge0CE(api_key) @pytest.fixture(scope="session") def rapid_extra_ce_client(): api_key = os.getenv("JUDGE0_RAPID_API_KEY") - client = clients.RapidJudge0ExtraCE(api_key) - return client + + if api_key is None: + return None + else: + return clients.RapidJudge0ExtraCE(api_key) @pytest.fixture(scope="session") def sulu_ce_client(): api_key = os.getenv("JUDGE0_SULU_API_KEY") - if api_key is None: - pytest.fail( - "Sulu API key is not available for testing. Make sure to have " - "JUDGE0_SULU_API_KEY in your environment variables." - ) - client = clients.SuluJudge0CE(api_key) - return client + if api_key is None: + return None + else: + return clients.SuluJudge0CE(api_key) @pytest.fixture(scope="session") def sulu_extra_ce_client(): api_key = os.getenv("JUDGE0_SULU_API_KEY") + if api_key is None: - pytest.fail( - "Sulu API key is not available for testing. Make sure to have " - "JUDGE0_SULU_API_KEY in your environment variables." - ) + return None + else: + return clients.SuluJudge0ExtraCE(api_key) - client = clients.SuluJudge0ExtraCE(api_key) - return client + +@pytest.fixture(scope="session") +def preview_ce_client() -> clients.SuluJudge0CE: + return clients.SuluJudge0CE(retry_strategy=RegularPeriodRetry(0.5)) + + +@pytest.fixture(scope="session") +def preview_extra_ce_client() -> clients.SuluJudge0ExtraCE: + return clients.SuluJudge0ExtraCE(retry_strategy=RegularPeriodRetry(0.5)) @pytest.fixture(scope="session") @@ -91,6 +107,7 @@ def ce_client( sulu_ce_client, rapid_ce_client, atd_ce_client, + preview_ce_client, ): if custom_ce_client is not None: return custom_ce_client @@ -100,8 +117,10 @@ def ce_client( return rapid_ce_client if atd_ce_client is not None: return atd_ce_client + if preview_ce_client is not None: + return preview_ce_client - pytest.fail("No CE client available for testing.") + pytest.fail("No CE client available for testing. This error should not happen!") @pytest.fixture(scope="session") @@ -110,6 +129,7 @@ def extra_ce_client( sulu_extra_ce_client, rapid_extra_ce_client, atd_extra_ce_client, + preview_extra_ce_client, ): if custom_extra_ce_client is not None: return custom_extra_ce_client @@ -119,5 +139,9 @@ def extra_ce_client( return rapid_extra_ce_client if atd_extra_ce_client is not None: return atd_extra_ce_client + if preview_extra_ce_client is not None: + return preview_extra_ce_client - pytest.fail("No Extra CE client available for testing.") + pytest.fail( + "No Extra CE client available for testing. This error should not happen!" + ) From 57050fab0b53ad082eea5eca7d9af9e4b8500b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 22:31:46 +0100 Subject: [PATCH 34/90] Move docs requirements to pyproject.toml --- .github/workflows/docs.yml | 8 ++++---- docs/requirements.txt | 4 ---- docs/source/contributors_guide/contributing.rst | 5 ++--- pyproject.toml | 11 ++++++++++- 4 files changed, 16 insertions(+), 12 deletions(-) delete mode 100644 docs/requirements.txt diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4a70709c..df34c7f2 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,10 +17,10 @@ jobs: persist-credentials: false fetch-depth: 0 # Fetch the full history ref: ${{ github.ref }} # Check out the current branch or tag - + - name: Fetch tags only run: git fetch --tags --no-recurse-submodules - + - name: Set up Python uses: actions/setup-python@v4 with: @@ -29,7 +29,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r docs/requirements.txt + pip install -e [docs] - name: Build documentation run: sphinx-multiversion docs/source docs/build/html --keep-going --no-color @@ -41,7 +41,7 @@ jobs: # Get the latest tag latest_tag=$(git tag --sort=-creatordate | head -n 1) echo "LATEST_RELEASE=$latest_tag" >> $GITHUB_ENV - + - name: Generate index.html for judge0.github.io/judge0-python. run: | echo ' diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index cd3bc0f8..00000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -sphinx==7.4.7 -sphinxawesome-theme==5.3.2 -sphinx-autodoc-typehints==2.3.0 -sphinx-multiversion==0.2.4 \ No newline at end of file diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 552471d5..194834cf 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -24,8 +24,7 @@ Preparing the development setup .. code-block:: console - $ pip install -e .[test] - $ pip install -r docs/requirements.txt # needed for building the docs + $ pip install -e [dev] $ pre-commit install Building documentation @@ -73,7 +72,7 @@ without changing the tests. You can use the fixtures in your tests like this: .. code-block:: python - + def test_my_test(request): client = request.getfixturevalue("ce_client") # or extra_ce_client diff --git a/pyproject.toml b/pyproject.toml index 4974a30a..1fc29ce9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,16 @@ test = [ "pytest-cov==6.0.0", "flake8-docstrings==1.7.0", ] -docs = ["sphinx==7.4.7"] +docs = [ + "sphinx==7.4.7", + "sphinxawesome-theme==5.3.2", + "sphinx-autodoc-typehints==2.3.0", + "sphinx-multiversion==0.2.4", +] +dev = [ + "judge0[test]", + "judge0[docs]", +] [tool.flake8] extend-ignore = [ From a06164c7bfd8060670e0182978465f97a24887cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 22:37:07 +0100 Subject: [PATCH 35/90] Fix dependency installation in workflow and in the docs --- .github/workflows/docs.yml | 2 +- docs/source/contributors_guide/contributing.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index df34c7f2..11d9d8e3 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -29,7 +29,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -e [docs] + pip install -e .[docs] - name: Build documentation run: sphinx-multiversion docs/source docs/build/html --keep-going --no-color diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 194834cf..094577c2 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -24,7 +24,7 @@ Preparing the development setup .. code-block:: console - $ pip install -e [dev] + $ pip install -e .[dev] $ pre-commit install Building documentation From 7974f90f5a17f676ee4eaf24457c21bc230ba93b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 22:39:33 +0100 Subject: [PATCH 36/90] Remove newline from workflow file --- .github/workflows/publish.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 35cd8dd4..0a4e3e38 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -46,4 +46,3 @@ jobs: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} run: twine upload dist/* - From 9f92d2b2fbda78100bce50bf2263de8495d46b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 5 Jan 2025 23:05:30 +0100 Subject: [PATCH 37/90] Add pytest ini_options. Fix skipped test. --- .github/workflows/test.yml | 2 +- docs/source/contributors_guide/contributing.rst | 4 ++-- pyproject.toml | 3 +++ src/judge0/api.py | 7 +++++-- src/judge0/base_types.py | 2 ++ tests/test_api.py | 1 - 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 991d2d19..2beadbd3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,4 +39,4 @@ jobs: JUDGE0_EXTRA_CE_ENDPOINT: ${{ secrets.JUDGE0_EXTRA_CE_ENDPOINT }} run: | source venv/bin/activate - pytest -vv tests/ + pytest tests diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 094577c2..867f3f14 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -80,7 +80,7 @@ To run the tests locally, you can use the following command: .. code-block:: console - $ pytest -svv tests -k '' + $ pytest tests -k '' This will enable you to run a single test, without incurring the cost of running the full test suite. If you want to run the full test suite, you can @@ -88,7 +88,7 @@ use the following command: .. code-block:: console - $ pytest -svv tests + $ pytest tests or you can create a draft PR and let the CI pipeline run the tests for you. The CI pipeline will run the tests on every PR, using a private instance diff --git a/pyproject.toml b/pyproject.toml index 1fc29ce9..e8a4b3d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,3 +72,6 @@ extend-ignore = [ ] docstring-convention = "numpy" max-line-length = 88 + +[tool.pytest.ini_options] +addopts = "-vv" diff --git a/src/judge0/api.py b/src/judge0/api.py index 6c084713..e83ecf78 100644 --- a/src/judge0/api.py +++ b/src/judge0/api.py @@ -67,8 +67,11 @@ def _resolve_client( if isinstance(client, Flavor): return get_client(client) - if client is None and isinstance(submissions, Iterable) and len(submissions) == 0: - raise ValueError("Client cannot be determined from empty submissions.") + if client is None: + if ( + isinstance(submissions, Iterable) and len(submissions) == 0 + ) or submissions is None: + raise ValueError("Client cannot be determined from empty submissions.") # client is None and we have to determine a flavor of the client from the # the submission's languages. diff --git a/src/judge0/base_types.py b/src/judge0/base_types.py index dc18bdd7..94cedf83 100644 --- a/src/judge0/base_types.py +++ b/src/judge0/base_types.py @@ -16,6 +16,8 @@ class TestCase: """Test case data model.""" + __test__ = False # Needed to avoid pytest warning + input: Optional[str] = None expected_output: Optional[str] = None diff --git a/tests/test_api.py b/tests/test_api.py index 50a14644..3ba95267 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -48,7 +48,6 @@ def test_resolve_client_with_flavor( None, ], ) -@pytest.mark.skip def test_resolve_client_empty_submissions_argument(submissions): with pytest.raises(ValueError): _resolve_client(submissions=submissions) From ad8f8e04ee49949df67047d23166e75067d71ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 21 Jul 2025 16:31:40 +0200 Subject: [PATCH 38/90] Update README with Quick Start --- README.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/README.md b/README.md index de2703eb..4b0b8936 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,73 @@ # Judge0 Python SDK The official Python SDK for Judge0. +```python +>>> import judge0 +>>> result = judge0.run(source_code="print('hello, world')") +>>> result.stdout +'hello, world\n' +>>> result.time +0.987 +>>> result.memory +52440 +>>> for f in result: +... f.name +... f.content +... +'script.py' +b"print('hello, world')" +``` + +## Installation + +```bash +pip install judge0 +``` + +### Requirements + +- Python 3.9+ + +## Quick Start + +### Getting The API Key + +Get your API key from [Sulu](https://platform.sulu.sh/apis/judge0), [Rapid](https://rapidapi.com/organization/judge0), or [ATD](https://www.allthingsdev.co/publisher/profile/Herman%20Zvonimir%20Do%C5%A1ilovi%C4%87). + +#### Notes + +* [**Recommended**] Choose Sulu if you need pay-as-you-go (pey-per-use) pricing. +* Choose Rapid or ATD if you need a quota-based (volume-based) plan. +* Judge0 has two flavors: Judge0 CE and Judge0 Extra CE, and their difference is just in the languages they support. When choosing Sulu, your API key will work for both flavors, but for Rapid and ATD you will need to explicitly subscribe to both flavors if you want to use both. + +### Using Your API Key + +#### Option 1: Explicit Client Object + +Explicitly create a client object with your API key and pass it to Judge0 Python SDK functions. + +```python +import judge0 +client = judge0.SuluJudge0CE(api_key="xxx") +result = judge0.run(client=client, source_code="print('hello, world')") +print(result.stdout) +``` + +Other options include: +- `judge0.RapidJudge0CE` +- `judge0.ATDJudge0CE` +- `judge0.SuluJudge0ExtraCE` +- `judge0.RapidJudge0ExtraCE` +- `judge0.ATDJudge0ExtraCE` + +#### Option 2: Implicit Client Object + +Put your API key in one of the following environment variables, respectable to the provider that issued you the API key: `JUDGE0_SULU_API_KEY`, `JUDGE0_RAPID_API_KEY`, or `JUDGE0_ATD_API_KEY`. + +Judge0 Python SDK will automatically detect the environment variable and use it to create a client object that will be used for all API calls if you do not explicitly pass a client object. + +```python +import judge0 +result = judge0.run(source_code="print('hello, world')") +print(result.stdout) +``` From 0be30800f0d002b102a8977a3aba0cf38216e779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 21 Jul 2025 16:49:17 +0200 Subject: [PATCH 39/90] Add Examples --- README.md | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/README.md b/README.md index 4b0b8936..a9f17468 100644 --- a/README.md +++ b/README.md @@ -71,3 +71,93 @@ import judge0 result = judge0.run(source_code="print('hello, world')") print(result.stdout) ``` + +## Examples + +### Running C Programming Language + +```python +import judge0 + +source_code = """ +#include + +int main() { + printf("hello, world\\n"); + return 0; +} +""" + +result = judge0.run(source_code=source_code, language=judge0.C) +print(result.stdout) +``` + +### Running Java Programming Language + +```python +import judge0 + +source_code = """ +public class Main { + public static void main(String[] args) { + System.out.println("hello, world"); + } +} +""" + +result = judge0.run(source_code=source_code, language=judge0.JAVA) +print(result.stdout) +``` + +### Reading From Standard Input + +```python +import judge0 + +source_code = """ +#include + +int main() { + int a, b; + scanf("%d %d", &a, &b); + printf("%d\\n", a + b); + + char name[10]; + scanf("%s", name); + printf("Hello, %s!\\n", name); + + return 0; +} +""" + +stdin = """ +3 5 +Bob +""" + +result = judge0.run(source_code=source_code, stdin=stdin, language=judge0.C) +print(result.stdout) +``` + +### Test Cases + +```python +import judge0 + +results = judge0.run( + source_code="print(f'Hello, {input()}!')", + test_cases=[ + ("Bob", "Hello, Bob!"), # Test Case #1. Tuple with first value as standard input, second value as expected output. + { # Test Case #2. Dictionary with "input" and "expected_output" keys. + "input": "Alice", + "expected_output": "Hello, Alice!" + }, + ["Charlie", "Hello, Charlie!"], # Test Case #3. List with first value as standard input and second value as expected output. + ], +) + +for i, result in enumerate(results): + print(f"--- Test Case #{i + 1} ---") + print(result.stdout) + print(result.status) +``` From d41a05e88fc53a628c102a1530f3eabf822d3c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 21 Jul 2025 17:49:30 +0200 Subject: [PATCH 40/90] Test Cases And Multiple Languages --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/README.md b/README.md index a9f17468..8c2ef390 100644 --- a/README.md +++ b/README.md @@ -161,3 +161,47 @@ for i, result in enumerate(results): print(result.stdout) print(result.status) ``` + +### Test Cases And Multiple Languages + +```python +import judge0 + +submissions = [ + judge0.Submission( + source_code="print(f'Hello, {input()}!')", + language=judge0.PYTHON, + ), + judge0.Submission( + source_code=""" +#include + +int main() { + char name[10]; + scanf("%s", name); + printf("Hello, %s!\\n", name); + return 0; +} +""", + language=judge0.C, + ), +] + +test_cases=[ + ("Bob", "Hello, Bob!"), + ("Alice", "Hello, Alice!"), + ("Charlie", "Hello, Charlie!"), +] + +results = judge0.run(submissions=submissions, test_cases=test_cases) + +for i in range(len(submissions)): + print(f"--- Submission #{i + 1} ---") + + for j in range(len(test_cases)): + result = results[i * len(test_cases) + j] + + print(f"--- Test Case #{j + 1} ---") + print(result.stdout) + print(result.status) +``` From 428b01c0457465f43516a8b5007fb3e815d6401d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 21 Jul 2025 17:55:37 +0200 Subject: [PATCH 41/90] Add example for Asynchronous Execution --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 8c2ef390..2905bcc2 100644 --- a/README.md +++ b/README.md @@ -205,3 +205,16 @@ for i in range(len(submissions)): print(result.stdout) print(result.status) ``` + +### Asynchronous Execution + +```python +import judge0 + +submission = judge0.async_run(source_code="print('hello, world')") +print(submission.stdout) # Prints 'None' + +judge0.wait(submissions=submission) # Wait for the submission to finish. + +print(submission.stdout) # Prints 'hello, world' +``` From 8a0563093a0205707d504432cf8100350c733242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 21 Jul 2025 17:58:42 +0200 Subject: [PATCH 42/90] Add Get Languages example --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 2905bcc2..722a0c55 100644 --- a/README.md +++ b/README.md @@ -218,3 +218,11 @@ judge0.wait(submissions=submission) # Wait for the submission to finish. print(submission.stdout) # Prints 'hello, world' ``` + +### Get Languages + +```python +import judge0 +client = judge0.get_client() +print(client.get_languages()) +``` From cd0680608c407a4d81cdbe6b6ac054c8743981f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 26 Jul 2025 16:51:49 +0200 Subject: [PATCH 43/90] Update latest languages for Judge0 CE v1.14.0 --- src/judge0/data.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/judge0/data.py b/src/judge0/data.py index 39ad1b32..4e1aeec8 100644 --- a/src/judge0/data.py +++ b/src/judge0/data.py @@ -92,7 +92,7 @@ LanguageAlias.CPP_GCC: 105, LanguageAlias.CSHARP: 51, LanguageAlias.CSHARP_MONO: 51, - LanguageAlias.C_CLANG: 104, + LanguageAlias.C_CLANG: 110, LanguageAlias.C_GCC: 103, LanguageAlias.D: 56, LanguageAlias.DART: 90, @@ -101,7 +101,7 @@ LanguageAlias.EXECUTABLE: 44, LanguageAlias.FORTRAN: 59, LanguageAlias.FSHARP: 87, - LanguageAlias.GO: 95, + LanguageAlias.GO: 107, LanguageAlias.GROOVY: 88, LanguageAlias.HASKELL: 61, LanguageAlias.JAVA: 62, @@ -109,7 +109,7 @@ LanguageAlias.JAVASCRIPT: 102, LanguageAlias.JAVA_JDK: 91, LanguageAlias.JAVA_OPENJDK: 62, - LanguageAlias.KOTLIN: 78, + LanguageAlias.KOTLIN: 111, LanguageAlias.LUA: 64, LanguageAlias.MULTI_FILE: 89, LanguageAlias.OBJECTIVE_C: 79, @@ -120,12 +120,12 @@ LanguageAlias.PHP: 98, LanguageAlias.PLAIN_TEXT: 43, LanguageAlias.PROLOG: 69, - LanguageAlias.PYTHON: 100, + LanguageAlias.PYTHON: 109, LanguageAlias.PYTHON2: 70, - LanguageAlias.PYTHON3: 100, + LanguageAlias.PYTHON3: 109, LanguageAlias.R: 99, LanguageAlias.RUBY: 72, - LanguageAlias.RUST: 73, + LanguageAlias.RUST: 108, LanguageAlias.SCALA: 81, LanguageAlias.SQLITE: 82, LanguageAlias.SWIFT: 83, From 08ff35193a6fc6c1f5d8746f5581d61297c5e8d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 26 Jul 2025 16:54:35 +0200 Subject: [PATCH 44/90] Update latest languages for Judge0 Extra CE v1.14.0 --- src/judge0/data.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/judge0/data.py b/src/judge0/data.py index 4e1aeec8..ff4ed9ef 100644 --- a/src/judge0/data.py +++ b/src/judge0/data.py @@ -141,9 +141,9 @@ LanguageAlias.CPP_TEST: 12, LanguageAlias.CPP_TEST_CLANG: 15, LanguageAlias.CPP_TEST_GCC: 12, - LanguageAlias.CSHARP: 29, + LanguageAlias.CSHARP: 30, LanguageAlias.CSHARP_MONO: 22, - LanguageAlias.CSHARP_DOTNET: 29, + LanguageAlias.CSHARP_DOTNET: 30, LanguageAlias.CSHARP_TEST: 23, LanguageAlias.C_CLANG: 1, LanguageAlias.FSHARP: 24, @@ -155,12 +155,12 @@ LanguageAlias.MPI_PYTHON: 8, LanguageAlias.MULTI_FILE: 89, LanguageAlias.NIM: 9, - LanguageAlias.PYTHON: 25, + LanguageAlias.PYTHON: 32, LanguageAlias.PYTHON2: 26, LanguageAlias.PYTHON2_PYPY: 26, - LanguageAlias.PYTHON3: 25, + LanguageAlias.PYTHON3: 32, LanguageAlias.PYTHON3_PYPY: 28, - LanguageAlias.PYTHON_FOR_ML: 25, + LanguageAlias.PYTHON_FOR_ML: 32, LanguageAlias.VISUAL_BASIC: 20, }, } From 3080ac3480d7a0bab8cfcc99949ce6def80ad08e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 26 Jul 2025 16:58:55 +0200 Subject: [PATCH 45/90] Prepare for release 0.0.4 --- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e8a4b3d0..665f9ac2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.1.0.dev0" +version = "0.0.4" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.9" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index f5f33a5a..6e569c40 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -29,7 +29,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.1.0.dev0" +__version__ = "0.0.4" __all__ = [ "ATD", From 802ce9ee52b2c7bcb033c13e39eb8350865bdabb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 26 Jul 2025 17:10:06 +0200 Subject: [PATCH 46/90] Update working version. Update docs for creating a release. --- docs/source/contributors_guide/release_notes.rst | 3 ++- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/source/contributors_guide/release_notes.rst b/docs/source/contributors_guide/release_notes.rst index da50b25b..af4e92ab 100644 --- a/docs/source/contributors_guide/release_notes.rst +++ b/docs/source/contributors_guide/release_notes.rst @@ -18,6 +18,7 @@ Creating a release is a simple process that involves a few steps: #. Release title should be ``Judge0 Python SDK vX.Y.Z``. #. Release notes should include a changes from the previous release to the newest release. #. Use the `template `_ from the repo to organize the changes. + #. Click the `Generate release notes` button and use only `Full Changelog` section. #. Create the release. ("Set as a pre-release" should NOT be checked.) #. **Release on PyPI**: #. Use the `GitHub Actions workflow `_ to create a release on PyPI. @@ -29,4 +30,4 @@ that updates the working version in ``judge0/__init__.py`` and ``judge0/pyproje to the minor version. Merge the pull request and you're done! For example, if the new release was ``1.2.2``, the working version should be updated to ``1.3.0.dev0``. -You've successfully created a release! Congratulations! 🎉 \ No newline at end of file +You've successfully created a release! Congratulations! 🎉 diff --git a/pyproject.toml b/pyproject.toml index 665f9ac2..c869e238 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.0.4" +version = "0.0.5.dev0" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.9" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 6e569c40..a4686233 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -29,7 +29,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.0.4" +__version__ = "0.0.5.dev0" __all__ = [ "ATD", From de933507326b438dc8f1da63d11572902ae2e47f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 26 Jul 2025 18:04:33 +0200 Subject: [PATCH 47/90] Add warning when using preview client --- src/judge0/__init__.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index a4686233..3e487e0b 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -1,3 +1,4 @@ +import logging import os from typing import Union @@ -65,6 +66,8 @@ JUDGE0_IMPLICIT_CE_CLIENT = None JUDGE0_IMPLICIT_EXTRA_CE_CLIENT = None +logger = logging.getLogger(__name__) + def _get_implicit_client(flavor: Flavor) -> Client: global JUDGE0_IMPLICIT_CE_CLIENT, JUDGE0_IMPLICIT_EXTRA_CE_CLIENT @@ -104,6 +107,12 @@ def _get_implicit_client(flavor: Flavor) -> Client: def _get_preview_client(flavor: Flavor) -> Union[SuluJudge0CE, SuluJudge0ExtraCE]: + logger.warning( + "You are using a preview version of the client which is not recommended" + " for production.\n" + "For production, please specify your API key in the environment variable." + ) + if flavor == Flavor.CE: return SuluJudge0CE(retry_strategy=RegularPeriodRetry(0.5)) else: From 59175c5d106608c9261cf5d31909e6d58f9b6d08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 26 Jul 2025 18:11:24 +0200 Subject: [PATCH 48/90] Use default endpoints for JUDGE0_CE_ENDPOINT and JUDGE0_EXTRA_CE_ENDPOINT --- src/judge0/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 3e487e0b..4bb3d6c2 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -122,9 +122,11 @@ def _get_preview_client(flavor: Flavor) -> Union[SuluJudge0CE, SuluJudge0ExtraCE def _get_custom_client(flavor: Flavor) -> Union[Client, None]: from json import loads - ce_endpoint = os.getenv("JUDGE0_CE_ENDPOINT") + ce_endpoint = os.getenv("JUDGE0_CE_ENDPOINT", "https://ce.judge0.com") ce_auth_header = os.getenv("JUDGE0_CE_AUTH_HEADERS") - extra_ce_endpoint = os.getenv("JUDGE0_EXTRA_CE_ENDPOINT") + extra_ce_endpoint = os.getenv( + "JUDGE0_EXTRA_CE_ENDPOINT", "https://extra-ce.judge0.com" + ) extra_ce_auth_header = os.getenv("JUDGE0_EXTRA_CE_AUTH_HEADERS") if flavor == Flavor.CE and ce_endpoint is not None and ce_auth_header is not None: From dd3ba0cc1047d8c666e0cdddb0033acb4bbc3cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 26 Jul 2025 18:57:47 +0200 Subject: [PATCH 49/90] Add support for Judge0 Cloud client --- src/judge0/__init__.py | 16 +++++---- src/judge0/clients.py | 76 ++++++++++++++++++++++++++++++++++++++++-- tests/conftest.py | 26 +++++++++++++++ tests/test_clients.py | 2 ++ 4 files changed, 112 insertions(+), 8 deletions(-) diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 4bb3d6c2..65c842d7 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -19,6 +19,9 @@ ATDJudge0CE, ATDJudge0ExtraCE, Client, + Judge0Cloud, + Judge0CloudCE, + Judge0CloudExtraCE, Rapid, RapidJudge0CE, RapidJudge0ExtraCE, @@ -39,6 +42,9 @@ "Client", "File", "Filesystem", + "Judge0Cloud", + "Judge0CloudCE", + "Judge0CloudExtraCE", "Language", "LanguageAlias", "MaxRetries", @@ -54,12 +60,12 @@ "SuluJudge0ExtraCE", "TestCase", "async_execute", + "async_run", "execute", "get_client", - "async_run", - "sync_run", "run", "sync_execute", + "sync_run", "wait", ] @@ -122,11 +128,9 @@ def _get_preview_client(flavor: Flavor) -> Union[SuluJudge0CE, SuluJudge0ExtraCE def _get_custom_client(flavor: Flavor) -> Union[Client, None]: from json import loads - ce_endpoint = os.getenv("JUDGE0_CE_ENDPOINT", "https://ce.judge0.com") + ce_endpoint = os.getenv("JUDGE0_CE_ENDPOINT") ce_auth_header = os.getenv("JUDGE0_CE_AUTH_HEADERS") - extra_ce_endpoint = os.getenv( - "JUDGE0_EXTRA_CE_ENDPOINT", "https://extra-ce.judge0.com" - ) + extra_ce_endpoint = os.getenv("JUDGE0_EXTRA_CE_ENDPOINT") extra_ce_auth_header = os.getenv("JUDGE0_EXTRA_CE_AUTH_HEADERS") if flavor == Flavor.CE and ce_endpoint is not None and ce_auth_header is not None: diff --git a/src/judge0/clients.py b/src/judge0/clients.py index 2d8366a9..ae7c8d50 100644 --- a/src/judge0/clients.py +++ b/src/judge0/clients.py @@ -715,5 +715,77 @@ def __init__(self, api_key=None, **kwargs): super().__init__(self.DEFAULT_ENDPOINT, api_key, **kwargs) -CE = (SuluJudge0CE, RapidJudge0CE, ATDJudge0CE) -EXTRA_CE = (SuluJudge0ExtraCE, RapidJudge0ExtraCE, ATDJudge0ExtraCE) +class Judge0Cloud(Client): + """Base class for all Judge0 Cloud clients. + + Parameters + ---------- + endpoint : str + Default request endpoint. + auth_headers : str or dict + Judge0 Cloud authentication headers, either as a JSON string or a dictionary. + **kwargs : dict + Additional keyword arguments for the base Client. + """ + + def __init__(self, endpoint, auth_headers, **kwargs): + if isinstance(auth_headers, str): + from json import loads + + auth_headers = loads(auth_headers) + + super().__init__( + endpoint, + auth_headers, + **kwargs, + ) + + +class Judge0CloudCE(Judge0Cloud): + """Judge0 Cloud client for CE flavor. + + Parameters + ---------- + endpoint : str + Default request endpoint. + auth_headers : str or dict + Judge0 Cloud authentication headers, either as a JSON string or a dictionary. + **kwargs : dict + Additional keyword arguments for the base Client. + """ + + DEFAULT_ENDPOINT: ClassVar[str] = "https://ce.judge0.com" + HOME_URL: ClassVar[str] = "https://ce.judge0.com" + API_KEY_ENV: ClassVar[str] = "JUDGE0_CLOUD_CE_AUTH_HEADERS" + + def __init__(self, auth_headers, **kwargs): + super().__init__( + self.DEFAULT_ENDPOINT, + auth_headers, + **kwargs, + ) + + +class Judge0CloudExtraCE(Judge0Cloud): + """Judge0 Cloud client for Extra CE flavor. + + Parameters + ---------- + endpoint : str + Default request endpoint. + auth_headers : str or dict + Judge0 Cloud authentication headers, either as a JSON string or a dictionary. + **kwargs : dict + Additional keyword arguments for the base Client. + """ + + DEFAULT_ENDPOINT: ClassVar[str] = "https://extra-ce.judge0.com" + HOME_URL: ClassVar[str] = "https://extra-ce.judge0.com" + API_KEY_ENV: ClassVar[str] = "JUDGE0_CLOUD_EXTRA_CE_AUTH_HEADERS" + + def __init__(self, auth_headers, **kwargs): + super().__init__(self.DEFAULT_ENDPOINT, auth_headers, **kwargs) + + +CE = (Judge0CloudCE, SuluJudge0CE, RapidJudge0CE, ATDJudge0CE) +EXTRA_CE = (Judge0CloudExtraCE, SuluJudge0ExtraCE, RapidJudge0ExtraCE, ATDJudge0ExtraCE) diff --git a/tests/conftest.py b/tests/conftest.py index 4e1547c5..b8c950e7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -91,6 +91,26 @@ def sulu_extra_ce_client(): return clients.SuluJudge0ExtraCE(api_key) +@pytest.fixture(scope="session") +def judge0_cloud_ce_client(): + auth_headers = os.getenv("JUDGE0_CLOUD_CE_AUTH_HEADERS") + + if auth_headers is None: + return None + else: + return clients.Judge0CloudCE(auth_headers) + + +@pytest.fixture(scope="session") +def judge0_cloud_extra_ce_client(): + auth_headers = os.getenv("JUDGE0_CLOUD_EXTRA_CE_AUTH_HEADERS") + + if auth_headers is None: + return None + else: + return clients.Judge0CloudExtraCE(auth_headers) + + @pytest.fixture(scope="session") def preview_ce_client() -> clients.SuluJudge0CE: return clients.SuluJudge0CE(retry_strategy=RegularPeriodRetry(0.5)) @@ -104,6 +124,7 @@ def preview_extra_ce_client() -> clients.SuluJudge0ExtraCE: @pytest.fixture(scope="session") def ce_client( custom_ce_client, + judge0_cloud_ce_client, sulu_ce_client, rapid_ce_client, atd_ce_client, @@ -111,6 +132,8 @@ def ce_client( ): if custom_ce_client is not None: return custom_ce_client + if judge0_cloud_ce_client is not None: + return judge0_cloud_ce_client if sulu_ce_client is not None: return sulu_ce_client if rapid_ce_client is not None: @@ -126,6 +149,7 @@ def ce_client( @pytest.fixture(scope="session") def extra_ce_client( custom_extra_ce_client, + judge0_cloud_extra_ce_client, sulu_extra_ce_client, rapid_extra_ce_client, atd_extra_ce_client, @@ -133,6 +157,8 @@ def extra_ce_client( ): if custom_extra_ce_client is not None: return custom_extra_ce_client + if judge0_cloud_extra_ce_client is not None: + return judge0_cloud_extra_ce_client if sulu_extra_ce_client is not None: return sulu_extra_ce_client if rapid_extra_ce_client is not None: diff --git a/tests/test_clients.py b/tests/test_clients.py index c22c9dca..e5ccd458 100644 --- a/tests/test_clients.py +++ b/tests/test_clients.py @@ -7,6 +7,8 @@ "rapid_extra_ce_client", "sulu_ce_client", "sulu_extra_ce_client", + "judge0_cloud_ce_client", + "judge0_cloud_extra_ce_client", ) From 9f852ef26c9b1f1f6067b14a53b4aef22ca53431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Fri, 22 Aug 2025 03:27:37 +0200 Subject: [PATCH 50/90] Update latest ID for Scala --- src/judge0/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/judge0/data.py b/src/judge0/data.py index ff4ed9ef..5182e7a5 100644 --- a/src/judge0/data.py +++ b/src/judge0/data.py @@ -126,7 +126,7 @@ LanguageAlias.R: 99, LanguageAlias.RUBY: 72, LanguageAlias.RUST: 108, - LanguageAlias.SCALA: 81, + LanguageAlias.SCALA: 112, LanguageAlias.SQLITE: 82, LanguageAlias.SWIFT: 83, LanguageAlias.TYPESCRIPT: 101, From 8899a870278d7d122b2d299f2d0b2c99057a3a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Thu, 11 Sep 2025 20:23:48 +0200 Subject: [PATCH 51/90] Add .env.template. Allow empty auth headers for Judge0 Cloud. Use Judge0 Cloud as preview client. --- .env.template | 26 ++++++++++++++++++++++++++ src/judge0/__init__.py | 9 ++++----- src/judge0/clients.py | 6 +++--- 3 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 .env.template diff --git a/.env.template b/.env.template new file mode 100644 index 00000000..990a8d1d --- /dev/null +++ b/.env.template @@ -0,0 +1,26 @@ +# Sulu API Key. Get yours at https://platform.sulu.sh/portal/consumer/dashboard +# Subscribe here: https://platform.sulu.sh/apis/judge0 +JUDGE0_SULU_API_KEY= + +# Rapid API Key. Get yours at https://rapidapi.com/developer/apps +# Subscribe here: https://rapidapi.com/organization/judge0 +JUDGE0_RAPID_API_KEY= + +# ATD API Key. Get yours at https://www.allthingsdev.co/account/apps +# Subscribe here: https://www.allthingsdev.co/publisher/profile/Herman%20Zvonimir%20Došilović +JUDGE0_ATD_API_KEY= + +# Auth headers for Judge0 Cloud. +# Contact us to get your credentials. +JUDGE0_CLOUD_CE_AUTH_HEADERS= +JUDGE0_CLOUD_EXTRA_CE_AUTH_HEADERS= + +# Endpoint and auth headers for custom Judge0 CE instance. +# Use to connect to your own Judge0 CE server. +JUDGE0_CE_ENDPOINT= +JUDGE0_CE_AUTH_HEADERS= # Use "{}" for no auth headers. + +# Endpoint and auth headers for custom Judge0 Extra CE instance. +# Use to connect to your own Judge0 Extra CE server. +JUDGE0_EXTRA_CE_ENDPOINT= +JUDGE0_EXTRA_CE_AUTH_HEADERS= # Use "{}" for no auth headers. diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 65c842d7..d19f8df6 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -94,13 +94,12 @@ def _get_implicit_client(flavor: Flavor) -> Client: # Let's check if we can find a self-hosted client. client = _get_custom_client(flavor) - # Try to find one of the API keys JUDGE0_{SULU,RAPID,ATD}_API_KEY - # for hub clients. + # Try to find one of the API keys for hub clients. if client is None: client = _get_hub_client(flavor) # If we didn't find any of the possible keys, initialize - # the preview Sulu client based on the flavor. + # the preview client based on the flavor. if client is None: client = _get_preview_client(flavor) @@ -120,9 +119,9 @@ def _get_preview_client(flavor: Flavor) -> Union[SuluJudge0CE, SuluJudge0ExtraCE ) if flavor == Flavor.CE: - return SuluJudge0CE(retry_strategy=RegularPeriodRetry(0.5)) + return Judge0CloudCE() else: - return SuluJudge0ExtraCE(retry_strategy=RegularPeriodRetry(0.5)) + return Judge0CloudExtraCE() def _get_custom_client(flavor: Flavor) -> Union[Client, None]: diff --git a/src/judge0/clients.py b/src/judge0/clients.py index ae7c8d50..5fcaafe3 100644 --- a/src/judge0/clients.py +++ b/src/judge0/clients.py @@ -728,7 +728,7 @@ class Judge0Cloud(Client): Additional keyword arguments for the base Client. """ - def __init__(self, endpoint, auth_headers, **kwargs): + def __init__(self, endpoint, auth_headers=None, **kwargs): if isinstance(auth_headers, str): from json import loads @@ -758,7 +758,7 @@ class Judge0CloudCE(Judge0Cloud): HOME_URL: ClassVar[str] = "https://ce.judge0.com" API_KEY_ENV: ClassVar[str] = "JUDGE0_CLOUD_CE_AUTH_HEADERS" - def __init__(self, auth_headers, **kwargs): + def __init__(self, auth_headers=None, **kwargs): super().__init__( self.DEFAULT_ENDPOINT, auth_headers, @@ -783,7 +783,7 @@ class Judge0CloudExtraCE(Judge0Cloud): HOME_URL: ClassVar[str] = "https://extra-ce.judge0.com" API_KEY_ENV: ClassVar[str] = "JUDGE0_CLOUD_EXTRA_CE_AUTH_HEADERS" - def __init__(self, auth_headers, **kwargs): + def __init__(self, auth_headers=None, **kwargs): super().__init__(self.DEFAULT_ENDPOINT, auth_headers, **kwargs) From 0a96d03413f40888d2ee82adc88db29a661e76b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Thu, 11 Sep 2025 20:54:49 +0200 Subject: [PATCH 52/90] Add JUDGE0_CLOUD_CE_AUTH_HEADERS to test.yml workflow. --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2beadbd3..80f2e529 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,6 +37,8 @@ jobs: JUDGE0_EXTRA_CE_AUTH_HEADERS: ${{ secrets.JUDGE0_EXTRA_CE_AUTH_HEADERS }} JUDGE0_CE_ENDPOINT: ${{ secrets.JUDGE0_CE_ENDPOINT }} JUDGE0_EXTRA_CE_ENDPOINT: ${{ secrets.JUDGE0_EXTRA_CE_ENDPOINT }} + JUDGE0_CLOUD_CE_AUTH_HEADERS: ${{ secrets.JUDGE0_CLOUD_CE_AUTH_HEADERS }} + JUDGE0_CLOUD_EXTRA_CE_AUTH_HEADERS: ${{ secrets.JUDGE0_CLOUD_EXTRA_CE_AUTH_HEADERS }} run: | source venv/bin/activate pytest tests From 50896191391f958e77723d9c6e407ae49740cb26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 8 Nov 2025 21:54:14 +0100 Subject: [PATCH 53/90] Remove Sulu --- .env.template | 4 - .github/workflows/test.yml | 1 - README.md | 11 +-- docs/source/api/clients.rst | 9 --- .../contributors_guide/contributing.rst | 4 +- examples/sulu_clients.py | 22 ------ examples/sulu_submission.py | 32 -------- examples/sulu_submissions.py | 39 ---------- src/judge0/__init__.py | 8 +- src/judge0/clients.py | 74 +------------------ src/judge0/utils.py | 4 +- tests/conftest.py | 34 +-------- tests/test_api.py | 4 +- tests/test_clients.py | 2 - 14 files changed, 19 insertions(+), 229 deletions(-) delete mode 100644 examples/sulu_clients.py delete mode 100644 examples/sulu_submission.py delete mode 100644 examples/sulu_submissions.py diff --git a/.env.template b/.env.template index 990a8d1d..84f0e034 100644 --- a/.env.template +++ b/.env.template @@ -1,7 +1,3 @@ -# Sulu API Key. Get yours at https://platform.sulu.sh/portal/consumer/dashboard -# Subscribe here: https://platform.sulu.sh/apis/judge0 -JUDGE0_SULU_API_KEY= - # Rapid API Key. Get yours at https://rapidapi.com/developer/apps # Subscribe here: https://rapidapi.com/organization/judge0 JUDGE0_RAPID_API_KEY= diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 80f2e529..affae10a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,7 +32,6 @@ jobs: env: # Add necessary api keys as env variables. JUDGE0_ATD_API_KEY: ${{ secrets.JUDGE0_ATD_API_KEY }} JUDGE0_RAPID_API_KEY: ${{ secrets.JUDGE0_RAPID_API_KEY }} - JUDGE0_SULU_API_KEY: ${{ secrets.JUDGE0_SULU_API_KEY }} JUDGE0_CE_AUTH_HEADERS: ${{ secrets.JUDGE0_CE_AUTH_HEADERS }} JUDGE0_EXTRA_CE_AUTH_HEADERS: ${{ secrets.JUDGE0_EXTRA_CE_AUTH_HEADERS }} JUDGE0_CE_ENDPOINT: ${{ secrets.JUDGE0_CE_ENDPOINT }} diff --git a/README.md b/README.md index 722a0c55..33eee1e8 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,11 @@ pip install judge0 ### Getting The API Key -Get your API key from [Sulu](https://platform.sulu.sh/apis/judge0), [Rapid](https://rapidapi.com/organization/judge0), or [ATD](https://www.allthingsdev.co/publisher/profile/Herman%20Zvonimir%20Do%C5%A1ilovi%C4%87). +Get your API key from [Rapid](https://rapidapi.com/organization/judge0), or [ATD](https://www.allthingsdev.co/publisher/profile/Herman%20Zvonimir%20Do%C5%A1ilovi%C4%87). #### Notes -* [**Recommended**] Choose Sulu if you need pay-as-you-go (pey-per-use) pricing. -* Choose Rapid or ATD if you need a quota-based (volume-based) plan. -* Judge0 has two flavors: Judge0 CE and Judge0 Extra CE, and their difference is just in the languages they support. When choosing Sulu, your API key will work for both flavors, but for Rapid and ATD you will need to explicitly subscribe to both flavors if you want to use both. +* Judge0 has two flavors: Judge0 CE and Judge0 Extra CE, and their difference is just in the languages they support. When choosing Rapid and ATD you will need to explicitly subscribe to both flavors if you want to use both. ### Using Your API Key @@ -48,7 +46,7 @@ Explicitly create a client object with your API key and pass it to Judge0 Python ```python import judge0 -client = judge0.SuluJudge0CE(api_key="xxx") +client = judge0.RapidJudge0CE(api_key="xxx") result = judge0.run(client=client, source_code="print('hello, world')") print(result.stdout) ``` @@ -56,13 +54,12 @@ print(result.stdout) Other options include: - `judge0.RapidJudge0CE` - `judge0.ATDJudge0CE` -- `judge0.SuluJudge0ExtraCE` - `judge0.RapidJudge0ExtraCE` - `judge0.ATDJudge0ExtraCE` #### Option 2: Implicit Client Object -Put your API key in one of the following environment variables, respectable to the provider that issued you the API key: `JUDGE0_SULU_API_KEY`, `JUDGE0_RAPID_API_KEY`, or `JUDGE0_ATD_API_KEY`. +Put your API key in one of the following environment variables, respectable to the provider that issued you the API key: `JUDGE0_RAPID_API_KEY`, or `JUDGE0_ATD_API_KEY`. Judge0 Python SDK will automatically detect the environment variable and use it to create a client object that will be used for all API calls if you do not explicitly pass a client object. diff --git a/docs/source/api/clients.rst b/docs/source/api/clients.rst index b4d15c94..29e7e45a 100644 --- a/docs/source/api/clients.rst +++ b/docs/source/api/clients.rst @@ -35,12 +35,3 @@ Clients Module .. autoclass:: judge0.clients.RapidJudge0ExtraCE :show-inheritance: - -.. autoclass:: judge0.clients.Sulu - :show-inheritance: - -.. autoclass:: judge0.clients.SuluJudge0CE - :show-inheritance: - -.. autoclass:: judge0.clients.SuluJudge0ExtraCE - :show-inheritance: \ No newline at end of file diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 867f3f14..4c1623b9 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -52,8 +52,8 @@ Testing .. warning:: If you are implementing features or fixing bugs, you are expected to have - all of the three API keys (ATD, Sulu, and RapidAPI) setup and set in you - environment variables - ``JUDGE0_SULU_API_KEY``, ``JUDGE0_RAPID_API_KEY``, + all API keys (RapidAPI and ATD) setup and set in you + environment variables - ``JUDGE0_RAPID_API_KEY``, and ``JUDGE0_ATD_API_KEY``. Every bug fix or new feature should have tests for it. The tests are located in diff --git a/examples/sulu_clients.py b/examples/sulu_clients.py deleted file mode 100644 index b9c60874..00000000 --- a/examples/sulu_clients.py +++ /dev/null @@ -1,22 +0,0 @@ -import os - -import judge0 -from dotenv import load_dotenv - -load_dotenv() - -api_key = os.getenv("JUDGE0_SULU_API_KEY") - -client_ce = judge0.SuluJudge0CE(api_key=api_key) -print(client_ce.get_about()) -print(client_ce.get_config_info()) -print(client_ce.get_statuses()) -print(client_ce.get_languages()) -print(client_ce.get_language(language_id=42)) - -client_extra_ce = judge0.SuluJudge0ExtraCE(api_key=api_key) -print(client_extra_ce.get_about()) -print(client_extra_ce.get_config_info()) -print(client_extra_ce.get_statuses()) -print(client_extra_ce.get_languages()) -print(client_extra_ce.get_language(language_id=24)) diff --git a/examples/sulu_submission.py b/examples/sulu_submission.py deleted file mode 100644 index ef744927..00000000 --- a/examples/sulu_submission.py +++ /dev/null @@ -1,32 +0,0 @@ -import os - -import judge0 - -from dotenv import load_dotenv - -load_dotenv() - -api_key = os.getenv("JUDGE0_SULU_API_KEY") - - -def run_example(client_class, language_id): - client = client_class(api_key=api_key) - submission = judge0.Submission( - source_code="print('Hello Judge0')", - language=language_id, - expected_output="Hello Judge0", - ) - - judge0.execute(client=client, submissions=submission) - - print(f"{submission.status=}") - print(f"{submission.stdout=}") - - -def main(): - run_example(judge0.SuluJudge0CE, 100) - run_example(judge0.SuluJudge0ExtraCE, 25) - - -if __name__ == "__main__": - main() diff --git a/examples/sulu_submissions.py b/examples/sulu_submissions.py deleted file mode 100644 index b7088701..00000000 --- a/examples/sulu_submissions.py +++ /dev/null @@ -1,39 +0,0 @@ -import os - -import judge0 - -from dotenv import load_dotenv - -load_dotenv() - -api_key = os.getenv("JUDGE0_SULU_API_KEY") - - -def run_example(client_class, lang_id_python, lang_id_c): - client = client_class(api_key=api_key) - submission1 = judge0.Submission( - source_code="print('Hello Judge0')", - language=lang_id_python, - expected_output="Hello Judge0", - ) - submission2 = judge0.Submission( - source_code='#include \n\nint main() {\n printf("Hello World!");\n return 0;\n}', - language=lang_id_c, - expected_output="Hello World!", - ) - - submissions = [submission1, submission2] - judge0.execute(client=client, submissions=submissions) - - for submission in submissions: - print(f"{submission.status=}") - print(f"{submission.stdout=}") - - -def main(): - run_example(judge0.SuluJudge0CE, 100, 50) - run_example(judge0.SuluJudge0ExtraCE, 25, 1) - - -if __name__ == "__main__": - main() diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index d19f8df6..97c9a7e4 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -25,9 +25,6 @@ Rapid, RapidJudge0CE, RapidJudge0ExtraCE, - Sulu, - SuluJudge0CE, - SuluJudge0ExtraCE, ) from .filesystem import File, Filesystem from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry @@ -55,9 +52,6 @@ "RegularPeriodRetry", "Status", "Submission", - "Sulu", - "SuluJudge0CE", - "SuluJudge0ExtraCE", "TestCase", "async_execute", "async_run", @@ -111,7 +105,7 @@ def _get_implicit_client(flavor: Flavor) -> Client: return client -def _get_preview_client(flavor: Flavor) -> Union[SuluJudge0CE, SuluJudge0ExtraCE]: +def _get_preview_client(flavor: Flavor) -> Union[Judge0CloudCE, Judge0CloudExtraCE]: logger.warning( "You are using a preview version of the client which is not recommended" " for production.\n" diff --git a/src/judge0/clients.py b/src/judge0/clients.py index 5fcaafe3..49d1ac61 100644 --- a/src/judge0/clients.py +++ b/src/judge0/clients.py @@ -23,11 +23,11 @@ class Client: ---------- API_KEY_ENV : str Environment variable where judge0-python should look for API key for - the client. Set to default values for ATD, RapidAPI, and Sulu clients. + the client. Set to default values for RapidAPI and ATD clients. """ # Environment variable where judge0-python should look for API key for - # the client. Set to default values for ATD, RapidAPI, and Sulu clients. + # the client. Set to default values for RapidAPI and ATD clients. API_KEY_ENV: ClassVar[str] = None def __init__( @@ -649,72 +649,6 @@ def __init__(self, api_key, **kwargs): ) -class Sulu(Client): - """Base class for all Sulu clients. - - Parameters - ---------- - endpoint : str - Default request endpoint. - api_key : str, optional - Sulu API key. - **kwargs : dict - Additional keyword arguments for the base Client. - """ - - API_KEY_ENV: ClassVar[str] = "JUDGE0_SULU_API_KEY" - - def __init__(self, endpoint, api_key=None, **kwargs): - self.api_key = api_key - super().__init__( - endpoint, - {"Authorization": f"Bearer {api_key}"} if api_key else None, - **kwargs, - ) - - -class SuluJudge0CE(Sulu): - """Sulu client for CE flavor. - - Parameters - ---------- - api_key : str, optional - Sulu API key. - **kwargs : dict - Additional keyword arguments for the base Client. - """ - - DEFAULT_ENDPOINT: ClassVar[str] = "https://judge0-ce.p.sulu.sh" - HOME_URL: ClassVar[str] = "https://sparkhub.sulu.sh/apis/judge0/judge0-ce/readme" - - def __init__(self, api_key=None, **kwargs): - super().__init__( - self.DEFAULT_ENDPOINT, - api_key, - **kwargs, - ) - - -class SuluJudge0ExtraCE(Sulu): - """Sulu client for Extra CE flavor. - - Parameters - ---------- - api_key : str - Sulu API key. - **kwargs : dict - Additional keyword arguments for the base Client. - """ - - DEFAULT_ENDPOINT: ClassVar[str] = "https://judge0-extra-ce.p.sulu.sh" - HOME_URL: ClassVar[str] = ( - "https://sparkhub.sulu.sh/apis/judge0/judge0-extra-ce/readme" - ) - - def __init__(self, api_key=None, **kwargs): - super().__init__(self.DEFAULT_ENDPOINT, api_key, **kwargs) - - class Judge0Cloud(Client): """Base class for all Judge0 Cloud clients. @@ -787,5 +721,5 @@ def __init__(self, auth_headers=None, **kwargs): super().__init__(self.DEFAULT_ENDPOINT, auth_headers, **kwargs) -CE = (Judge0CloudCE, SuluJudge0CE, RapidJudge0CE, ATDJudge0CE) -EXTRA_CE = (Judge0CloudExtraCE, SuluJudge0ExtraCE, RapidJudge0ExtraCE, ATDJudge0ExtraCE) +CE = (Judge0CloudCE, RapidJudge0CE, ATDJudge0CE) +EXTRA_CE = (Judge0CloudExtraCE, RapidJudge0ExtraCE, ATDJudge0ExtraCE) diff --git a/src/judge0/utils.py b/src/judge0/utils.py index e38b41f5..94eb5efc 100644 --- a/src/judge0/utils.py +++ b/src/judge0/utils.py @@ -23,14 +23,14 @@ def wrapper(*args, **kwargs): return func(*args, **kwargs) except HTTPError as err: if is_http_too_many_requests_error(exception=err): - # If the raised exception is inside the one of the Sulu clients + # If the raised exception is inside the one of the Judge0 Cloud clients # let's check if we are dealing with the implicit client. if args: instance = args[0] class_name = instance.__class__.__name__ # Check if we are using a preview version of the client. if ( - class_name in ("SuluJudge0CE", "SuluJudge0ExtraCE") + class_name in ("Judge0CloudCE", "Judge0CloudExtraCE") and instance.api_key is None ): raise PreviewClientLimitError( diff --git a/tests/conftest.py b/tests/conftest.py index b8c950e7..38a85732 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -71,26 +71,6 @@ def rapid_extra_ce_client(): return clients.RapidJudge0ExtraCE(api_key) -@pytest.fixture(scope="session") -def sulu_ce_client(): - api_key = os.getenv("JUDGE0_SULU_API_KEY") - - if api_key is None: - return None - else: - return clients.SuluJudge0CE(api_key) - - -@pytest.fixture(scope="session") -def sulu_extra_ce_client(): - api_key = os.getenv("JUDGE0_SULU_API_KEY") - - if api_key is None: - return None - else: - return clients.SuluJudge0ExtraCE(api_key) - - @pytest.fixture(scope="session") def judge0_cloud_ce_client(): auth_headers = os.getenv("JUDGE0_CLOUD_CE_AUTH_HEADERS") @@ -112,20 +92,19 @@ def judge0_cloud_extra_ce_client(): @pytest.fixture(scope="session") -def preview_ce_client() -> clients.SuluJudge0CE: - return clients.SuluJudge0CE(retry_strategy=RegularPeriodRetry(0.5)) +def preview_ce_client() -> clients.Judge0CloudCE: + return clients.Judge0CloudCE(retry_strategy=RegularPeriodRetry(0.5)) @pytest.fixture(scope="session") -def preview_extra_ce_client() -> clients.SuluJudge0ExtraCE: - return clients.SuluJudge0ExtraCE(retry_strategy=RegularPeriodRetry(0.5)) +def preview_extra_ce_client() -> clients.Judge0CloudExtraCE: + return clients.Judge0CloudExtraCE(retry_strategy=RegularPeriodRetry(0.5)) @pytest.fixture(scope="session") def ce_client( custom_ce_client, judge0_cloud_ce_client, - sulu_ce_client, rapid_ce_client, atd_ce_client, preview_ce_client, @@ -134,8 +113,6 @@ def ce_client( return custom_ce_client if judge0_cloud_ce_client is not None: return judge0_cloud_ce_client - if sulu_ce_client is not None: - return sulu_ce_client if rapid_ce_client is not None: return rapid_ce_client if atd_ce_client is not None: @@ -150,7 +127,6 @@ def ce_client( def extra_ce_client( custom_extra_ce_client, judge0_cloud_extra_ce_client, - sulu_extra_ce_client, rapid_extra_ce_client, atd_extra_ce_client, preview_extra_ce_client, @@ -159,8 +135,6 @@ def extra_ce_client( return custom_extra_ce_client if judge0_cloud_extra_ce_client is not None: return judge0_cloud_extra_ce_client - if sulu_extra_ce_client is not None: - return sulu_extra_ce_client if rapid_extra_ce_client is not None: return rapid_extra_ce_client if atd_extra_ce_client is not None: diff --git a/tests/test_api.py b/tests/test_api.py index 3ba95267..b58aa24e 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -9,8 +9,8 @@ "atd_extra_ce_client", "rapid_ce_client", "rapid_extra_ce_client", - "sulu_ce_client", - "sulu_extra_ce_client", + "judge0_cloud_ce_client", + "judge0_cloud_extra_ce_client", ) diff --git a/tests/test_clients.py b/tests/test_clients.py index e5ccd458..98eb45e4 100644 --- a/tests/test_clients.py +++ b/tests/test_clients.py @@ -5,8 +5,6 @@ "atd_extra_ce_client", "rapid_ce_client", "rapid_extra_ce_client", - "sulu_ce_client", - "sulu_extra_ce_client", "judge0_cloud_ce_client", "judge0_cloud_extra_ce_client", ) From 70f09c987aa70f48995eccee46c6d73e2a34abd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 8 Nov 2025 22:23:20 +0100 Subject: [PATCH 54/90] Deprecate Python 3.9. Update logo and year in the docs. --- .github/workflows/docs.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/test.yml | 4 ++-- README.md | 2 +- docs/assets/logo.png | Bin 31233 -> 247958 bytes docs/source/conf.py | 2 +- .../contributors_guide/contributing.rst | 6 +++--- pyproject.toml | 5 ++--- 8 files changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 11d9d8e3..b8e06c26 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -24,7 +24,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.9" + python-version: "3.10" - name: Install dependencies run: | diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0a4e3e38..0ab3dff3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,7 +21,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.9 + python-version: 3.10 # Install build and twine - name: Install Build Tools diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index affae10a..31c375ad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,10 +18,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v3 with: - python-version: "3.9" + python-version: "3.10" - name: Install dependencies run: | python -m venv venv diff --git a/README.md b/README.md index 33eee1e8..a9eb6005 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ pip install judge0 ### Requirements -- Python 3.9+ +- Python 3.10+ ## Quick Start diff --git a/docs/assets/logo.png b/docs/assets/logo.png index 9661bbb3b66cba7024393224b4afefdedb102674..2b5912032eaa9bdab3167a48822f49e5f0bd5516 100644 GIT binary patch literal 247958 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 Vb~%Q&fr;v&;@i@t&(2}2l~zRo5E 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%0DEPDZ*U~NZ{Bgz-?UyLAKS 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

p4zq%} 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ʁ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 literal 31233 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

VJca6nosg~zu%#x_>VE4K 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 diff --git a/docs/source/conf.py b/docs/source/conf.py index ea153536..f4c02c87 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -13,7 +13,7 @@ from sphinxawesome_theme.postprocess import Icons project = "Judge0 Python SDK" -copyright = "2024, Judge0" +copyright = "2025, Judge0" author = "Judge0" release = "" diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 4c1623b9..237bab67 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -4,20 +4,20 @@ Contributing Preparing the development setup ------------------------------- -1. Install Python 3.9 +1. Install Python 3.10 .. code-block:: console $ sudo add-apt-repository ppa:deadsnakes/ppa $ sudo apt update - $ sudo apt install python3.9 python3.9-venv + $ sudo apt install python3.10 python3.10-venv 2. Clone the repo, create and activate a new virtual environment .. code-block:: console $ cd judge0-python - $ python3.9 -m venv venv + $ python3.10 -m venv venv $ . venv/bin/activate 3. Install the library and development dependencies diff --git a/pyproject.toml b/pyproject.toml index c869e238..ac58706c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "judge0" version = "0.0.5.dev0" description = "The official Python SDK for Judge0." readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" authors = [{ name = "Judge0", email = "contact@judge0.com" }] classifiers = [ "Intended Audience :: Developers", @@ -11,7 +11,6 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", @@ -46,7 +45,7 @@ test = [ "flake8-docstrings==1.7.0", ] docs = [ - "sphinx==7.4.7", + "sphinx==8.1.3", "sphinxawesome-theme==5.3.2", "sphinx-autodoc-typehints==2.3.0", "sphinx-multiversion==0.2.4", From db408cd4ed64a026559bb4f8cdf12e9ac771a75d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 8 Nov 2025 22:40:16 +0100 Subject: [PATCH 55/90] Bump version to 0.0.5 --- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ac58706c..53718b3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.0.5.dev0" +version = "0.0.5" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.10" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 97c9a7e4..387b651f 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -30,7 +30,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.0.5.dev0" +__version__ = "0.0.5" __all__ = [ "ATD", From 26c5c84e3d320fc32931319d9b5c8d87321a8116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 8 Nov 2025 23:06:10 +0100 Subject: [PATCH 56/90] Fix python-version in publish.yml --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0ab3dff3..b768eb27 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,7 +21,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.10 + python-version: "3.10" # Install build and twine - name: Install Build Tools From 3a8f970e469415deaba375a9224a2ea657d2088a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sat, 8 Nov 2025 23:09:00 +0100 Subject: [PATCH 57/90] Bump to new dev release --- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 53718b3d..8a4d7a34 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.0.5" +version = "0.1.0.dev0" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.10" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 387b651f..b2a4dcb4 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -30,7 +30,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.0.5" +__version__ = "0.1.0.dev0" __all__ = [ "ATD", From 417648bb838f8e73d884df61178c86f88748aecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 03:45:18 +0100 Subject: [PATCH 58/90] Add example for running LLM code --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/README.md b/README.md index a9eb6005..ca554a1a 100644 --- a/README.md +++ b/README.md @@ -223,3 +223,34 @@ import judge0 client = judge0.get_client() print(client.get_languages()) ``` + +### Running LLM-Generated Code + +```python +import os +from ollama import Client +import judge0 + +# Get your Ollama Cloud API key from https://ollama.com. +client = Client( + host="https://ollama.com", + headers={"Authorization": "Bearer " + os.environ.get("OLLAMA_API_KEY")}, +) + +system = "You are a helpful assistant that can execute Python code. Only respond with the code to be executed and nothing else. Strip backticks in code blocks." +prompt = "Calculate how many r's are in the word 'strawberry'." + +response = client.chat( + model="gpt-oss:120b-cloud", + messages=[ + {"role": "system", "content": system}, + {"role": "user", "content": prompt}, + ], +) + +code = response["message"]["content"] +print(f"Generated code:\n{code}") + +result = judge0.run(source_code=code, language=judge0.PYTHON) +print(f"Execution result:\n{result.stdout}") +``` From 9478549635fecc0fe2287e9d4f7590791dcde7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 03:48:33 +0100 Subject: [PATCH 59/90] Add hello, world example --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index ca554a1a..4caf7db4 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,13 @@ print(result.stdout) ``` ## Examples +### hello, world + +```python +import judge0 +result = judge0.run(source_code="print('hello, world')") +print(result.stdout) +``` ### Running C Programming Language From 8d93f74569a0ea78a77543a39c4cf2c82d724413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 04:33:30 +0100 Subject: [PATCH 60/90] Add Tool Calling Example --- README.md | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/README.md b/README.md index 4caf7db4..9d5aa122 100644 --- a/README.md +++ b/README.md @@ -233,6 +233,8 @@ print(client.get_languages()) ### Running LLM-Generated Code +#### Simple + ```python import os from ollama import Client @@ -261,3 +263,59 @@ print(f"Generated code:\n{code}") result = judge0.run(source_code=code, language=judge0.PYTHON) print(f"Execution result:\n{result.stdout}") ``` + +#### Tool Calling (a.k.a. Function Calling) + +```python +import os +from ollama import Client +import judge0 + +# Get your Ollama Cloud API key from https://ollama.com. +client = Client( + host="https://ollama.com", + headers={"Authorization": "Bearer " + os.environ.get("OLLAMA_API_KEY")}, +) + +model="qwen3-coder:480b-cloud" + +messages=[ + {"role": "user", "content": "Calculate how many r's are in the word 'strawberry'."}, +] + +tools = [{ + "type": "function", + "function": { + "name": "execute_python", + "description": "Execute Python code and return result", + "parameters": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "The Python code to execute" + } + }, + "required": ["code"] + } + } +}] + +response = client.chat(model=model, messages=messages, tools=tools) + +response_message = response["message"] +messages.append(response_message) + +if response_message.tool_calls: + for tool_call in response_message.tool_calls: + if tool_call.function.name == "execute_python": + result = judge0.run(source_code=tool_call.function.arguments["code"], language=judge0.PYTHON) + messages.append({ + "role": "tool", + "tool_name": "execute_python", + "content": result.stdout, + }) + +final_response = client.chat(model=model, messages=messages) +print(final_response["message"]["content"]) +``` From 93c6bdab03abf0a9922e60ef300010afa90b16e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 13:40:09 +0100 Subject: [PATCH 61/90] Add Filesystem example --- README.md | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9d5aa122..0cd7054b 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ print(result.stdout) ```python import judge0 -result = judge0.run(source_code="print('hello, world')") +result = judge0.run(source_code="print('hello, world')", language=judge0.PYTHON) print(result.stdout) ``` @@ -233,7 +233,7 @@ print(client.get_languages()) ### Running LLM-Generated Code -#### Simple +#### Simple Example with Ollama ```python import os @@ -264,7 +264,7 @@ result = judge0.run(source_code=code, language=judge0.PYTHON) print(f"Execution result:\n{result.stdout}") ``` -#### Tool Calling (a.k.a. Function Calling) +#### Tool Calling (a.k.a. Function Calling) with Ollama ```python import os @@ -319,3 +319,38 @@ if response_message.tool_calls: final_response = client.chat(model=model, messages=messages) print(final_response["message"]["content"]) ``` + +### Filesystem + +```python +import judge0 +from judge0 import Filesystem, File, Submission + +fs = Filesystem( + content=[ + File(name="./my_dir1/my_file1.txt", content="hello from my_file.txt"), + ] +) + +source_code = """ +cat ./my_dir1/my_file1.txt + +mkdir my_dir2 +echo "hello, world" > ./my_dir2/my_file2.txt +""" + +submission = Submission( + source_code=source_code, + language=judge0.BASH, + additional_files=fs, +) + +result = judge0.run(submissions=submission) +fs = Filesystem(content=result.post_execution_filesystem) + +print(result.stdout) + +matches = [f for f in fs if f.name == "my_dir2/my_file2.txt"] +f = matches[0] if matches else None +print(f) +``` From 2000ef6251015fa61a47c5b4b9b19ad15600068c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 13:50:26 +0100 Subject: [PATCH 62/90] Update Filesystem example --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 0cd7054b..12a47643 100644 --- a/README.md +++ b/README.md @@ -346,11 +346,9 @@ submission = Submission( ) result = judge0.run(submissions=submission) -fs = Filesystem(content=result.post_execution_filesystem) - print(result.stdout) -matches = [f for f in fs if f.name == "my_dir2/my_file2.txt"] +matches = [f for f in result.post_execution_filesystem if f.name == "my_dir2/my_file2.txt"] f = matches[0] if matches else None print(f) ``` From 1b1f8b19607e120058861c7e870952d2d5e31d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 20:56:38 +0100 Subject: [PATCH 63/90] Switch to uv for project management (#20) * Remove .python-version from gitignore. Add uv.lock and .python-version. * Adapt the pyproject.toml. Update contributing docs. Update docs build Makefile. * Update workflows. --- .github/workflows/docs.yml | 91 +- .github/workflows/publish.yml | 59 +- .github/workflows/test.yml | 12 +- .gitignore | 2 +- .python-version | 1 + docs/Makefile | 2 +- .../contributors_guide/contributing.rst | 31 +- pyproject.toml | 8 +- uv.lock | 1305 +++++++++++++++++ 9 files changed, 1404 insertions(+), 107 deletions(-) create mode 100644 .python-version create mode 100644 uv.lock diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index b8e06c26..182c3f95 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -5,63 +5,62 @@ on: push: branches: ["master"] - jobs: build: runs-on: ubuntu-24.04 permissions: contents: write steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - fetch-depth: 0 # Fetch the full history - ref: ${{ github.ref }} # Check out the current branch or tag + - uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 # Fetch the full history + ref: ${{ github.ref }} # Check out the current branch or tag - - name: Fetch tags only - run: git fetch --tags --no-recurse-submodules + - name: Fetch tags only + run: git fetch --tags --no-recurse-submodules - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.10" + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -e .[docs] + - name: Install uv and dependencies + run: | + curl -LsSf https://astral.sh/uv/0.9.8/install.sh | sh + uv sync --group docs - - name: Build documentation - run: sphinx-multiversion docs/source docs/build/html --keep-going --no-color + - name: Build documentation + run: uv run sphinx-multiversion docs/source docs/build/html --keep-going --no-color - - name: Get the latest tag - run: | - # Fetch all tags - git fetch --tags - # Get the latest tag - latest_tag=$(git tag --sort=-creatordate | head -n 1) - echo "LATEST_RELEASE=$latest_tag" >> $GITHUB_ENV + - name: Get the latest tag + run: | + # Fetch all tags + git fetch --tags + # Get the latest tag + latest_tag=$(git tag --sort=-creatordate | head -n 1) + echo "LATEST_RELEASE=$latest_tag" >> $GITHUB_ENV - - name: Generate index.html for judge0.github.io/judge0-python. - run: | - echo ' - - - - - ' > docs/build/html/index.html - env: - latest_release: ${{ env.LATEST_RELEASE }} + - name: Generate index.html for judge0.github.io/judge0-python. + run: | + echo ' + + + + + ' > docs/build/html/index.html + env: + latest_release: ${{ env.LATEST_RELEASE }} - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: html-docs - path: docs/build/html/ + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: html-docs + path: docs/build/html/ - - name: Deploy - uses: peaceiris/actions-gh-pages@v3 - if: github.ref == 'refs/heads/master' - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: docs/build/html + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + if: github.ref == 'refs/heads/master' + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: docs/build/html diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b768eb27..ab561792 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,39 +10,30 @@ on: jobs: publish: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - # Checkout the repository - - name: Checkout Code - uses: actions/checkout@v3 - - # Set up Python environment - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.10" - - # Install build and twine - - name: Install Build Tools - run: | - python -m pip install --upgrade pip - pip install build twine - - # Build the package - - name: Build the Package - run: python -m build - - - name: Publish to Test PyPI - if: github.event.inputs.repository == 'test' - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.TEST_PYPI_TOKEN }} - run: twine upload --repository-url https://test.pypi.org/legacy/ dist/* - - - name: Publish to Regular PyPI - if: github.event.inputs.repository == 'pypi' - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - run: twine upload dist/* + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install uv + run: curl -LsSf https://astral.sh/uv/0.9.8/install.sh | sh + + - name: Build package with uv + run: uv build + + - name: Publish to Test PyPI + if: github.event.inputs.repository == 'test' + env: + UV_PUBLISH_TOKEN: ${{ secrets.TEST_PYPI_TOKEN }} + run: uv publish --token $UV_PUBLISH_TOKEN --repository testpypi + + - name: Publish to Regular PyPI + if: github.event.inputs.repository == 'pypi' + env: + UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }} + run: uv publish --token $UV_PUBLISH_TOKEN diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 31c375ad..a2aa0db1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,12 +22,10 @@ jobs: uses: actions/setup-python@v3 with: python-version: "3.10" - - name: Install dependencies + - name: Install uv and project run: | - python -m venv venv - source venv/bin/activate - python -m pip install --upgrade pip - pip install -e .[test] + curl -LsSf https://astral.sh/uv/0.9.8/install.sh | sh + uv sync --group test - name: Test with pytest env: # Add necessary api keys as env variables. JUDGE0_ATD_API_KEY: ${{ secrets.JUDGE0_ATD_API_KEY }} @@ -38,6 +36,4 @@ jobs: JUDGE0_EXTRA_CE_ENDPOINT: ${{ secrets.JUDGE0_EXTRA_CE_ENDPOINT }} JUDGE0_CLOUD_CE_AUTH_HEADERS: ${{ secrets.JUDGE0_CLOUD_CE_AUTH_HEADERS }} JUDGE0_CLOUD_EXTRA_CE_AUTH_HEADERS: ${{ secrets.JUDGE0_CLOUD_EXTRA_CE_AUTH_HEADERS }} - run: | - source venv/bin/activate - pytest tests + run: uv run pytest tests diff --git a/.gitignore b/.gitignore index 13480660..82f92755 100644 --- a/.gitignore +++ b/.gitignore @@ -85,7 +85,7 @@ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: -.python-version +# .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. diff --git a/.python-version b/.python-version new file mode 100644 index 00000000..7c7a975f --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.10 \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile index d0c3cbf1..faf5089f 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,7 +4,7 @@ # You can set these variables from the command line, and also # from the environment for the first two. SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build +SPHINXBUILD ?= uv run sphinx-build SOURCEDIR = source BUILDDIR = build diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 237bab67..7c4e240d 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -4,28 +4,37 @@ Contributing Preparing the development setup ------------------------------- -1. Install Python 3.10 +1. Install `uv `_. +2. Fork the repository (in GitHub) and clone the forked repository: .. code-block:: console - $ sudo add-apt-repository ppa:deadsnakes/ppa - $ sudo apt update - $ sudo apt install python3.10 python3.10-venv + $ git clone https://github.com//judge0-python + $ cd judge0-python -2. Clone the repo, create and activate a new virtual environment +3. Prepare the virtual environment and dependencies: .. code-block:: console - $ cd judge0-python - $ python3.10 -m venv venv - $ . venv/bin/activate + $ uv sync --group dev + +4. Install the necessary development tools: + +.. code-block:: console + + $ uv tool install pre-commit + +5. Make sure all the necessary tools are installed: + +.. code-block:: console + + $ uv tool list -3. Install the library and development dependencies +6. Finally, install the pre-commit hooks: .. code-block:: console - $ pip install -e .[dev] - $ pre-commit install + $ uv tool run pre-commit install Building documentation ---------------------- diff --git a/pyproject.toml b/pyproject.toml index 8a4d7a34..8595aac9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,10 +35,9 @@ Homepage = "https://github.com/judge0/judge0-python" Repository = "https://github.com/judge0/judge0-python.git" Issues = "https://github.com/judge0/judge0-python/issues" -[project.optional-dependencies] +[dependency-groups] test = [ "ufmt==2.7.3", - "pre-commit==3.8.0", "pytest==8.3.3", "python-dotenv==1.0.1", "pytest-cov==6.0.0", @@ -50,10 +49,7 @@ docs = [ "sphinx-autodoc-typehints==2.3.0", "sphinx-multiversion==0.2.4", ] -dev = [ - "judge0[test]", - "judge0[docs]", -] +dev = [{ include-group = "test" }, { include-group = "docs" }] [tool.flake8] extend-ignore = [ diff --git a/uv.lock b/uv.lock new file mode 100644 index 00000000..8d05bf15 --- /dev/null +++ b/uv.lock @@ -0,0 +1,1305 @@ +version = 1 +revision = 3 +requires-python = ">=3.10" +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.13.*'", + "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version < '3.11'", +] + +[[package]] +name = "alabaster" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/f8/d9c74d0daf3f742840fd818d69cfae176fa332022fd44e3469487d5a9420/alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e", size = 24210, upload-time = "2024-07-26T18:15:03.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "attrs" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, +] + +[[package]] +name = "babel" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/77/e9/df2358efd7659577435e2177bfa69cba6c33216681af51a707193dec162a/beautifulsoup4-4.14.2.tar.gz", hash = "sha256:2a98ab9f944a11acee9cc848508ec28d9228abfd522ef0fad6a02a72e0ded69e", size = 625822, upload-time = "2025-09-29T10:05:42.613Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/fe/3aed5d0be4d404d12d36ab97e2f1791424d9ca39c2f754a6285d59a3b01d/beautifulsoup4-4.14.2-py3-none-any.whl", hash = "sha256:5ef6fa3a8cbece8488d66985560f97ed091e22bbc4e9c2338508a9d5de6d4515", size = 106392, upload-time = "2025-09-29T10:05:43.771Z" }, +] + +[[package]] +name = "black" +version = "25.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "pytokens" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4b/43/20b5c90612d7bdb2bdbcceeb53d588acca3bb8f0e4c5d5c751a2c8fdd55a/black-25.9.0.tar.gz", hash = "sha256:0474bca9a0dd1b51791fcc507a4e02078a1c63f6d4e4ae5544b9848c7adfb619", size = 648393, upload-time = "2025-09-19T00:27:37.758Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/40/dbe31fc56b218a858c8fc6f5d8d3ba61c1fa7e989d43d4a4574b8b992840/black-25.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ce41ed2614b706fd55fd0b4a6909d06b5bab344ffbfadc6ef34ae50adba3d4f7", size = 1715605, upload-time = "2025-09-19T00:36:13.483Z" }, + { url = "https://files.pythonhosted.org/packages/92/b2/f46800621200eab6479b1f4c0e3ede5b4c06b768e79ee228bc80270bcc74/black-25.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2ab0ce111ef026790e9b13bd216fa7bc48edd934ffc4cbf78808b235793cbc92", size = 1571829, upload-time = "2025-09-19T00:32:42.13Z" }, + { url = "https://files.pythonhosted.org/packages/4e/64/5c7f66bd65af5c19b4ea86062bb585adc28d51d37babf70969e804dbd5c2/black-25.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f96b6726d690c96c60ba682955199f8c39abc1ae0c3a494a9c62c0184049a713", size = 1631888, upload-time = "2025-09-19T00:30:54.212Z" }, + { url = "https://files.pythonhosted.org/packages/3b/64/0b9e5bfcf67db25a6eef6d9be6726499a8a72ebab3888c2de135190853d3/black-25.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:d119957b37cc641596063cd7db2656c5be3752ac17877017b2ffcdb9dfc4d2b1", size = 1327056, upload-time = "2025-09-19T00:31:08.877Z" }, + { url = "https://files.pythonhosted.org/packages/b7/f4/7531d4a336d2d4ac6cc101662184c8e7d068b548d35d874415ed9f4116ef/black-25.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:456386fe87bad41b806d53c062e2974615825c7a52159cde7ccaeb0695fa28fa", size = 1698727, upload-time = "2025-09-19T00:31:14.264Z" }, + { url = "https://files.pythonhosted.org/packages/28/f9/66f26bfbbf84b949cc77a41a43e138d83b109502cd9c52dfc94070ca51f2/black-25.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a16b14a44c1af60a210d8da28e108e13e75a284bf21a9afa6b4571f96ab8bb9d", size = 1555679, upload-time = "2025-09-19T00:31:29.265Z" }, + { url = "https://files.pythonhosted.org/packages/bf/59/61475115906052f415f518a648a9ac679d7afbc8da1c16f8fdf68a8cebed/black-25.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aaf319612536d502fdd0e88ce52d8f1352b2c0a955cc2798f79eeca9d3af0608", size = 1617453, upload-time = "2025-09-19T00:30:42.24Z" }, + { url = "https://files.pythonhosted.org/packages/7f/5b/20fd5c884d14550c911e4fb1b0dae00d4abb60a4f3876b449c4d3a9141d5/black-25.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:c0372a93e16b3954208417bfe448e09b0de5cc721d521866cd9e0acac3c04a1f", size = 1333655, upload-time = "2025-09-19T00:30:56.715Z" }, + { url = "https://files.pythonhosted.org/packages/fb/8e/319cfe6c82f7e2d5bfb4d3353c6cc85b523d677ff59edc61fdb9ee275234/black-25.9.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1b9dc70c21ef8b43248f1d86aedd2aaf75ae110b958a7909ad8463c4aa0880b0", size = 1742012, upload-time = "2025-09-19T00:33:08.678Z" }, + { url = "https://files.pythonhosted.org/packages/94/cc/f562fe5d0a40cd2a4e6ae3f685e4c36e365b1f7e494af99c26ff7f28117f/black-25.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e46eecf65a095fa62e53245ae2795c90bdecabd53b50c448d0a8bcd0d2e74c4", size = 1581421, upload-time = "2025-09-19T00:35:25.937Z" }, + { url = "https://files.pythonhosted.org/packages/84/67/6db6dff1ebc8965fd7661498aea0da5d7301074b85bba8606a28f47ede4d/black-25.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9101ee58ddc2442199a25cb648d46ba22cd580b00ca4b44234a324e3ec7a0f7e", size = 1655619, upload-time = "2025-09-19T00:30:49.241Z" }, + { url = "https://files.pythonhosted.org/packages/10/10/3faef9aa2a730306cf469d76f7f155a8cc1f66e74781298df0ba31f8b4c8/black-25.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:77e7060a00c5ec4b3367c55f39cf9b06e68965a4f2e61cecacd6d0d9b7ec945a", size = 1342481, upload-time = "2025-09-19T00:31:29.625Z" }, + { url = "https://files.pythonhosted.org/packages/48/99/3acfea65f5e79f45472c45f87ec13037b506522719cd9d4ac86484ff51ac/black-25.9.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0172a012f725b792c358d57fe7b6b6e8e67375dd157f64fa7a3097b3ed3e2175", size = 1742165, upload-time = "2025-09-19T00:34:10.402Z" }, + { url = "https://files.pythonhosted.org/packages/3a/18/799285282c8236a79f25d590f0222dbd6850e14b060dfaa3e720241fd772/black-25.9.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3bec74ee60f8dfef564b573a96b8930f7b6a538e846123d5ad77ba14a8d7a64f", size = 1581259, upload-time = "2025-09-19T00:32:49.685Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ce/883ec4b6303acdeca93ee06b7622f1fa383c6b3765294824165d49b1a86b/black-25.9.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b756fc75871cb1bcac5499552d771822fd9db5a2bb8db2a7247936ca48f39831", size = 1655583, upload-time = "2025-09-19T00:30:44.505Z" }, + { url = "https://files.pythonhosted.org/packages/21/17/5c253aa80a0639ccc427a5c7144534b661505ae2b5a10b77ebe13fa25334/black-25.9.0-cp313-cp313-win_amd64.whl", hash = "sha256:846d58e3ce7879ec1ffe816bb9df6d006cd9590515ed5d17db14e17666b2b357", size = 1343428, upload-time = "2025-09-19T00:32:13.839Z" }, + { url = "https://files.pythonhosted.org/packages/1b/46/863c90dcd3f9d41b109b7f19032ae0db021f0b2a81482ba0a1e28c84de86/black-25.9.0-py3-none-any.whl", hash = "sha256:474b34c1342cdc157d307b56c4c65bce916480c4a8f6551fdc6bf9b486a7c4ae", size = 203363, upload-time = "2025-09-19T00:27:35.724Z" }, +] + +[[package]] +name = "certifi" +version = "2025.10.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/5b/b6ce21586237c77ce67d01dc5507039d444b630dd76611bbca2d8e5dcd91/certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43", size = 164519, upload-time = "2025-10-05T04:12:15.808Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/37/af0d2ef3967ac0d6113837b44a4f0bfe1328c2b9763bd5b1744520e5cfed/certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de", size = 163286, upload-time = "2025-10-05T04:12:14.03Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/b8/6d51fc1d52cbd52cd4ccedd5b5b2f0f6a11bbf6765c782298b0f3e808541/charset_normalizer-3.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e824f1492727fa856dd6eda4f7cee25f8518a12f3c4a56a74e8095695089cf6d", size = 209709, upload-time = "2025-10-14T04:40:11.385Z" }, + { url = "https://files.pythonhosted.org/packages/5c/af/1f9d7f7faafe2ddfb6f72a2e07a548a629c61ad510fe60f9630309908fef/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bd5d4137d500351a30687c2d3971758aac9a19208fc110ccb9d7188fbe709e8", size = 148814, upload-time = "2025-10-14T04:40:13.135Z" }, + { url = "https://files.pythonhosted.org/packages/79/3d/f2e3ac2bbc056ca0c204298ea4e3d9db9b4afe437812638759db2c976b5f/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:027f6de494925c0ab2a55eab46ae5129951638a49a34d87f4c3eda90f696b4ad", size = 144467, upload-time = "2025-10-14T04:40:14.728Z" }, + { url = "https://files.pythonhosted.org/packages/ec/85/1bf997003815e60d57de7bd972c57dc6950446a3e4ccac43bc3070721856/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f820802628d2694cb7e56db99213f930856014862f3fd943d290ea8438d07ca8", size = 162280, upload-time = "2025-10-14T04:40:16.14Z" }, + { url = "https://files.pythonhosted.org/packages/3e/8e/6aa1952f56b192f54921c436b87f2aaf7c7a7c3d0d1a765547d64fd83c13/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:798d75d81754988d2565bff1b97ba5a44411867c0cf32b77a7e8f8d84796b10d", size = 159454, upload-time = "2025-10-14T04:40:17.567Z" }, + { url = "https://files.pythonhosted.org/packages/36/3b/60cbd1f8e93aa25d1c669c649b7a655b0b5fb4c571858910ea9332678558/charset_normalizer-3.4.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9d1bb833febdff5c8927f922386db610b49db6e0d4f4ee29601d71e7c2694313", size = 153609, upload-time = "2025-10-14T04:40:19.08Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/6a13396948b8fd3c4b4fd5bc74d045f5637d78c9675585e8e9fbe5636554/charset_normalizer-3.4.4-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cd98cdc06614a2f768d2b7286d66805f94c48cde050acdbbb7db2600ab3197e", size = 151849, upload-time = "2025-10-14T04:40:20.607Z" }, + { url = "https://files.pythonhosted.org/packages/b7/7a/59482e28b9981d105691e968c544cc0df3b7d6133152fb3dcdc8f135da7a/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:077fbb858e903c73f6c9db43374fd213b0b6a778106bc7032446a8e8b5b38b93", size = 151586, upload-time = "2025-10-14T04:40:21.719Z" }, + { url = "https://files.pythonhosted.org/packages/92/59/f64ef6a1c4bdd2baf892b04cd78792ed8684fbc48d4c2afe467d96b4df57/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:244bfb999c71b35de57821b8ea746b24e863398194a4014e4c76adc2bbdfeff0", size = 145290, upload-time = "2025-10-14T04:40:23.069Z" }, + { url = "https://files.pythonhosted.org/packages/6b/63/3bf9f279ddfa641ffa1962b0db6a57a9c294361cc2f5fcac997049a00e9c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64b55f9dce520635f018f907ff1b0df1fdc31f2795a922fb49dd14fbcdf48c84", size = 163663, upload-time = "2025-10-14T04:40:24.17Z" }, + { url = "https://files.pythonhosted.org/packages/ed/09/c9e38fc8fa9e0849b172b581fd9803bdf6e694041127933934184e19f8c3/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:faa3a41b2b66b6e50f84ae4a68c64fcd0c44355741c6374813a800cd6695db9e", size = 151964, upload-time = "2025-10-14T04:40:25.368Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d1/d28b747e512d0da79d8b6a1ac18b7ab2ecfd81b2944c4c710e166d8dd09c/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6515f3182dbe4ea06ced2d9e8666d97b46ef4c75e326b79bb624110f122551db", size = 161064, upload-time = "2025-10-14T04:40:26.806Z" }, + { url = "https://files.pythonhosted.org/packages/bb/9a/31d62b611d901c3b9e5500c36aab0ff5eb442043fb3a1c254200d3d397d9/charset_normalizer-3.4.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc00f04ed596e9dc0da42ed17ac5e596c6ccba999ba6bd92b0e0aef2f170f2d6", size = 155015, upload-time = "2025-10-14T04:40:28.284Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/107e008fa2bff0c8b9319584174418e5e5285fef32f79d8ee6a430d0039c/charset_normalizer-3.4.4-cp310-cp310-win32.whl", hash = "sha256:f34be2938726fc13801220747472850852fe6b1ea75869a048d6f896838c896f", size = 99792, upload-time = "2025-10-14T04:40:29.613Z" }, + { url = "https://files.pythonhosted.org/packages/eb/66/e396e8a408843337d7315bab30dbf106c38966f1819f123257f5520f8a96/charset_normalizer-3.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:a61900df84c667873b292c3de315a786dd8dac506704dea57bc957bd31e22c7d", size = 107198, upload-time = "2025-10-14T04:40:30.644Z" }, + { url = "https://files.pythonhosted.org/packages/b5/58/01b4f815bf0312704c267f2ccb6e5d42bcc7752340cd487bc9f8c3710597/charset_normalizer-3.4.4-cp310-cp310-win_arm64.whl", hash = "sha256:cead0978fc57397645f12578bfd2d5ea9138ea0fac82b2f63f7f7c6877986a69", size = 100262, upload-time = "2025-10-14T04:40:32.108Z" }, + { url = "https://files.pythonhosted.org/packages/ed/27/c6491ff4954e58a10f69ad90aca8a1b6fe9c5d3c6f380907af3c37435b59/charset_normalizer-3.4.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e1fcf0720908f200cd21aa4e6750a48ff6ce4afe7ff5a79a90d5ed8a08296f8", size = 206988, upload-time = "2025-10-14T04:40:33.79Z" }, + { url = "https://files.pythonhosted.org/packages/94/59/2e87300fe67ab820b5428580a53cad894272dbb97f38a7a814a2a1ac1011/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f819d5fe9234f9f82d75bdfa9aef3a3d72c4d24a6e57aeaebba32a704553aa0", size = 147324, upload-time = "2025-10-14T04:40:34.961Z" }, + { url = "https://files.pythonhosted.org/packages/07/fb/0cf61dc84b2b088391830f6274cb57c82e4da8bbc2efeac8c025edb88772/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:a59cb51917aa591b1c4e6a43c132f0cdc3c76dbad6155df4e28ee626cc77a0a3", size = 142742, upload-time = "2025-10-14T04:40:36.105Z" }, + { url = "https://files.pythonhosted.org/packages/62/8b/171935adf2312cd745d290ed93cf16cf0dfe320863ab7cbeeae1dcd6535f/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8ef3c867360f88ac904fd3f5e1f902f13307af9052646963ee08ff4f131adafc", size = 160863, upload-time = "2025-10-14T04:40:37.188Z" }, + { url = "https://files.pythonhosted.org/packages/09/73/ad875b192bda14f2173bfc1bc9a55e009808484a4b256748d931b6948442/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d9e45d7faa48ee908174d8fe84854479ef838fc6a705c9315372eacbc2f02897", size = 157837, upload-time = "2025-10-14T04:40:38.435Z" }, + { url = "https://files.pythonhosted.org/packages/6d/fc/de9cce525b2c5b94b47c70a4b4fb19f871b24995c728e957ee68ab1671ea/charset_normalizer-3.4.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:840c25fb618a231545cbab0564a799f101b63b9901f2569faecd6b222ac72381", size = 151550, upload-time = "2025-10-14T04:40:40.053Z" }, + { url = "https://files.pythonhosted.org/packages/55/c2/43edd615fdfba8c6f2dfbd459b25a6b3b551f24ea21981e23fb768503ce1/charset_normalizer-3.4.4-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ca5862d5b3928c4940729dacc329aa9102900382fea192fc5e52eb69d6093815", size = 149162, upload-time = "2025-10-14T04:40:41.163Z" }, + { url = "https://files.pythonhosted.org/packages/03/86/bde4ad8b4d0e9429a4e82c1e8f5c659993a9a863ad62c7df05cf7b678d75/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d9c7f57c3d666a53421049053eaacdd14bbd0a528e2186fcb2e672effd053bb0", size = 150019, upload-time = "2025-10-14T04:40:42.276Z" }, + { url = "https://files.pythonhosted.org/packages/1f/86/a151eb2af293a7e7bac3a739b81072585ce36ccfb4493039f49f1d3cae8c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:277e970e750505ed74c832b4bf75dac7476262ee2a013f5574dd49075879e161", size = 143310, upload-time = "2025-10-14T04:40:43.439Z" }, + { url = "https://files.pythonhosted.org/packages/b5/fe/43dae6144a7e07b87478fdfc4dbe9efd5defb0e7ec29f5f58a55aeef7bf7/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31fd66405eaf47bb62e8cd575dc621c56c668f27d46a61d975a249930dd5e2a4", size = 162022, upload-time = "2025-10-14T04:40:44.547Z" }, + { url = "https://files.pythonhosted.org/packages/80/e6/7aab83774f5d2bca81f42ac58d04caf44f0cc2b65fc6db2b3b2e8a05f3b3/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0d3d8f15c07f86e9ff82319b3d9ef6f4bf907608f53fe9d92b28ea9ae3d1fd89", size = 149383, upload-time = "2025-10-14T04:40:46.018Z" }, + { url = "https://files.pythonhosted.org/packages/4f/e8/b289173b4edae05c0dde07f69f8db476a0b511eac556dfe0d6bda3c43384/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9f7fcd74d410a36883701fafa2482a6af2ff5ba96b9a620e9e0721e28ead5569", size = 159098, upload-time = "2025-10-14T04:40:47.081Z" }, + { url = "https://files.pythonhosted.org/packages/d8/df/fe699727754cae3f8478493c7f45f777b17c3ef0600e28abfec8619eb49c/charset_normalizer-3.4.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ebf3e58c7ec8a8bed6d66a75d7fb37b55e5015b03ceae72a8e7c74495551e224", size = 152991, upload-time = "2025-10-14T04:40:48.246Z" }, + { url = "https://files.pythonhosted.org/packages/1a/86/584869fe4ddb6ffa3bd9f491b87a01568797fb9bd8933f557dba9771beaf/charset_normalizer-3.4.4-cp311-cp311-win32.whl", hash = "sha256:eecbc200c7fd5ddb9a7f16c7decb07b566c29fa2161a16cf67b8d068bd21690a", size = 99456, upload-time = "2025-10-14T04:40:49.376Z" }, + { url = "https://files.pythonhosted.org/packages/65/f6/62fdd5feb60530f50f7e38b4f6a1d5203f4d16ff4f9f0952962c044e919a/charset_normalizer-3.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:5ae497466c7901d54b639cf42d5b8c1b6a4fead55215500d2f486d34db48d016", size = 106978, upload-time = "2025-10-14T04:40:50.844Z" }, + { url = "https://files.pythonhosted.org/packages/7a/9d/0710916e6c82948b3be62d9d398cb4fcf4e97b56d6a6aeccd66c4b2f2bd5/charset_normalizer-3.4.4-cp311-cp311-win_arm64.whl", hash = "sha256:65e2befcd84bc6f37095f5961e68a6f077bf44946771354a28ad434c2cce0ae1", size = 99969, upload-time = "2025-10-14T04:40:52.272Z" }, + { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, + { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, + { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, + { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, + { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, + { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, + { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, + { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, + { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, + { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, + { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, + { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "click" +version = "8.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/61/de6cd827efad202d7057d93e0fed9294b96952e188f7384832791c7b2254/click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4", size = 276943, upload-time = "2025-09-18T17:32:23.696Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/d3/9dcc0f5797f070ec8edf30fbadfb200e71d9db6b84d211e3b2085a7589a0/click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc", size = 107295, upload-time = "2025-09-18T17:32:22.42Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "coverage" +version = "7.11.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/32/e6/7c4006cf689ed7a4aa75dcf1f14acbc04e585714c220b5cc6d231096685a/coverage-7.11.2.tar.gz", hash = "sha256:ae43149b7732df15c3ca9879b310c48b71d08cd8a7ba77fda7f9108f78499e93", size = 814849, upload-time = "2025-11-08T20:26:33.011Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/5b/d943b719938467d313973fd83af9c810e248fcec33165d5ab0148ab1c602/coverage-7.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:004bdc5985b86f565772af627925e368256ee2172623db10a0d78a3b53f20ef1", size = 216802, upload-time = "2025-11-08T20:23:47.186Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f7/d3c096ca6a6212e8a536ae2144406d28b43e7528ff05a0bf6a5336319d0d/coverage-7.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3aa8c62460499e10ceac5ea61cc09c4f7ddcd8a68c6313cf08785ad353dfd311", size = 217317, upload-time = "2025-11-08T20:23:50.255Z" }, + { url = "https://files.pythonhosted.org/packages/10/46/d0dbafbd3604293b73a44ae9c88e339921c13f309138b31ec60b451895b9/coverage-7.11.2-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d73da4893125e0671f762e408dea9957b2bda0036c9589c2fd258a6b870acbdb", size = 244068, upload-time = "2025-11-08T20:23:51.63Z" }, + { url = "https://files.pythonhosted.org/packages/3d/16/ef8aba300f7224167c556d15852bf35d42c7af93b68f3ef82323737515e8/coverage-7.11.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:805efa416085999da918f15f81b26636d8e79863e1fbac1495664686d1e6a6e9", size = 245896, upload-time = "2025-11-08T20:23:53.1Z" }, + { url = "https://files.pythonhosted.org/packages/7f/ea/02fa537e61bc61fd111d5d9611184a354dd26bbc31e58ccd922f76404723/coverage-7.11.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c65f4291aec39692a3bfbe1d92ae5bea58c16b5553fdf021de61c655d987233f", size = 247755, upload-time = "2025-11-08T20:23:54.88Z" }, + { url = "https://files.pythonhosted.org/packages/41/3b/6cc19074059c030e489fd5ff934aa49521a75ba6236d27badb3b4270b21c/coverage-7.11.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b7658f3d4f728092368c091c18efcfb679be9b612c93bfdf345f33635a325188", size = 244714, upload-time = "2025-11-08T20:23:56.655Z" }, + { url = "https://files.pythonhosted.org/packages/a6/d5/b3480a0fd9c45fad37884c38ee943788ef43b64abf156b3f8e6af096c62e/coverage-7.11.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9f5f6ee021b3b25e748a9a053f3a8dd61a62b6689efd6425cb47e27360994903", size = 245800, upload-time = "2025-11-08T20:23:58.06Z" }, + { url = "https://files.pythonhosted.org/packages/07/2a/34f1476db9c58c410193f8f0cbecdfd9931912ed07de628fdffe0dae216d/coverage-7.11.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9a95b7a6043b221ec1a0d4d5481e424272b37028353265fbe5fcd3768d652eb7", size = 243808, upload-time = "2025-11-08T20:23:59.756Z" }, + { url = "https://files.pythonhosted.org/packages/73/fd/b43a0a4f6306a486d31cdd4166afd4dc0b08a8f072d7ab2ccc23893b6d19/coverage-7.11.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:94ced4a29a6987af99faaa49a513bf8d0458e8af004c54174e05dd7a8a31c7d9", size = 244070, upload-time = "2025-11-08T20:24:01.281Z" }, + { url = "https://files.pythonhosted.org/packages/cc/8c/bcbe2c9cb81ef008d05b04ebc37a3a1c65d61b61c9cf772f0ae473ddc56b/coverage-7.11.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8014a28a37ffabf7da7107f4f154d68c6b89672f27fef835a0574591c5cd140b", size = 244688, upload-time = "2025-11-08T20:24:02.641Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f7/c6c276f6663a1d7e29f8cc4a5a8c76dbf834ecb74017936187146adbce9e/coverage-7.11.2-cp310-cp310-win32.whl", hash = "sha256:43ecf9dca4fcb3baf8a886019dd5ce663c95a5e1c5172719c414f0ebd9eeb785", size = 219382, upload-time = "2025-11-08T20:24:04.476Z" }, + { url = "https://files.pythonhosted.org/packages/4f/aa/0d07b2d567f1d005088b4afad533b4a6af48ec75f3f9071afbe5f7076cab/coverage-7.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:230317450af65a37c1fdbdd3546f7277e0c1c1b65e0d57409248e5dd0fa13493", size = 220319, upload-time = "2025-11-08T20:24:06.464Z" }, + { url = "https://files.pythonhosted.org/packages/89/39/326336c0adc6dc624be0edb5143dec90a9da2626335e83f6d09da120922f/coverage-7.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:36c41bf2ee6f6062de8177e249fee17cd5c9662cd373f7a41e6468a34c5b9c0f", size = 216927, upload-time = "2025-11-08T20:24:08.167Z" }, + { url = "https://files.pythonhosted.org/packages/b7/68/cd1d3422fc9525827cddf62b2385f78356b88e745e90e8e512fefcc05f8f/coverage-7.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:397778cf6d50df59c890bd3ac10acb5bf413388ff6a013305134f1403d5db648", size = 217429, upload-time = "2025-11-08T20:24:09.939Z" }, + { url = "https://files.pythonhosted.org/packages/36/73/3f384dd79d6bbdf7fbceda3c7e0db33e148559bc18c49022c9c0c5e512c1/coverage-7.11.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c85f44ed4260221e46a4e9e8e8df4b359ab6c0a742c79e85d649779bcf77b534", size = 247832, upload-time = "2025-11-08T20:24:11.897Z" }, + { url = "https://files.pythonhosted.org/packages/45/3c/27839b6f343998e82f3e470397c058566c953dc71fe37e0abb953133a341/coverage-7.11.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cbffd1d5c5bf4c576ca247bf77646cdad4dced82928337eeb0b85e2b3be4d64b", size = 249749, upload-time = "2025-11-08T20:24:13.705Z" }, + { url = "https://files.pythonhosted.org/packages/6e/51/011102c7f6902084e632128ac0f42cd3345acc543a7c9f8ce5e1a94397ef/coverage-7.11.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea10a57568af7cf082a7a4d98a699f993652c2ffbdd5a6c9d63c9ca10b693b4d", size = 251860, upload-time = "2025-11-08T20:24:15.113Z" }, + { url = "https://files.pythonhosted.org/packages/bb/4c/4622eb7aac98c2552ed8a176a6015ea8cf36a2ec75cbcfb5f2ccf100bbd6/coverage-7.11.2-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4b1bea4c707f4c09f682fe0e646a114dfd068f627880d4a208850d01f8164ad", size = 247942, upload-time = "2025-11-08T20:24:16.637Z" }, + { url = "https://files.pythonhosted.org/packages/95/94/42ba12fc827fb504f8f8ec5313e46cf5582cdb9d4823e76d70ed22e88bdf/coverage-7.11.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1ac3f647ecf25d883051ef42d38d823016e715b9f289f8c1768be5117075d1bd", size = 249553, upload-time = "2025-11-08T20:24:18.153Z" }, + { url = "https://files.pythonhosted.org/packages/a3/47/2cd8014c872a3e469ffe50fbc692d02c7460e20cd701a0d6366fbef759e3/coverage-7.11.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d423991415f73a70c0a5f3e0a226cf4ab374dd0da7409978069b844df3d31582", size = 247627, upload-time = "2025-11-08T20:24:19.644Z" }, + { url = "https://files.pythonhosted.org/packages/a9/31/e722f2c7f0f16954d13e6441a24d841174bcb1ff2421c6504c024c09c7af/coverage-7.11.2-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0f4a958ff286038ac870f836351e9fb8912f1614d1cdbda200fc899235f7dc9b", size = 247353, upload-time = "2025-11-08T20:24:21.28Z" }, + { url = "https://files.pythonhosted.org/packages/0a/dd/d4fd26be0ce7993f0013df9788e52cd83a1adf5cfb9887bfd1b38722380e/coverage-7.11.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d1ff4b87ad438148976f2215141a490ae000e878536370d53f8da8c59a175a6", size = 248251, upload-time = "2025-11-08T20:24:22.724Z" }, + { url = "https://files.pythonhosted.org/packages/1c/33/003f7b5f10fae2ad7390e57a1520c46a24bd46e374b197e97050ae47751f/coverage-7.11.2-cp311-cp311-win32.whl", hash = "sha256:e448ceee2fb880427eafc9a3f8e6162b2ac7cc3e9b30b85d6511f25cc8a11820", size = 219410, upload-time = "2025-11-08T20:24:24.15Z" }, + { url = "https://files.pythonhosted.org/packages/22/e8/5db102c57143f33a9229ecdc8d7976ad0c5d103fcd26f2b939db96789990/coverage-7.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:bc65e32fe5bb942f0f5247e1500e355cbbdf326181198f5e27e3bb3ddb81e203", size = 220342, upload-time = "2025-11-08T20:24:25.947Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b2/9908f6b4b979045c01e02a069ae5f73c16dff022c296a5e1fd756c602c6c/coverage-7.11.2-cp311-cp311-win_arm64.whl", hash = "sha256:e8eb6cbd7d3b238335b5da0f3ce281102435afb503be4d7bdd69eea3c700a952", size = 219014, upload-time = "2025-11-08T20:24:27.382Z" }, + { url = "https://files.pythonhosted.org/packages/4f/98/aef630a13bc974333aeb83d69765eb513f790bf4bd5b79b8036ec176de8e/coverage-7.11.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:eaa2a5eeb82fa7a6a9cd65c4f968ee2a53839d451b4e88e060c67d87a0a40732", size = 217103, upload-time = "2025-11-08T20:24:28.938Z" }, + { url = "https://files.pythonhosted.org/packages/f9/1f/41f144dc49c07043230ad79126a9c79236724579c43175e476e0731ddc2a/coverage-7.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:07e14a4050525fd98bf3d793f229eb8b3ae81678f4031e38e6a18a068bd59fd4", size = 217467, upload-time = "2025-11-08T20:24:30.758Z" }, + { url = "https://files.pythonhosted.org/packages/a1/fa/6fc4b47c7c8323b0326c57786858b6185668f008edc2ea626bc35fb53e28/coverage-7.11.2-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:03e7e7dc31a7deaebf121c3c3bd3c6442b7fbf50aca72aae2a1d08aa30ca2a20", size = 248947, upload-time = "2025-11-08T20:24:32.559Z" }, + { url = "https://files.pythonhosted.org/packages/22/38/03bb7b3d991259ef8d483b83560f87eb4c6d5e8889ad836d212e010d08b3/coverage-7.11.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d752a8e398a19e2fb24781e4c73089bfeb417b6ac55f96c2c42cfe5bdb21cc18", size = 251707, upload-time = "2025-11-08T20:24:34.371Z" }, + { url = "https://files.pythonhosted.org/packages/83/6c/c32c7c76c8373978bf68bcfd87a1d265ace9c973ed9a007cada37f25948a/coverage-7.11.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a02818ec44803e325d66bd022828212df934739b894d1699c9a05b9105d30f2", size = 252793, upload-time = "2025-11-08T20:24:35.921Z" }, + { url = "https://files.pythonhosted.org/packages/60/16/86582ab283bad8e137f76e97c5b75a81f547174bca9bb2eba8b7be33d8b6/coverage-7.11.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d30a717493583c2a83c99f195e934c073be7f4291b32b7352c246d52e43f6893", size = 249331, upload-time = "2025-11-08T20:24:37.462Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8a/24449d3e2a84bd38c1903757265cd45b6c9021ecf013f27e33155dba5ada/coverage-7.11.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:55ae008253df6000bc885a780c1b0e939bd8c932f41e16df1cfe19a00428a98a", size = 250728, upload-time = "2025-11-08T20:24:38.936Z" }, + { url = "https://files.pythonhosted.org/packages/86/bc/fcfe9bdda15f48ef6d78a8524837216752fe82474965d42310e6296c8bde/coverage-7.11.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:17047fb65fcd1ce8a2f97dd2247c2b59cb4bc8848b3911db02dcb05856f91b71", size = 248877, upload-time = "2025-11-08T20:24:40.444Z" }, + { url = "https://files.pythonhosted.org/packages/51/27/58db09afcb155f41739330c521258782eefc12fe18f70d3b8e5dbc61857b/coverage-7.11.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:5f72a49504e1f35443b157d97997c9259a017384373eab52fd09b8ade2ae4674", size = 248455, upload-time = "2025-11-08T20:24:42.479Z" }, + { url = "https://files.pythonhosted.org/packages/24/6b/1eba5fa2b01b1aa727aa2a1c480c5f475fccecf32decae95b890cef7ee68/coverage-7.11.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5c31cdbb95ab0f4a60224a04efc43cfb406ce904f0b60fb6b2a72f37718ea5cb", size = 250316, upload-time = "2025-11-08T20:24:44.029Z" }, + { url = "https://files.pythonhosted.org/packages/08/58/46d3dcb99366c74b0478f2a58fd97e82419871a50989937e08578f9a5c5c/coverage-7.11.2-cp312-cp312-win32.whl", hash = "sha256:632904d126ca97e5d4ecf7e51ae8b20f086b6f002c6075adcfd4ff3a28574527", size = 219617, upload-time = "2025-11-08T20:24:46.086Z" }, + { url = "https://files.pythonhosted.org/packages/94/19/ab26b96a5c6fd0b5d644524997b60523b3ccbe7473a069e1385a272be238/coverage-7.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:c7ea5dec77d79dabb7b5fc712c59361aac52e459cd22028480625c3c743323d0", size = 220427, upload-time = "2025-11-08T20:24:47.809Z" }, + { url = "https://files.pythonhosted.org/packages/5b/c5/948b268909f04eb2b0a55e22f1e4b3ffd472a8a398d05ebcf95c36d8b1eb/coverage-7.11.2-cp312-cp312-win_arm64.whl", hash = "sha256:ed6ba9f1777fdd1c8e5650c7d123211fa484a187c61af4d82948dc5ee3c0afcc", size = 219068, upload-time = "2025-11-08T20:24:49.813Z" }, + { url = "https://files.pythonhosted.org/packages/ec/00/57f3f8adaced9e4c74f482932e093176df7e400b4bb95dc1f3cd499511b5/coverage-7.11.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:38a5509fe7fabb6fb3161059b947641753b6529150ef483fc01c4516a546f2ad", size = 217125, upload-time = "2025-11-08T20:24:51.368Z" }, + { url = "https://files.pythonhosted.org/packages/fc/2a/ff1a55673161608c895080950cdfbb6485c95e6fa57a92d2cd1e463717b3/coverage-7.11.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7e01ab8d69b6cffa2463e78a4d760a6b69dfebe5bf21837eabcc273655c7e7b3", size = 217499, upload-time = "2025-11-08T20:24:53.238Z" }, + { url = "https://files.pythonhosted.org/packages/73/e3/eaac01709ffbef291a12ca2526b6247f55ab17724e2297cc70921cd9a81f/coverage-7.11.2-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b4776c6555a9f378f37fa06408f2e1cc1d06e4c4e06adb3d157a4926b549efbe", size = 248479, upload-time = "2025-11-08T20:24:54.825Z" }, + { url = "https://files.pythonhosted.org/packages/75/25/d846d2d08d182eeb30d1eba839fabdd9a3e6c710a1f187657b9c697bab23/coverage-7.11.2-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6f70fa1ef17cba5dada94e144ea1b6e117d4f174666842d1da3aaf765d6eb477", size = 251074, upload-time = "2025-11-08T20:24:56.442Z" }, + { url = "https://files.pythonhosted.org/packages/2e/7a/34c9402ad12bce609be4be1146a7d22a7fae8e9d752684b6315cce552a65/coverage-7.11.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:811bff1f93566a8556a9aeb078bd82573e37f4d802a185fba4cbe75468615050", size = 252318, upload-time = "2025-11-08T20:24:57.987Z" }, + { url = "https://files.pythonhosted.org/packages/cf/2f/292fe3cea4cc1c4b8fb060fa60e565ab1b3bfc67bda74bedefb24b4a2407/coverage-7.11.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d0e80c9946da61cc0bf55dfd90d65707acc1aa5bdcb551d4285ea8906255bb33", size = 248641, upload-time = "2025-11-08T20:24:59.642Z" }, + { url = "https://files.pythonhosted.org/packages/c5/af/33ccb2aa2f43bbc330a1fccf84a396b90f2e61c00dccb7b72b2993a3c795/coverage-7.11.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:10f10c9acf584ef82bfaaa7296163bd11c7487237f1670e81fc2fa7e972be67b", size = 250457, upload-time = "2025-11-08T20:25:01.358Z" }, + { url = "https://files.pythonhosted.org/packages/bd/91/4b5b58f34e0587fbc5c1a28d644d9c20c13349c1072aea507b6e372c8f20/coverage-7.11.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fd3f7cc6cb999e3eff91a2998a70c662b0fcd3c123d875766147c530ca0d3248", size = 248421, upload-time = "2025-11-08T20:25:02.895Z" }, + { url = "https://files.pythonhosted.org/packages/d5/d5/5c5ed220b15f490717522d241629c522fa22275549a6ccfbc96a3654b009/coverage-7.11.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:e52a028a56889d3ad036c0420e866e4a69417d3203e2fc5f03dcb8841274b64c", size = 248244, upload-time = "2025-11-08T20:25:04.742Z" }, + { url = "https://files.pythonhosted.org/packages/1e/27/504088aba40735132db838711d966e1314931ff9bddcd0e2ea6bc7e345a7/coverage-7.11.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f6f985e175dfa1fb8c0a01f47186720ae25d5e20c181cc5f3b9eba95589b8148", size = 250004, upload-time = "2025-11-08T20:25:06.633Z" }, + { url = "https://files.pythonhosted.org/packages/ea/89/4d61c0ad0d39656bd5e73fe41a93a34b063c90333258e6307aadcfcdbb97/coverage-7.11.2-cp313-cp313-win32.whl", hash = "sha256:e48b95abe2983be98cdf52900e07127eb7fe7067c87a700851f4f1f53d2b00e6", size = 219639, upload-time = "2025-11-08T20:25:08.27Z" }, + { url = "https://files.pythonhosted.org/packages/e0/a7/a298afa025ebe7a2afd6657871a1ac2d9c49666ce00f9a35ee9df61a3bd8/coverage-7.11.2-cp313-cp313-win_amd64.whl", hash = "sha256:ea910cc737ee8553c81ad5c104bc5b135106ebb36f88be506c3493e001b4c733", size = 220445, upload-time = "2025-11-08T20:25:09.906Z" }, + { url = "https://files.pythonhosted.org/packages/7e/a1/1825f5eadc0a0a6ea1c6e678827e1ec8c0494dbd23270016fccfc3358fbf/coverage-7.11.2-cp313-cp313-win_arm64.whl", hash = "sha256:ef2d3081562cd83f97984a96e02e7a294efa28f58d5e7f4e28920f59fd752b41", size = 219077, upload-time = "2025-11-08T20:25:11.777Z" }, + { url = "https://files.pythonhosted.org/packages/c0/61/98336c6f4545690b482e805c3a1a83fb2db4c19076307b187db3d421b5b3/coverage-7.11.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:87d7c7b0b2279e174f36d276e2afb7bf16c9ea04e824d4fa277eea1854f4cfd4", size = 217818, upload-time = "2025-11-08T20:25:13.697Z" }, + { url = "https://files.pythonhosted.org/packages/57/ee/6dca6e5f1a4affba8d3224996d0e9145e6d67817da753cc436e48bb8d0e6/coverage-7.11.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:940d195f4c8ba3ec6e7c302c9f546cdbe63e57289ed535452bc52089b1634f1c", size = 218170, upload-time = "2025-11-08T20:25:15.284Z" }, + { url = "https://files.pythonhosted.org/packages/ec/17/9c9ca3ef09d3576027e77cf580eb599d8d655f9ca2456a26ca50c53e07e3/coverage-7.11.2-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e3b92e10ca996b5421232dd6629b9933f97eb57ce374bca800ab56681fbeda2b", size = 259466, upload-time = "2025-11-08T20:25:17.373Z" }, + { url = "https://files.pythonhosted.org/packages/53/96/2001a596827a0b91ba5f627f21b5ce998fa1f27d861a8f6d909f5ea663ff/coverage-7.11.2-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:61d6a7cc1e7a7a761ac59dcc88cee54219fd4231face52bd1257cfd3df29ae9f", size = 261530, upload-time = "2025-11-08T20:25:19.085Z" }, + { url = "https://files.pythonhosted.org/packages/4d/bb/fea7007035fdc3c40fcca0ab740da549ff9d38fa50b0d37cd808fbbf9683/coverage-7.11.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bee1911c44c52cad6b51d436aa8c6ff5ca5d414fa089c7444592df9e7b890be9", size = 263963, upload-time = "2025-11-08T20:25:21.168Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b3/7452071353441b632ebea42f6ad328a7ab592e4bc50a31f9921b41667017/coverage-7.11.2-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4c4423ea9c28749080b41e18ec74d658e6c9f148a6b47e719f3d7f56197f8227", size = 258644, upload-time = "2025-11-08T20:25:22.928Z" }, + { url = "https://files.pythonhosted.org/packages/e6/05/6e56b1c2b3308f587508ad4b0a4cb76c8d6179fea2df148e071979b3eb77/coverage-7.11.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:689d3b4dd0d4c912ed8bfd7a1b5ff2c5ecb1fa16571840573174704ff5437862", size = 261539, upload-time = "2025-11-08T20:25:25.277Z" }, + { url = "https://files.pythonhosted.org/packages/91/15/7afeeac2a49f651318e4a83f1d5f4d3d4f4092f1d451ac4aec8069cddbdb/coverage-7.11.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:75ef769be19d69ea71b0417d7fbf090032c444792579cdf9b166346a340987d5", size = 259153, upload-time = "2025-11-08T20:25:28.098Z" }, + { url = "https://files.pythonhosted.org/packages/1e/77/08f3b5c7500b2031cee74e8a01f9a5bc407f781ff6a826707563bb9dd5b7/coverage-7.11.2-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:6681164bc697b93676945c8c814b76ac72204c395e11b71ba796a93b33331c24", size = 258043, upload-time = "2025-11-08T20:25:30.087Z" }, + { url = "https://files.pythonhosted.org/packages/ca/49/8e080e7622bd7c82df0f8324bbe0461ed1032a638b80046f1a53a88ea3a8/coverage-7.11.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4aa799c61869318d2b86c0d3c413d6805546aec42069f009cbb27df2eefb2790", size = 260243, upload-time = "2025-11-08T20:25:31.722Z" }, + { url = "https://files.pythonhosted.org/packages/dc/75/da033d8589661527b4a6d30c414005467e48fbccc0f3c10898af183e14e1/coverage-7.11.2-cp313-cp313t-win32.whl", hash = "sha256:9a6468e1a3a40d3d1f9120a9ff221d3eacef4540a6f819fff58868fe0bd44fa9", size = 220309, upload-time = "2025-11-08T20:25:33.9Z" }, + { url = "https://files.pythonhosted.org/packages/29/ef/8a477d41dbcde1f1179c13c43c9f77ee926b793fe3e5f1cf5d868a494679/coverage-7.11.2-cp313-cp313t-win_amd64.whl", hash = "sha256:30c437e8b51ce081fe3903c9e368e85c9a803b093fd062c49215f3bf4fd1df37", size = 221374, upload-time = "2025-11-08T20:25:35.88Z" }, + { url = "https://files.pythonhosted.org/packages/0d/a3/4c3cdd737ed1f630b821430004c2d5f1088b9bc0a7115aa5ad7c40d7d5cb/coverage-7.11.2-cp313-cp313t-win_arm64.whl", hash = "sha256:a35701fe0b5ee9d4b67d31aa76555237af32a36b0cf8dd33f8a74470cf7cd2f5", size = 219648, upload-time = "2025-11-08T20:25:37.572Z" }, + { url = "https://files.pythonhosted.org/packages/52/d1/43d17c299249085d6e0df36db272899e92aa09e68e27d3e92a4cf8d9523e/coverage-7.11.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7f933bc1fead57373922e383d803e1dd5ec7b5a786c220161152ebee1aa3f006", size = 217170, upload-time = "2025-11-08T20:25:39.254Z" }, + { url = "https://files.pythonhosted.org/packages/78/66/f21c03307079a0b7867b364af057430018a3d4a18ed1b99e1adaf5a0f305/coverage-7.11.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f80cb5b328e870bf3df0568b41643a85ee4b8ccd219a096812389e39aa310ea4", size = 217497, upload-time = "2025-11-08T20:25:41.277Z" }, + { url = "https://files.pythonhosted.org/packages/f0/dd/0a2257154c32f442fe3b4622501ab818ae4bd7cde33bd7a740630f6bd24c/coverage-7.11.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f6b2498f86f2554ed6cb8df64201ee95b8c70fb77064a8b2ae8a7185e7a4a5f0", size = 248539, upload-time = "2025-11-08T20:25:43.349Z" }, + { url = "https://files.pythonhosted.org/packages/3a/ca/c55ab0ee5ebfc4ab56cfc1b3585cba707342dc3f891fe19f02e07bc0c25f/coverage-7.11.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a913b21f716aa05b149a8656e9e234d9da04bc1f9842136ad25a53172fecc20e", size = 251057, upload-time = "2025-11-08T20:25:45.083Z" }, + { url = "https://files.pythonhosted.org/packages/db/01/a149b88ebe714b76d95427d609e629446d1df5d232f4bdaec34e471da124/coverage-7.11.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c5769159986eb174f0f66d049a52da03f2d976ac1355679371f1269e83528599", size = 252393, upload-time = "2025-11-08T20:25:47.272Z" }, + { url = "https://files.pythonhosted.org/packages/bc/a4/a992c805e95c46f0ac1b83782aa847030cb52bbfd8fc9015cff30f50fb9e/coverage-7.11.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:89565d7c9340858424a5ca3223bfefe449aeb116942cdc98cd76c07ca50e9db8", size = 248534, upload-time = "2025-11-08T20:25:49.034Z" }, + { url = "https://files.pythonhosted.org/packages/78/01/318ed024ae245dbc76152bc016919aef69c508a5aac0e2da5de9b1efea61/coverage-7.11.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b7fc943097fa48de00d14d2a2f3bcebfede024e031d7cd96063fe135f8cbe96e", size = 250412, upload-time = "2025-11-08T20:25:51.2Z" }, + { url = "https://files.pythonhosted.org/packages/6c/f9/f05c7984ef48c8d1c6c1ddb243223b344dcd8c6c0d54d359e4e325e2fa7e/coverage-7.11.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:72a3d109ac233666064d60b29ae5801dd28bc51d1990e69f183a2b91b92d4baf", size = 248367, upload-time = "2025-11-08T20:25:53.399Z" }, + { url = "https://files.pythonhosted.org/packages/7e/ac/461ed0dcaba0c727b760057ffa9837920d808a35274e179ff4a94f6f755a/coverage-7.11.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:4648c90cf741fb61e142826db1557a44079de0ca868c5c5a363c53d852897e84", size = 248187, upload-time = "2025-11-08T20:25:55.402Z" }, + { url = "https://files.pythonhosted.org/packages/e3/bf/8510ce8c7b1a8d682726df969e7523ee8aac23964b2c8301b8ce2400c1b4/coverage-7.11.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7f1aa017b47e1879d7bac50161b00d2b886f2ff3882fa09427119e1b3572ede1", size = 249849, upload-time = "2025-11-08T20:25:57.186Z" }, + { url = "https://files.pythonhosted.org/packages/75/6f/ea1c8990ca35d607502c9e531f164573ea59bb6cd5cd4dc56d7cc3d1fcb5/coverage-7.11.2-cp314-cp314-win32.whl", hash = "sha256:44b6e04bb94e59927a2807cd4de86386ce34248eaea95d9f1049a72f81828c38", size = 219908, upload-time = "2025-11-08T20:25:58.896Z" }, + { url = "https://files.pythonhosted.org/packages/1e/04/a64e2a8b9b65ae84670207dc6073e3d48ee9192646440b469e9b8c335d1f/coverage-7.11.2-cp314-cp314-win_amd64.whl", hash = "sha256:7ea36e981a8a591acdaa920704f8dc798f9fff356c97dbd5d5702046ae967ce1", size = 220724, upload-time = "2025-11-08T20:26:01.122Z" }, + { url = "https://files.pythonhosted.org/packages/73/df/eb4e9f9d0d55f7ec2b55298c30931a665c2249c06e3d1d14c5a6df638c77/coverage-7.11.2-cp314-cp314-win_arm64.whl", hash = "sha256:4aaf2212302b6f748dde596424b0f08bc3e1285192104e2480f43d56b6824f35", size = 219296, upload-time = "2025-11-08T20:26:02.918Z" }, + { url = "https://files.pythonhosted.org/packages/d0/b5/e9bb3b17a65fe92d1c7a2363eb5ae9893fafa578f012752ed40eee6aa3c8/coverage-7.11.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:84e8e0f5ab5134a2d32d4ebadc18b433dbbeddd0b73481f816333b1edd3ff1c8", size = 217905, upload-time = "2025-11-08T20:26:04.633Z" }, + { url = "https://files.pythonhosted.org/packages/38/6f/1f38dd0b63a9d82fb3c9d7fbe1c9dab26ae77e5b45e801d129664e039034/coverage-7.11.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5db683000ff6217273071c752bd6a1d341b6dc5d6aaa56678c53577a4e70e78a", size = 218172, upload-time = "2025-11-08T20:26:06.677Z" }, + { url = "https://files.pythonhosted.org/packages/fd/5d/2aeb513c6841270783b216478c6edc65b128c6889850c5f77568aa3a3098/coverage-7.11.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2970c03fefee2a5f1aebc91201a0706a7d0061cc71ab452bb5c5345b7174a349", size = 259537, upload-time = "2025-11-08T20:26:08.481Z" }, + { url = "https://files.pythonhosted.org/packages/d2/45/ddd9b22ec1b5c69cc579b149619c354f981aaaafc072b92574f2d3d6c267/coverage-7.11.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b9f28b900d96d83e2ae855b68d5cf5a704fa0b5e618999133fd2fb3bbe35ecb1", size = 261648, upload-time = "2025-11-08T20:26:10.551Z" }, + { url = "https://files.pythonhosted.org/packages/29/e2/8743b7281decd3f73b964389fea18305584dd6ba96f0aff91b4880b50310/coverage-7.11.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8b9a7ebc6a29202fb095877fd8362aab09882894d1c950060c76d61fb116114", size = 264061, upload-time = "2025-11-08T20:26:12.306Z" }, + { url = "https://files.pythonhosted.org/packages/00/1b/46daea7c4349c4530c62383f45148cc878845374b7a632e3ac2769b2f26a/coverage-7.11.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4f8f6bcaa7fe162460abb38f7a5dbfd7f47cfc51e2a0bf0d3ef9e51427298391", size = 258580, upload-time = "2025-11-08T20:26:14.5Z" }, + { url = "https://files.pythonhosted.org/packages/d7/53/f9b1c2d921d585dd6499e05bd71420950cac4e800f71525eb3d2690944fe/coverage-7.11.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:461577af3f8ad4da244a55af66c0731b68540ce571dbdc02598b5ec9e7a09e73", size = 261526, upload-time = "2025-11-08T20:26:16.353Z" }, + { url = "https://files.pythonhosted.org/packages/86/7d/55acee453a71a71b08b05848d718ce6ac4559d051b4a2c407b0940aa72be/coverage-7.11.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:5b284931d57389ec97a63fb1edf91c68ec369cee44bc40b37b5c3985ba0a2914", size = 259135, upload-time = "2025-11-08T20:26:18.101Z" }, + { url = "https://files.pythonhosted.org/packages/7d/3f/cf1e0217efdebab257eb0f487215fe02ff2b6f914cea641b2016c33358e1/coverage-7.11.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2ca963994d28e44285dc104cf94b25d8a7fd0c6f87cf944f46a23f473910703f", size = 257959, upload-time = "2025-11-08T20:26:19.894Z" }, + { url = "https://files.pythonhosted.org/packages/68/0e/e9be33e55346e650c3218a313e888df80418415462c63bceaf4b31e36ab5/coverage-7.11.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e7d3fccd5781c5d29ca0bd1ea272630f05cd40a71d419e7e6105c0991400eb14", size = 260290, upload-time = "2025-11-08T20:26:22.05Z" }, + { url = "https://files.pythonhosted.org/packages/d2/1d/9e93937c2a9bd255bb5efeff8c5df1c8322e508371f76f21a58af0e36a31/coverage-7.11.2-cp314-cp314t-win32.whl", hash = "sha256:f633da28958f57b846e955d28661b2b323d8ae84668756e1eea64045414dbe34", size = 220691, upload-time = "2025-11-08T20:26:24.043Z" }, + { url = "https://files.pythonhosted.org/packages/bf/30/893b5a67e2914cf2be8e99c511b8084eaa8c0585e42d8b3cd78208f5f126/coverage-7.11.2-cp314-cp314t-win_amd64.whl", hash = "sha256:410cafc1aba1f7eb8c09823d5da381be30a2c9b3595758a4c176fcfc04732731", size = 221800, upload-time = "2025-11-08T20:26:26.24Z" }, + { url = "https://files.pythonhosted.org/packages/2b/8b/6d93448c494a35000cc97d8d5d9c9b3774fa2b0c0d5be55f16877f962d71/coverage-7.11.2-cp314-cp314t-win_arm64.whl", hash = "sha256:595c6bb2b565cc2d930ee634cae47fa959dfd24cc0e8ae4cf2b6e7e131e0d1f7", size = 219838, upload-time = "2025-11-08T20:26:28.479Z" }, + { url = "https://files.pythonhosted.org/packages/05/7a/99766a75c88e576f47c2d9a06416ff5d95be9b42faca5c37e1ab77c4cd1a/coverage-7.11.2-py3-none-any.whl", hash = "sha256:2442afabe9e83b881be083238bb7cf5afd4a10e47f29b6094470338d2336b33c", size = 208891, upload-time = "2025-11-08T20:26:30.739Z" }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version <= '3.11'" }, +] + +[[package]] +name = "docutils" +version = "0.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444, upload-time = "2024-04-23T18:57:18.24Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, +] + +[[package]] +name = "flake8" +version = "7.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mccabe" }, + { name = "pycodestyle" }, + { name = "pyflakes" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/af/fbfe3c4b5a657d79e5c47a2827a362f9e1b763336a52f926126aa6dc7123/flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872", size = 48326, upload-time = "2025-06-20T19:31:35.838Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e", size = 57922, upload-time = "2025-06-20T19:31:34.425Z" }, +] + +[[package]] +name = "flake8-docstrings" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "flake8" }, + { name = "pydocstyle" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/93/24/f839e3a06e18f4643ccb81370909a497297909f15106e6af2fecdef46894/flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af", size = 5995, upload-time = "2023-01-25T14:27:13.903Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/7d/76a278fa43250441ed9300c344f889c7fb1817080c8fb8996b840bf421c2/flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75", size = 4994, upload-time = "2023-01-25T14:27:12.32Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "imagesize" +version = "1.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/84/62473fb57d61e31fef6e36d64a179c8781605429fd927b5dd608c997be31/imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a", size = 1280026, upload-time = "2022-07-01T12:21:05.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ff/62/85c4c919272577931d407be5ba5d71c20f0b616d31a0befe0ae45bb79abd/imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b", size = 8769, upload-time = "2022-07-01T12:21:02.467Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "judge0" +version = "0.1.0.dev0" +source = { editable = "." } +dependencies = [ + { name = "pydantic" }, + { name = "requests" }, +] + +[package.dev-dependencies] +dev = [ + { name = "flake8-docstrings" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "python-dotenv" }, + { name = "sphinx" }, + { name = "sphinx-autodoc-typehints" }, + { name = "sphinx-multiversion" }, + { name = "sphinxawesome-theme" }, + { name = "ufmt" }, +] +docs = [ + { name = "sphinx" }, + { name = "sphinx-autodoc-typehints" }, + { name = "sphinx-multiversion" }, + { name = "sphinxawesome-theme" }, +] +test = [ + { name = "flake8-docstrings" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "python-dotenv" }, + { name = "ufmt" }, +] + +[package.metadata] +requires-dist = [ + { name = "pydantic", specifier = ">=2.0.0,<3.0.0" }, + { name = "requests", specifier = ">=2.28.0,<3.0.0" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "flake8-docstrings", specifier = "==1.7.0" }, + { name = "pytest", specifier = "==8.3.3" }, + { name = "pytest-cov", specifier = "==6.0.0" }, + { name = "python-dotenv", specifier = "==1.0.1" }, + { name = "sphinx", specifier = "==8.1.3" }, + { name = "sphinx-autodoc-typehints", specifier = "==2.3.0" }, + { name = "sphinx-multiversion", specifier = "==0.2.4" }, + { name = "sphinxawesome-theme", specifier = "==5.3.2" }, + { name = "ufmt", specifier = "==2.7.3" }, +] +docs = [ + { name = "sphinx", specifier = "==8.1.3" }, + { name = "sphinx-autodoc-typehints", specifier = "==2.3.0" }, + { name = "sphinx-multiversion", specifier = "==0.2.4" }, + { name = "sphinxawesome-theme", specifier = "==5.3.2" }, +] +test = [ + { name = "flake8-docstrings", specifier = "==1.7.0" }, + { name = "pytest", specifier = "==8.3.3" }, + { name = "pytest-cov", specifier = "==6.0.0" }, + { name = "python-dotenv", specifier = "==1.0.1" }, + { name = "ufmt", specifier = "==2.7.3" }, +] + +[[package]] +name = "libcst" +version = "1.8.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml", marker = "python_full_version != '3.13.*'" }, + { name = "pyyaml-ft", marker = "python_full_version == '3.13.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/cd/337df968b38d94c5aabd3e1b10630f047a2b345f6e1d4456bd9fe7417537/libcst-1.8.6.tar.gz", hash = "sha256:f729c37c9317126da9475bdd06a7208eb52fcbd180a6341648b45a56b4ba708b", size = 891354, upload-time = "2025-11-03T22:33:30.621Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/52/97d5454dee9d014821fe0c88f3dc0e83131b97dd074a4d49537056a75475/libcst-1.8.6-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a20c5182af04332cc94d8520792befda06d73daf2865e6dddc5161c72ea92cb9", size = 2211698, upload-time = "2025-11-03T22:31:50.117Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a4/d1205985d378164687af3247a9c8f8bdb96278b0686ac98ab951bc6d336a/libcst-1.8.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:36473e47cb199b7e6531d653ee6ffed057de1d179301e6c67f651f3af0b499d6", size = 2093104, upload-time = "2025-11-03T22:31:52.189Z" }, + { url = "https://files.pythonhosted.org/packages/9e/de/1338da681b7625b51e584922576d54f1b8db8fc7ff4dc79121afc5d4d2cd/libcst-1.8.6-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:06fc56335a45d61b7c1b856bfab4587b84cfe31e9d6368f60bb3c9129d900f58", size = 2237419, upload-time = "2025-11-03T22:31:53.526Z" }, + { url = "https://files.pythonhosted.org/packages/50/06/ee66f2d83b870534756e593d464d8b33b0914c224dff3a407e0f74dc04e0/libcst-1.8.6-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:6b23d14a7fc0addd9795795763af26b185deb7c456b1e7cc4d5228e69dab5ce8", size = 2300820, upload-time = "2025-11-03T22:31:55.995Z" }, + { url = "https://files.pythonhosted.org/packages/9c/ca/959088729de8e0eac8dd516e4fb8623d8d92bad539060fa85c9e94d418a5/libcst-1.8.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:16cfe0cfca5fd840e1fb2c30afb628b023d3085b30c3484a79b61eae9d6fe7ba", size = 2301201, upload-time = "2025-11-03T22:31:57.347Z" }, + { url = "https://files.pythonhosted.org/packages/c2/4c/2a21a8c452436097dfe1da277f738c3517f3f728713f16d84b9a3d67ca8d/libcst-1.8.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:455f49a93aea4070132c30ebb6c07c2dea0ba6c1fde5ffde59fc45dbb9cfbe4b", size = 2408213, upload-time = "2025-11-03T22:31:59.221Z" }, + { url = "https://files.pythonhosted.org/packages/3e/26/8f7b671fad38a515bb20b038718fd2221ab658299119ac9bcec56c2ced27/libcst-1.8.6-cp310-cp310-win_amd64.whl", hash = "sha256:72cca15800ffc00ba25788e4626189fe0bc5fe2a0c1cb4294bce2e4df21cc073", size = 2119189, upload-time = "2025-11-03T22:32:00.696Z" }, + { url = "https://files.pythonhosted.org/packages/5b/bf/ffb23a48e27001165cc5c81c5d9b3d6583b21b7f5449109e03a0020b060c/libcst-1.8.6-cp310-cp310-win_arm64.whl", hash = "sha256:6cad63e3a26556b020b634d25a8703b605c0e0b491426b3e6b9e12ed20f09100", size = 2001736, upload-time = "2025-11-03T22:32:02.986Z" }, + { url = "https://files.pythonhosted.org/packages/dc/15/95c2ecadc0fb4af8a7057ac2012a4c0ad5921b9ef1ace6c20006b56d3b5f/libcst-1.8.6-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3649a813660fbffd7bc24d3f810b1f75ac98bd40d9d6f56d1f0ee38579021073", size = 2211289, upload-time = "2025-11-03T22:32:04.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/c3/7e1107acd5ed15cf60cc07c7bb64498a33042dc4821874aea3ec4942f3cd/libcst-1.8.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0cbe17067055829607c5ba4afa46bfa4d0dd554c0b5a583546e690b7367a29b6", size = 2092927, upload-time = "2025-11-03T22:32:06.209Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ff/0d2be87f67e2841a4a37d35505e74b65991d30693295c46fc0380ace0454/libcst-1.8.6-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:59a7e388c57d21d63722018978a8ddba7b176e3a99bd34b9b84a576ed53f2978", size = 2237002, upload-time = "2025-11-03T22:32:07.559Z" }, + { url = "https://files.pythonhosted.org/packages/69/99/8c4a1b35c7894ccd7d33eae01ac8967122f43da41325223181ca7e4738fe/libcst-1.8.6-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:b6c1248cc62952a3a005792b10cdef2a4e130847be9c74f33a7d617486f7e532", size = 2301048, upload-time = "2025-11-03T22:32:08.869Z" }, + { url = "https://files.pythonhosted.org/packages/9b/8b/d1aa811eacf936cccfb386ae0585aa530ea1221ccf528d67144e041f5915/libcst-1.8.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6421a930b028c5ef4a943b32a5a78b7f1bf15138214525a2088f11acbb7d3d64", size = 2300675, upload-time = "2025-11-03T22:32:10.579Z" }, + { url = "https://files.pythonhosted.org/packages/c6/6b/7b65cd41f25a10c1fef2389ddc5c2b2cc23dc4d648083fa3e1aa7e0eeac2/libcst-1.8.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6d8b67874f2188399a71a71731e1ba2d1a2c3173b7565d1cc7ffb32e8fbaba5b", size = 2407934, upload-time = "2025-11-03T22:32:11.856Z" }, + { url = "https://files.pythonhosted.org/packages/c5/8b/401cfff374bb3b785adfad78f05225225767ee190997176b2a9da9ed9460/libcst-1.8.6-cp311-cp311-win_amd64.whl", hash = "sha256:b0d8c364c44ae343937f474b2e492c1040df96d94530377c2f9263fb77096e4f", size = 2119247, upload-time = "2025-11-03T22:32:13.279Z" }, + { url = "https://files.pythonhosted.org/packages/f1/17/085f59eaa044b6ff6bc42148a5449df2b7f0ba567307de7782fe85c39ee2/libcst-1.8.6-cp311-cp311-win_arm64.whl", hash = "sha256:5dcaaebc835dfe5755bc85f9b186fb7e2895dda78e805e577fef1011d51d5a5c", size = 2001774, upload-time = "2025-11-03T22:32:14.647Z" }, + { url = "https://files.pythonhosted.org/packages/0c/3c/93365c17da3d42b055a8edb0e1e99f1c60c776471db6c9b7f1ddf6a44b28/libcst-1.8.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0c13d5bd3d8414a129e9dccaf0e5785108a4441e9b266e1e5e9d1f82d1b943c9", size = 2206166, upload-time = "2025-11-03T22:32:16.012Z" }, + { url = "https://files.pythonhosted.org/packages/1d/cb/7530940e6ac50c6dd6022349721074e19309eb6aa296e942ede2213c1a19/libcst-1.8.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f1472eeafd67cdb22544e59cf3bfc25d23dc94058a68cf41f6654ff4fcb92e09", size = 2083726, upload-time = "2025-11-03T22:32:17.312Z" }, + { url = "https://files.pythonhosted.org/packages/1b/cf/7e5eaa8c8f2c54913160671575351d129170db757bb5e4b7faffed022271/libcst-1.8.6-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:089c58e75cb142ec33738a1a4ea7760a28b40c078ab2fd26b270dac7d2633a4d", size = 2235755, upload-time = "2025-11-03T22:32:18.859Z" }, + { url = "https://files.pythonhosted.org/packages/55/54/570ec2b0e9a3de0af9922e3bb1b69a5429beefbc753a7ea770a27ad308bd/libcst-1.8.6-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c9d7aeafb1b07d25a964b148c0dda9451efb47bbbf67756e16eeae65004b0eb5", size = 2301473, upload-time = "2025-11-03T22:32:20.499Z" }, + { url = "https://files.pythonhosted.org/packages/11/4c/163457d1717cd12181c421a4cca493454bcabd143fc7e53313bc6a4ad82a/libcst-1.8.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:207481197afd328aa91d02670c15b48d0256e676ce1ad4bafb6dc2b593cc58f1", size = 2298899, upload-time = "2025-11-03T22:32:21.765Z" }, + { url = "https://files.pythonhosted.org/packages/35/1d/317ddef3669883619ef3d3395ea583305f353ef4ad87d7a5ac1c39be38e3/libcst-1.8.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:375965f34cc6f09f5f809244d3ff9bd4f6cb6699f571121cebce53622e7e0b86", size = 2408239, upload-time = "2025-11-03T22:32:23.275Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a1/f47d8cccf74e212dd6044b9d6dbc223636508da99acff1d54786653196bc/libcst-1.8.6-cp312-cp312-win_amd64.whl", hash = "sha256:da95b38693b989eaa8d32e452e8261cfa77fe5babfef1d8d2ac25af8c4aa7e6d", size = 2119660, upload-time = "2025-11-03T22:32:24.822Z" }, + { url = "https://files.pythonhosted.org/packages/19/d0/dd313bf6a7942cdf951828f07ecc1a7695263f385065edc75ef3016a3cb5/libcst-1.8.6-cp312-cp312-win_arm64.whl", hash = "sha256:bff00e1c766658adbd09a175267f8b2f7616e5ee70ce45db3d7c4ce6d9f6bec7", size = 1999824, upload-time = "2025-11-03T22:32:26.131Z" }, + { url = "https://files.pythonhosted.org/packages/90/01/723cd467ec267e712480c772aacc5aa73f82370c9665162fd12c41b0065b/libcst-1.8.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7445479ebe7d1aff0ee094ab5a1c7718e1ad78d33e3241e1a1ec65dcdbc22ffb", size = 2206386, upload-time = "2025-11-03T22:32:27.422Z" }, + { url = "https://files.pythonhosted.org/packages/17/50/b944944f910f24c094f9b083f76f61e3985af5a376f5342a21e01e2d1a81/libcst-1.8.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4fc3fef8a2c983e7abf5d633e1884c5dd6fa0dcb8f6e32035abd3d3803a3a196", size = 2083945, upload-time = "2025-11-03T22:32:28.847Z" }, + { url = "https://files.pythonhosted.org/packages/36/a1/bd1b2b2b7f153d82301cdaddba787f4a9fc781816df6bdb295ca5f88b7cf/libcst-1.8.6-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:1a3a5e4ee870907aa85a4076c914ae69066715a2741b821d9bf16f9579de1105", size = 2235818, upload-time = "2025-11-03T22:32:30.504Z" }, + { url = "https://files.pythonhosted.org/packages/b9/ab/f5433988acc3b4d188c4bb154e57837df9488cc9ab551267cdeabd3bb5e7/libcst-1.8.6-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:6609291c41f7ad0bac570bfca5af8fea1f4a27987d30a1fa8b67fe5e67e6c78d", size = 2301289, upload-time = "2025-11-03T22:32:31.812Z" }, + { url = "https://files.pythonhosted.org/packages/5d/57/89f4ba7a6f1ac274eec9903a9e9174890d2198266eee8c00bc27eb45ecf7/libcst-1.8.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:25eaeae6567091443b5374b4c7d33a33636a2d58f5eda02135e96fc6c8807786", size = 2299230, upload-time = "2025-11-03T22:32:33.242Z" }, + { url = "https://files.pythonhosted.org/packages/f2/36/0aa693bc24cce163a942df49d36bf47a7ed614a0cd5598eee2623bc31913/libcst-1.8.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:04030ea4d39d69a65873b1d4d877def1c3951a7ada1824242539e399b8763d30", size = 2408519, upload-time = "2025-11-03T22:32:34.678Z" }, + { url = "https://files.pythonhosted.org/packages/db/18/6dd055b5f15afa640fb3304b2ee9df8b7f72e79513814dbd0a78638f4a0e/libcst-1.8.6-cp313-cp313-win_amd64.whl", hash = "sha256:8066f1b70f21a2961e96bedf48649f27dfd5ea68be5cd1bed3742b047f14acde", size = 2119853, upload-time = "2025-11-03T22:32:36.287Z" }, + { url = "https://files.pythonhosted.org/packages/c9/ed/5ddb2a22f0b0abdd6dcffa40621ada1feaf252a15e5b2733a0a85dfd0429/libcst-1.8.6-cp313-cp313-win_arm64.whl", hash = "sha256:c188d06b583900e662cd791a3f962a8c96d3dfc9b36ea315be39e0a4c4792ebf", size = 1999808, upload-time = "2025-11-03T22:32:38.1Z" }, + { url = "https://files.pythonhosted.org/packages/25/d3/72b2de2c40b97e1ef4a1a1db4e5e52163fc7e7740ffef3846d30bc0096b5/libcst-1.8.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c41c76e034a1094afed7057023b1d8967f968782433f7299cd170eaa01ec033e", size = 2190553, upload-time = "2025-11-03T22:32:39.819Z" }, + { url = "https://files.pythonhosted.org/packages/0d/20/983b7b210ccc3ad94a82db54230e92599c4a11b9cfc7ce3bc97c1d2df75c/libcst-1.8.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5432e785322aba3170352f6e72b32bea58d28abd141ac37cc9b0bf6b7c778f58", size = 2074717, upload-time = "2025-11-03T22:32:41.373Z" }, + { url = "https://files.pythonhosted.org/packages/13/f2/9e01678fedc772e09672ed99930de7355757035780d65d59266fcee212b8/libcst-1.8.6-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:85b7025795b796dea5284d290ff69de5089fc8e989b25d6f6f15b6800be7167f", size = 2225834, upload-time = "2025-11-03T22:32:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/4a/0d/7bed847b5c8c365e9f1953da274edc87577042bee5a5af21fba63276e756/libcst-1.8.6-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:536567441182a62fb706e7aa954aca034827b19746832205953b2c725d254a93", size = 2287107, upload-time = "2025-11-03T22:32:44.549Z" }, + { url = "https://files.pythonhosted.org/packages/02/f0/7e51fa84ade26c518bfbe7e2e4758b56d86a114c72d60309ac0d350426c4/libcst-1.8.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2f04d3672bde1704f383a19e8f8331521abdbc1ed13abb349325a02ac56e5012", size = 2288672, upload-time = "2025-11-03T22:32:45.867Z" }, + { url = "https://files.pythonhosted.org/packages/ad/cd/15762659a3f5799d36aab1bc2b7e732672722e249d7800e3c5f943b41250/libcst-1.8.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f04febcd70e1e67917be7de513c8d4749d2e09206798558d7fe632134426ea4", size = 2392661, upload-time = "2025-11-03T22:32:47.232Z" }, + { url = "https://files.pythonhosted.org/packages/e4/6b/b7f9246c323910fcbe021241500f82e357521495dcfe419004dbb272c7cb/libcst-1.8.6-cp313-cp313t-win_amd64.whl", hash = "sha256:1dc3b897c8b0f7323412da3f4ad12b16b909150efc42238e19cbf19b561cc330", size = 2105068, upload-time = "2025-11-03T22:32:49.145Z" }, + { url = "https://files.pythonhosted.org/packages/a6/0b/4fd40607bc4807ec2b93b054594373d7fa3d31bb983789901afcb9bcebe9/libcst-1.8.6-cp313-cp313t-win_arm64.whl", hash = "sha256:44f38139fa95e488db0f8976f9c7ca39a64d6bc09f2eceef260aa1f6da6a2e42", size = 1985181, upload-time = "2025-11-03T22:32:50.597Z" }, + { url = "https://files.pythonhosted.org/packages/3a/60/4105441989e321f7ad0fd28ffccb83eb6aac0b7cfb0366dab855dcccfbe5/libcst-1.8.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:b188e626ce61de5ad1f95161b8557beb39253de4ec74fc9b1f25593324a0279c", size = 2204202, upload-time = "2025-11-03T22:32:52.311Z" }, + { url = "https://files.pythonhosted.org/packages/67/2f/51a6f285c3a183e50cfe5269d4a533c21625aac2c8de5cdf2d41f079320d/libcst-1.8.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:87e74f7d7dfcba9efa91127081e22331d7c42515f0a0ac6e81d4cf2c3ed14661", size = 2083581, upload-time = "2025-11-03T22:32:54.269Z" }, + { url = "https://files.pythonhosted.org/packages/2f/64/921b1c19b638860af76cdb28bc81d430056592910b9478eea49e31a7f47a/libcst-1.8.6-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:3a926a4b42015ee24ddfc8ae940c97bd99483d286b315b3ce82f3bafd9f53474", size = 2236495, upload-time = "2025-11-03T22:32:55.723Z" }, + { url = "https://files.pythonhosted.org/packages/12/a8/b00592f9bede618cbb3df6ffe802fc65f1d1c03d48a10d353b108057d09c/libcst-1.8.6-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:3f4fbb7f569e69fd9e89d9d9caa57ca42c577c28ed05062f96a8c207594e75b8", size = 2301466, upload-time = "2025-11-03T22:32:57.337Z" }, + { url = "https://files.pythonhosted.org/packages/af/df/790d9002f31580fefd0aec2f373a0f5da99070e04c5e8b1c995d0104f303/libcst-1.8.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:08bd63a8ce674be431260649e70fca1d43f1554f1591eac657f403ff8ef82c7a", size = 2300264, upload-time = "2025-11-03T22:32:58.852Z" }, + { url = "https://files.pythonhosted.org/packages/21/de/dc3f10e65bab461be5de57850d2910a02c24c3ddb0da28f0e6e4133c3487/libcst-1.8.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e00e275d4ba95d4963431ea3e409aa407566a74ee2bf309a402f84fc744abe47", size = 2408572, upload-time = "2025-11-03T22:33:00.552Z" }, + { url = "https://files.pythonhosted.org/packages/20/3b/35645157a7590891038b077db170d6dd04335cd2e82a63bdaa78c3297dfe/libcst-1.8.6-cp314-cp314-win_amd64.whl", hash = "sha256:fea5c7fa26556eedf277d4f72779c5ede45ac3018650721edd77fd37ccd4a2d4", size = 2193917, upload-time = "2025-11-03T22:33:02.354Z" }, + { url = "https://files.pythonhosted.org/packages/b3/a2/1034a9ba7d3e82f2c2afaad84ba5180f601aed676d92b76325797ad60951/libcst-1.8.6-cp314-cp314-win_arm64.whl", hash = "sha256:bb9b4077bdf8857b2483879cbbf70f1073bc255b057ec5aac8a70d901bb838e9", size = 2078748, upload-time = "2025-11-03T22:33:03.707Z" }, + { url = "https://files.pythonhosted.org/packages/95/a1/30bc61e8719f721a5562f77695e6154e9092d1bdf467aa35d0806dcd6cea/libcst-1.8.6-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:55ec021a296960c92e5a33b8d93e8ad4182b0eab657021f45262510a58223de1", size = 2188980, upload-time = "2025-11-03T22:33:05.152Z" }, + { url = "https://files.pythonhosted.org/packages/2c/14/c660204532407c5628e3b615015a902ed2d0b884b77714a6bdbe73350910/libcst-1.8.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ba9ab2b012fbd53b36cafd8f4440a6b60e7e487cd8b87428e57336b7f38409a4", size = 2074828, upload-time = "2025-11-03T22:33:06.864Z" }, + { url = "https://files.pythonhosted.org/packages/82/e2/c497c354943dff644749f177ee9737b09ed811b8fc842b05709a40fe0d1b/libcst-1.8.6-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c0a0cc80aebd8aa15609dd4d330611cbc05e9b4216bcaeabba7189f99ef07c28", size = 2225568, upload-time = "2025-11-03T22:33:08.354Z" }, + { url = "https://files.pythonhosted.org/packages/86/ef/45999676d07bd6d0eefa28109b4f97124db114e92f9e108de42ba46a8028/libcst-1.8.6-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:42a4f68121e2e9c29f49c97f6154e8527cd31021809cc4a941c7270aa64f41aa", size = 2286523, upload-time = "2025-11-03T22:33:10.206Z" }, + { url = "https://files.pythonhosted.org/packages/f4/6c/517d8bf57d9f811862f4125358caaf8cd3320a01291b3af08f7b50719db4/libcst-1.8.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a434c521fadaf9680788b50d5c21f4048fa85ed19d7d70bd40549fbaeeecab1", size = 2288044, upload-time = "2025-11-03T22:33:11.628Z" }, + { url = "https://files.pythonhosted.org/packages/83/ce/24d7d49478ffb61207f229239879845da40a374965874f5ee60f96b02ddb/libcst-1.8.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6a65f844d813ab4ef351443badffa0ae358f98821561d19e18b3190f59e71996", size = 2392605, upload-time = "2025-11-03T22:33:12.962Z" }, + { url = "https://files.pythonhosted.org/packages/39/c3/829092ead738b71e96a4e96896c96f276976e5a8a58b4473ed813d7c962b/libcst-1.8.6-cp314-cp314t-win_amd64.whl", hash = "sha256:bdb14bc4d4d83a57062fed2c5da93ecb426ff65b0dc02ddf3481040f5f074a82", size = 2181581, upload-time = "2025-11-03T22:33:14.514Z" }, + { url = "https://files.pythonhosted.org/packages/98/6d/5d6a790a02eb0d9d36c4aed4f41b277497e6178900b2fa29c35353aa45ed/libcst-1.8.6-cp314-cp314t-win_arm64.whl", hash = "sha256:819c8081e2948635cab60c603e1bbdceccdfe19104a242530ad38a36222cb88f", size = 2065000, upload-time = "2025-11-03T22:33:16.257Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" }, + { url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" }, + { url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" }, + { url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" }, + { url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" }, + { url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" }, + { url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" }, + { url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" }, + { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, + { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, + { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, +] + +[[package]] +name = "moreorless" +version = "0.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8d/85/2e4999ac4a21ab3c5f31e2a48e0989a80be3afc512a7983e3253615983d4/moreorless-0.5.0.tar.gz", hash = "sha256:560a04f85006fccd74feaa4b6213a446392ff7b5ec0194a5464b6c30f182fa33", size = 14093, upload-time = "2025-05-04T22:29:59.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fa/2e/9ea80ca55b73530b7639c6f146a58f636ddfe5a852ad467a44fe3e80d809/moreorless-0.5.0-py3-none-any.whl", hash = "sha256:66228870cd2f14bad5c3c3780aa71e29d3b2d9b5a01c03bfbf105efd4f668ecf", size = 14380, upload-time = "2025-05-04T22:29:57.417Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/61/33/9611380c2bdb1225fdef633e2a9610622310fed35ab11dac9620972ee088/platformdirs-4.5.0.tar.gz", hash = "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312", size = 21632, upload-time = "2025-10-08T17:44:48.791Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/cb/ac7874b3e5d58441674fb70742e6c374b28b0c7cb988d37d991cde47166c/platformdirs-4.5.0-py3-none-any.whl", hash = "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3", size = 18651, upload-time = "2025-10-08T17:44:47.223Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pycodestyle" +version = "2.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/e0/abfd2a0d2efe47670df87f3e3a0e2edda42f055053c85361f19c0e2c1ca8/pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", size = 39472, upload-time = "2025-06-20T18:49:48.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d", size = 31594, upload-time = "2025-06-20T18:49:47.491Z" }, +] + +[[package]] +name = "pydantic" +version = "2.12.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/ad/a17bc283d7d81837c061c49e3eaa27a45991759a1b7eae1031921c6bd924/pydantic-2.12.4.tar.gz", hash = "sha256:0f8cb9555000a4b5b617f66bfd2566264c4984b27589d3b845685983e8ea85ac", size = 821038, upload-time = "2025-11-05T10:50:08.59Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl", hash = "sha256:92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e", size = 463400, upload-time = "2025-11-05T10:50:06.732Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.41.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/90/32c9941e728d564b411d574d8ee0cf09b12ec978cb22b294995bae5549a5/pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146", size = 2107298, upload-time = "2025-11-04T13:39:04.116Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a8/61c96a77fe28993d9a6fb0f4127e05430a267b235a124545d79fea46dd65/pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2", size = 1901475, upload-time = "2025-11-04T13:39:06.055Z" }, + { url = "https://files.pythonhosted.org/packages/5d/b6/338abf60225acc18cdc08b4faef592d0310923d19a87fba1faf05af5346e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97", size = 1918815, upload-time = "2025-11-04T13:39:10.41Z" }, + { url = "https://files.pythonhosted.org/packages/d1/1c/2ed0433e682983d8e8cba9c8d8ef274d4791ec6a6f24c58935b90e780e0a/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9", size = 2065567, upload-time = "2025-11-04T13:39:12.244Z" }, + { url = "https://files.pythonhosted.org/packages/b3/24/cf84974ee7d6eae06b9e63289b7b8f6549d416b5c199ca2d7ce13bbcf619/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52", size = 2230442, upload-time = "2025-11-04T13:39:13.962Z" }, + { url = "https://files.pythonhosted.org/packages/fd/21/4e287865504b3edc0136c89c9c09431be326168b1eb7841911cbc877a995/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941", size = 2350956, upload-time = "2025-11-04T13:39:15.889Z" }, + { url = "https://files.pythonhosted.org/packages/a8/76/7727ef2ffa4b62fcab916686a68a0426b9b790139720e1934e8ba797e238/pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a", size = 2068253, upload-time = "2025-11-04T13:39:17.403Z" }, + { url = "https://files.pythonhosted.org/packages/d5/8c/a4abfc79604bcb4c748e18975c44f94f756f08fb04218d5cb87eb0d3a63e/pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c", size = 2177050, upload-time = "2025-11-04T13:39:19.351Z" }, + { url = "https://files.pythonhosted.org/packages/67/b1/de2e9a9a79b480f9cb0b6e8b6ba4c50b18d4e89852426364c66aa82bb7b3/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2", size = 2147178, upload-time = "2025-11-04T13:39:21Z" }, + { url = "https://files.pythonhosted.org/packages/16/c1/dfb33f837a47b20417500efaa0378adc6635b3c79e8369ff7a03c494b4ac/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556", size = 2341833, upload-time = "2025-11-04T13:39:22.606Z" }, + { url = "https://files.pythonhosted.org/packages/47/36/00f398642a0f4b815a9a558c4f1dca1b4020a7d49562807d7bc9ff279a6c/pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49", size = 2321156, upload-time = "2025-11-04T13:39:25.843Z" }, + { url = "https://files.pythonhosted.org/packages/7e/70/cad3acd89fde2010807354d978725ae111ddf6d0ea46d1ea1775b5c1bd0c/pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba", size = 1989378, upload-time = "2025-11-04T13:39:27.92Z" }, + { url = "https://files.pythonhosted.org/packages/76/92/d338652464c6c367e5608e4488201702cd1cbb0f33f7b6a85a60fe5f3720/pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9", size = 2013622, upload-time = "2025-11-04T13:39:29.848Z" }, + { url = "https://files.pythonhosted.org/packages/e8/72/74a989dd9f2084b3d9530b0915fdda64ac48831c30dbf7c72a41a5232db8/pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6", size = 2105873, upload-time = "2025-11-04T13:39:31.373Z" }, + { url = "https://files.pythonhosted.org/packages/12/44/37e403fd9455708b3b942949e1d7febc02167662bf1a7da5b78ee1ea2842/pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b", size = 1899826, upload-time = "2025-11-04T13:39:32.897Z" }, + { url = "https://files.pythonhosted.org/packages/33/7f/1d5cab3ccf44c1935a359d51a8a2a9e1a654b744b5e7f80d41b88d501eec/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a", size = 1917869, upload-time = "2025-11-04T13:39:34.469Z" }, + { url = "https://files.pythonhosted.org/packages/6e/6a/30d94a9674a7fe4f4744052ed6c5e083424510be1e93da5bc47569d11810/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8", size = 2063890, upload-time = "2025-11-04T13:39:36.053Z" }, + { url = "https://files.pythonhosted.org/packages/50/be/76e5d46203fcb2750e542f32e6c371ffa9b8ad17364cf94bb0818dbfb50c/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e", size = 2229740, upload-time = "2025-11-04T13:39:37.753Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ee/fed784df0144793489f87db310a6bbf8118d7b630ed07aa180d6067e653a/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1", size = 2350021, upload-time = "2025-11-04T13:39:40.94Z" }, + { url = "https://files.pythonhosted.org/packages/c8/be/8fed28dd0a180dca19e72c233cbf58efa36df055e5b9d90d64fd1740b828/pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b", size = 2066378, upload-time = "2025-11-04T13:39:42.523Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3b/698cf8ae1d536a010e05121b4958b1257f0b5522085e335360e53a6b1c8b/pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b", size = 2175761, upload-time = "2025-11-04T13:39:44.553Z" }, + { url = "https://files.pythonhosted.org/packages/b8/ba/15d537423939553116dea94ce02f9c31be0fa9d0b806d427e0308ec17145/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284", size = 2146303, upload-time = "2025-11-04T13:39:46.238Z" }, + { url = "https://files.pythonhosted.org/packages/58/7f/0de669bf37d206723795f9c90c82966726a2ab06c336deba4735b55af431/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594", size = 2340355, upload-time = "2025-11-04T13:39:48.002Z" }, + { url = "https://files.pythonhosted.org/packages/e5/de/e7482c435b83d7e3c3ee5ee4451f6e8973cff0eb6007d2872ce6383f6398/pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e", size = 2319875, upload-time = "2025-11-04T13:39:49.705Z" }, + { url = "https://files.pythonhosted.org/packages/fe/e6/8c9e81bb6dd7560e33b9053351c29f30c8194b72f2d6932888581f503482/pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b", size = 1987549, upload-time = "2025-11-04T13:39:51.842Z" }, + { url = "https://files.pythonhosted.org/packages/11/66/f14d1d978ea94d1bc21fc98fcf570f9542fe55bfcc40269d4e1a21c19bf7/pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe", size = 2011305, upload-time = "2025-11-04T13:39:53.485Z" }, + { url = "https://files.pythonhosted.org/packages/56/d8/0e271434e8efd03186c5386671328154ee349ff0354d83c74f5caaf096ed/pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f", size = 1972902, upload-time = "2025-11-04T13:39:56.488Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, + { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, + { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, + { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, + { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, + { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, + { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, + { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, + { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, + { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, + { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, + { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, + { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, + { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, + { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, + { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, + { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, + { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, + { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, + { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, + { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, + { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, + { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, + { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, + { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, + { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, + { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, + { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, + { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, + { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, + { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, + { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, + { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, + { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, + { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, + { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, + { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, + { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, + { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, + { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, + { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, + { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, + { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, + { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, + { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, + { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, + { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, + { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, + { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, + { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, + { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, + { url = "https://files.pythonhosted.org/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034", size = 2115441, upload-time = "2025-11-04T13:42:39.557Z" }, + { url = "https://files.pythonhosted.org/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c", size = 1930291, upload-time = "2025-11-04T13:42:42.169Z" }, + { url = "https://files.pythonhosted.org/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2", size = 1948632, upload-time = "2025-11-04T13:42:44.564Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1b/687711069de7efa6af934e74f601e2a4307365e8fdc404703afc453eab26/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad", size = 2138905, upload-time = "2025-11-04T13:42:47.156Z" }, + { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, + { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, + { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, + { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b0/1a2aa41e3b5a4ba11420aba2d091b2d17959c8d1519ece3627c371951e73/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8", size = 2103351, upload-time = "2025-11-04T13:43:02.058Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ee/31b1f0020baaf6d091c87900ae05c6aeae101fa4e188e1613c80e4f1ea31/pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a", size = 1925363, upload-time = "2025-11-04T13:43:05.159Z" }, + { url = "https://files.pythonhosted.org/packages/e1/89/ab8e86208467e467a80deaca4e434adac37b10a9d134cd2f99b28a01e483/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b", size = 2135615, upload-time = "2025-11-04T13:43:08.116Z" }, + { url = "https://files.pythonhosted.org/packages/99/0a/99a53d06dd0348b2008f2f30884b34719c323f16c3be4e6cc1203b74a91d/pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2", size = 2175369, upload-time = "2025-11-04T13:43:12.49Z" }, + { url = "https://files.pythonhosted.org/packages/6d/94/30ca3b73c6d485b9bb0bc66e611cff4a7138ff9736b7e66bcf0852151636/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093", size = 2144218, upload-time = "2025-11-04T13:43:15.431Z" }, + { url = "https://files.pythonhosted.org/packages/87/57/31b4f8e12680b739a91f472b5671294236b82586889ef764b5fbc6669238/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a", size = 2329951, upload-time = "2025-11-04T13:43:18.062Z" }, + { url = "https://files.pythonhosted.org/packages/7d/73/3c2c8edef77b8f7310e6fb012dbc4b8551386ed575b9eb6fb2506e28a7eb/pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963", size = 2318428, upload-time = "2025-11-04T13:43:20.679Z" }, + { url = "https://files.pythonhosted.org/packages/2f/02/8559b1f26ee0d502c74f9cca5c0d2fd97e967e083e006bbbb4e97f3a043a/pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a", size = 2147009, upload-time = "2025-11-04T13:43:23.286Z" }, + { url = "https://files.pythonhosted.org/packages/5f/9b/1b3f0e9f9305839d7e84912f9e8bfbd191ed1b1ef48083609f0dabde978c/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26", size = 2101980, upload-time = "2025-11-04T13:43:25.97Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ed/d71fefcb4263df0da6a85b5d8a7508360f2f2e9b3bf5814be9c8bccdccc1/pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808", size = 1923865, upload-time = "2025-11-04T13:43:28.763Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3a/626b38db460d675f873e4444b4bb030453bbe7b4ba55df821d026a0493c4/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc", size = 2134256, upload-time = "2025-11-04T13:43:31.71Z" }, + { url = "https://files.pythonhosted.org/packages/83/d9/8412d7f06f616bbc053d30cb4e5f76786af3221462ad5eee1f202021eb4e/pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1", size = 2174762, upload-time = "2025-11-04T13:43:34.744Z" }, + { url = "https://files.pythonhosted.org/packages/55/4c/162d906b8e3ba3a99354e20faa1b49a85206c47de97a639510a0e673f5da/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84", size = 2143141, upload-time = "2025-11-04T13:43:37.701Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f2/f11dd73284122713f5f89fc940f370d035fa8e1e078d446b3313955157fe/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770", size = 2330317, upload-time = "2025-11-04T13:43:40.406Z" }, + { url = "https://files.pythonhosted.org/packages/88/9d/b06ca6acfe4abb296110fb1273a4d848a0bfb2ff65f3ee92127b3244e16b/pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f", size = 2316992, upload-time = "2025-11-04T13:43:43.602Z" }, + { url = "https://files.pythonhosted.org/packages/36/c7/cfc8e811f061c841d7990b0201912c3556bfeb99cdcb7ed24adc8d6f8704/pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51", size = 2145302, upload-time = "2025-11-04T13:43:46.64Z" }, +] + +[[package]] +name = "pydocstyle" +version = "6.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "snowballstemmer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/5c/d5385ca59fd065e3c6a5fe19f9bc9d5ea7f2509fa8c9c22fb6b2031dd953/pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1", size = 36796, upload-time = "2023-01-17T20:29:19.838Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/ea/99ddefac41971acad68f14114f38261c1f27dac0b3ec529824ebc739bdaa/pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019", size = 38038, upload-time = "2023-01-17T20:29:18.094Z" }, +] + +[[package]] +name = "pyflakes" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/45/dc/fd034dc20b4b264b3d015808458391acbf9df40b1e54750ef175d39180b1/pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58", size = 64669, upload-time = "2025-06-20T18:45:27.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f", size = 63551, upload-time = "2025-06-20T18:45:26.937Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pytest" +version = "8.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/6c/62bbd536103af674e227c41a8f3dcd022d591f6eed5facb5a0f31ee33bbc/pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181", size = 1442487, upload-time = "2024-09-10T10:52:15.003Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/77/7440a06a8ead44c7757a64362dd22df5760f9b12dc5f11b6188cd2fc27a0/pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2", size = 342341, upload-time = "2024-09-10T10:52:12.54Z" }, +] + +[[package]] +name = "pytest-cov" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage", extra = ["toml"] }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945, upload-time = "2024-10-29T20:13:35.363Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949, upload-time = "2024-10-29T20:13:33.215Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115, upload-time = "2024-01-23T06:33:00.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863, upload-time = "2024-01-23T06:32:58.246Z" }, +] + +[[package]] +name = "pytokens" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/8d/a762be14dae1c3bf280202ba3172020b2b0b4c537f94427435f19c413b72/pytokens-0.3.0.tar.gz", hash = "sha256:2f932b14ed08de5fcf0b391ace2642f858f1394c0857202959000b68ed7a458a", size = 17644, upload-time = "2025-11-05T13:36:35.34Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/25/d9db8be44e205a124f6c98bc0324b2bb149b7431c53877fc6d1038dddaf5/pytokens-0.3.0-py3-none-any.whl", hash = "sha256:95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3", size = 12195, upload-time = "2025-11-05T13:36:33.183Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, + { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, + { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, + { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, + { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, + { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, + { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, + { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, + { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, + { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, + { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, + { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, + { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, + { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyyaml-ft" +version = "8.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/eb/5a0d575de784f9a1f94e2b1288c6886f13f34185e13117ed530f32b6f8a8/pyyaml_ft-8.0.0.tar.gz", hash = "sha256:0c947dce03954c7b5d38869ed4878b2e6ff1d44b08a0d84dc83fdad205ae39ab", size = 141057, upload-time = "2025-06-10T15:32:15.613Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/ba/a067369fe61a2e57fb38732562927d5bae088c73cb9bb5438736a9555b29/pyyaml_ft-8.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8c1306282bc958bfda31237f900eb52c9bedf9b93a11f82e1aab004c9a5657a6", size = 187027, upload-time = "2025-06-10T15:31:48.722Z" }, + { url = "https://files.pythonhosted.org/packages/ad/c5/a3d2020ce5ccfc6aede0d45bcb870298652ac0cf199f67714d250e0cdf39/pyyaml_ft-8.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:30c5f1751625786c19de751e3130fc345ebcba6a86f6bddd6e1285342f4bbb69", size = 176146, upload-time = "2025-06-10T15:31:50.584Z" }, + { url = "https://files.pythonhosted.org/packages/e3/bb/23a9739291086ca0d3189eac7cd92b4d00e9fdc77d722ab610c35f9a82ba/pyyaml_ft-8.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fa992481155ddda2e303fcc74c79c05eddcdbc907b888d3d9ce3ff3e2adcfb0", size = 746792, upload-time = "2025-06-10T15:31:52.304Z" }, + { url = "https://files.pythonhosted.org/packages/5f/c2/e8825f4ff725b7e560d62a3609e31d735318068e1079539ebfde397ea03e/pyyaml_ft-8.0.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cec6c92b4207004b62dfad1f0be321c9f04725e0f271c16247d8b39c3bf3ea42", size = 786772, upload-time = "2025-06-10T15:31:54.712Z" }, + { url = "https://files.pythonhosted.org/packages/35/be/58a4dcae8854f2fdca9b28d9495298fd5571a50d8430b1c3033ec95d2d0e/pyyaml_ft-8.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06237267dbcab70d4c0e9436d8f719f04a51123f0ca2694c00dd4b68c338e40b", size = 778723, upload-time = "2025-06-10T15:31:56.093Z" }, + { url = "https://files.pythonhosted.org/packages/86/ed/fed0da92b5d5d7340a082e3802d84c6dc9d5fa142954404c41a544c1cb92/pyyaml_ft-8.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8a7f332bc565817644cdb38ffe4739e44c3e18c55793f75dddb87630f03fc254", size = 758478, upload-time = "2025-06-10T15:31:58.314Z" }, + { url = "https://files.pythonhosted.org/packages/f0/69/ac02afe286275980ecb2dcdc0156617389b7e0c0a3fcdedf155c67be2b80/pyyaml_ft-8.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7d10175a746be65f6feb86224df5d6bc5c049ebf52b89a88cf1cd78af5a367a8", size = 799159, upload-time = "2025-06-10T15:31:59.675Z" }, + { url = "https://files.pythonhosted.org/packages/4e/ac/c492a9da2e39abdff4c3094ec54acac9747743f36428281fb186a03fab76/pyyaml_ft-8.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:58e1015098cf8d8aec82f360789c16283b88ca670fe4275ef6c48c5e30b22a96", size = 158779, upload-time = "2025-06-10T15:32:01.029Z" }, + { url = "https://files.pythonhosted.org/packages/5d/9b/41998df3298960d7c67653669f37710fa2d568a5fc933ea24a6df60acaf6/pyyaml_ft-8.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:e64fa5f3e2ceb790d50602b2fd4ec37abbd760a8c778e46354df647e7c5a4ebb", size = 191331, upload-time = "2025-06-10T15:32:02.602Z" }, + { url = "https://files.pythonhosted.org/packages/0f/16/2710c252ee04cbd74d9562ebba709e5a284faeb8ada88fcda548c9191b47/pyyaml_ft-8.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8d445bf6ea16bb93c37b42fdacfb2f94c8e92a79ba9e12768c96ecde867046d1", size = 182879, upload-time = "2025-06-10T15:32:04.466Z" }, + { url = "https://files.pythonhosted.org/packages/9a/40/ae8163519d937fa7bfa457b6f78439cc6831a7c2b170e4f612f7eda71815/pyyaml_ft-8.0.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c56bb46b4fda34cbb92a9446a841da3982cdde6ea13de3fbd80db7eeeab8b49", size = 811277, upload-time = "2025-06-10T15:32:06.214Z" }, + { url = "https://files.pythonhosted.org/packages/f9/66/28d82dbff7f87b96f0eeac79b7d972a96b4980c1e445eb6a857ba91eda00/pyyaml_ft-8.0.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dab0abb46eb1780da486f022dce034b952c8ae40753627b27a626d803926483b", size = 831650, upload-time = "2025-06-10T15:32:08.076Z" }, + { url = "https://files.pythonhosted.org/packages/e8/df/161c4566facac7d75a9e182295c223060373d4116dead9cc53a265de60b9/pyyaml_ft-8.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd48d639cab5ca50ad957b6dd632c7dd3ac02a1abe0e8196a3c24a52f5db3f7a", size = 815755, upload-time = "2025-06-10T15:32:09.435Z" }, + { url = "https://files.pythonhosted.org/packages/05/10/f42c48fa5153204f42eaa945e8d1fd7c10d6296841dcb2447bf7da1be5c4/pyyaml_ft-8.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:052561b89d5b2a8e1289f326d060e794c21fa068aa11255fe71d65baf18a632e", size = 810403, upload-time = "2025-06-10T15:32:11.051Z" }, + { url = "https://files.pythonhosted.org/packages/d5/d2/e369064aa51009eb9245399fd8ad2c562bd0bcd392a00be44b2a824ded7c/pyyaml_ft-8.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3bb4b927929b0cb162fb1605392a321e3333e48ce616cdcfa04a839271373255", size = 835581, upload-time = "2025-06-10T15:32:12.897Z" }, + { url = "https://files.pythonhosted.org/packages/c0/28/26534bed77109632a956977f60d8519049f545abc39215d086e33a61f1f2/pyyaml_ft-8.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:de04cfe9439565e32f178106c51dd6ca61afaa2907d143835d501d84703d3793", size = 171579, upload-time = "2025-06-10T15:32:14.34Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "snowballstemmer" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/75/a7/9810d872919697c9d01295633f5d574fb416d47e535f258272ca1f01f447/snowballstemmer-3.0.1.tar.gz", hash = "sha256:6d5eeeec8e9f84d4d56b847692bacf79bc2c8e90c7f80ca4444ff8b6f2e52895", size = 105575, upload-time = "2025-05-09T16:34:51.843Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/78/3565d011c61f5a43488987ee32b6f3f656e7f107ac2782dd57bdd7d91d9a/snowballstemmer-3.0.1-py3-none-any.whl", hash = "sha256:6cd7b3897da8d6c9ffb968a6781fa6532dce9c3618a4b127d920dab764a19064", size = 103274, upload-time = "2025-05-09T16:34:50.371Z" }, +] + +[[package]] +name = "soupsieve" +version = "2.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/e6/21ccce3262dd4889aa3332e5a119a3491a95e8f60939870a3a035aabac0d/soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f", size = 103472, upload-time = "2025-08-27T15:39:51.78Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/14/a0/bb38d3b76b8cae341dad93a2dd83ab7462e6dbcdd84d43f54ee60a8dc167/soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c", size = 36679, upload-time = "2025-08-27T15:39:50.179Z" }, +] + +[[package]] +name = "sphinx" +version = "8.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "alabaster" }, + { name = "babel" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "docutils" }, + { name = "imagesize" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pygments" }, + { name = "requests" }, + { name = "snowballstemmer" }, + { name = "sphinxcontrib-applehelp" }, + { name = "sphinxcontrib-devhelp" }, + { name = "sphinxcontrib-htmlhelp" }, + { name = "sphinxcontrib-jsmath" }, + { name = "sphinxcontrib-qthelp" }, + { name = "sphinxcontrib-serializinghtml" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611, upload-time = "2024-10-13T20:27:13.93Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125, upload-time = "2024-10-13T20:27:10.448Z" }, +] + +[[package]] +name = "sphinx-autodoc-typehints" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/cd/03e7b917230dc057922130a79ba0240df1693bfd76727ea33fae84b39138/sphinx_autodoc_typehints-2.3.0.tar.gz", hash = "sha256:535c78ed2d6a1bad393ba9f3dfa2602cf424e2631ee207263e07874c38fde084", size = 40709, upload-time = "2024-08-29T16:25:48.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f3/e0a4ce49da4b6f4e4ce84b3c39a0677831884cb9d8a87ccbf1e9e56e53ac/sphinx_autodoc_typehints-2.3.0-py3-none-any.whl", hash = "sha256:3098e2c6d0ba99eacd013eb06861acc9b51c6e595be86ab05c08ee5506ac0c67", size = 19836, upload-time = "2024-08-29T16:25:46.707Z" }, +] + +[[package]] +name = "sphinx-multiversion" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "sphinx" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9a/10/25231164a97a9016bdc73a3530af8f4a6846bdc564af1460af2ff3e59a50/sphinx-multiversion-0.2.4.tar.gz", hash = "sha256:5cd1ca9ecb5eed63cb8d6ce5e9c438ca13af4fa98e7eb6f376be541dd4990bcb", size = 7024, upload-time = "2020-08-12T15:48:20.566Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/51/203bb30b3ce76373237288e92cb71fb66f80ee380473f36bfe8a9d299c5d/sphinx_multiversion-0.2.4-py2.py3-none-any.whl", hash = "sha256:5c38d5ce785a335d8c8d768b46509bd66bfb9c6252b93b700ca8c05317f207d6", size = 9597, upload-time = "2024-10-03T21:45:52.754Z" }, + { url = "https://files.pythonhosted.org/packages/05/ad/4989e6be165805694e93d09bc57425aa1368273b7de4fe3083fe4310803a/sphinx_multiversion-0.2.4-py3-none-any.whl", hash = "sha256:dec29f2a5890ad68157a790112edc0eb63140e70f9df0a363743c6258fbeb478", size = 9642, upload-time = "2020-08-12T15:48:19.649Z" }, +] + +[[package]] +name = "sphinxawesome-theme" +version = "5.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "sphinx", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/45/58/6f3e05f77c881e1356d73fc1d99561efe1795671bd56e7fb47c63a32cc1f/sphinxawesome_theme-5.3.2.tar.gz", hash = "sha256:0629d38b80aefc279b1186c53a7a6faf21e721b5b2ecda14f488ca1074e2631f", size = 364039, upload-time = "2024-11-08T11:51:03.257Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/e9/ca6a7178677bb171c8fd7f9eab726c00182168d38a79d2a58e7678590227/sphinxawesome_theme-5.3.2-py3-none-any.whl", hash = "sha256:5f2bb6b6ab8fa11db1ded5590106eb557351d6a6c36adea7ebd4e0f4bc96945d", size = 375173, upload-time = "2024-11-08T11:51:01.441Z" }, +] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/6e/b837e84a1a704953c62ef8776d45c3e8d759876b4a84fe14eba2859106fe/sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", size = 20053, upload-time = "2024-07-29T01:09:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/85/9ebeae2f76e9e77b952f4b274c27238156eae7979c5421fba91a28f4970d/sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5", size = 119300, upload-time = "2024-07-29T01:08:58.99Z" }, +] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/d2/5beee64d3e4e747f316bae86b55943f51e82bb86ecd325883ef65741e7da/sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", size = 12967, upload-time = "2024-07-29T01:09:23.417Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/7a/987e583882f985fe4d7323774889ec58049171828b58c2217e7f79cdf44e/sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2", size = 82530, upload-time = "2024-07-29T01:09:21.945Z" }, +] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/93/983afd9aa001e5201eab16b5a444ed5b9b0a7a010541e0ddfbbfd0b2470c/sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9", size = 22617, upload-time = "2024-07-29T01:09:37.889Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/7b/18a8c0bcec9182c05a0b3ec2a776bba4ead82750a55ff798e8d406dae604/sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", size = 98705, upload-time = "2024-07-29T01:09:36.407Z" }, +] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/e8/9ed3830aeed71f17c026a07a5097edcf44b692850ef215b161b8ad875729/sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8", size = 5787, upload-time = "2019-01-21T16:10:16.347Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/42/4c8646762ee83602e3fb3fbe774c2fac12f317deb0b5dbeeedd2d3ba4b77/sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", size = 5071, upload-time = "2019-01-21T16:10:14.333Z" }, +] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/68/bc/9104308fc285eb3e0b31b67688235db556cd5b0ef31d96f30e45f2e51cae/sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", size = 17165, upload-time = "2024-07-29T01:09:56.435Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/83/859ecdd180cacc13b1f7e857abf8582a64552ea7a061057a6c716e790fce/sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb", size = 88743, upload-time = "2024-07-29T01:09:54.885Z" }, +] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/44/6716b257b0aa6bfd51a1b31665d1c205fb12cb5ad56de752dfa15657de2f/sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d", size = 16080, upload-time = "2024-07-29T01:10:09.332Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, +] + +[[package]] +name = "stdlibs" +version = "2025.10.28" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/83/ac15c4a3c059725dcb5f5d76270b986808cc12d2d7d417ee540d37609e46/stdlibs-2025.10.28.tar.gz", hash = "sha256:18db81f45f7783ddf86b80771e061782c70e2f4a8642843b3c80b42cd774b24f", size = 20108, upload-time = "2025-10-28T22:14:42.308Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/65/de/5fcc806280950b9535d3892c7f1f3477efc4c2f8624ae6c0b2c3baf9a339/stdlibs-2025.10.28-py3-none-any.whl", hash = "sha256:fc25a3608c417c7fecec06736a2671adaceafc9f20c3f536d967e894a998afea", size = 59232, upload-time = "2025-10-28T22:14:40.799Z" }, +] + +[[package]] +name = "toml" +version = "0.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253, upload-time = "2020-11-01T01:40:22.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" }, +] + +[[package]] +name = "tomli" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/2e/299f62b401438d5fe1624119c723f5d877acc86a4c2492da405626665f12/tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45", size = 153236, upload-time = "2025-10-08T22:01:00.137Z" }, + { url = "https://files.pythonhosted.org/packages/86/7f/d8fffe6a7aefdb61bced88fcb5e280cfd71e08939da5894161bd71bea022/tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba", size = 148084, upload-time = "2025-10-08T22:01:01.63Z" }, + { url = "https://files.pythonhosted.org/packages/47/5c/24935fb6a2ee63e86d80e4d3b58b222dafaf438c416752c8b58537c8b89a/tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf", size = 234832, upload-time = "2025-10-08T22:01:02.543Z" }, + { url = "https://files.pythonhosted.org/packages/89/da/75dfd804fc11e6612846758a23f13271b76d577e299592b4371a4ca4cd09/tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441", size = 242052, upload-time = "2025-10-08T22:01:03.836Z" }, + { url = "https://files.pythonhosted.org/packages/70/8c/f48ac899f7b3ca7eb13af73bacbc93aec37f9c954df3c08ad96991c8c373/tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845", size = 239555, upload-time = "2025-10-08T22:01:04.834Z" }, + { url = "https://files.pythonhosted.org/packages/ba/28/72f8afd73f1d0e7829bfc093f4cb98ce0a40ffc0cc997009ee1ed94ba705/tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c", size = 245128, upload-time = "2025-10-08T22:01:05.84Z" }, + { url = "https://files.pythonhosted.org/packages/b6/eb/a7679c8ac85208706d27436e8d421dfa39d4c914dcf5fa8083a9305f58d9/tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456", size = 96445, upload-time = "2025-10-08T22:01:06.896Z" }, + { url = "https://files.pythonhosted.org/packages/0a/fe/3d3420c4cb1ad9cb462fb52967080575f15898da97e21cb6f1361d505383/tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be", size = 107165, upload-time = "2025-10-08T22:01:08.107Z" }, + { url = "https://files.pythonhosted.org/packages/ff/b7/40f36368fcabc518bb11c8f06379a0fd631985046c038aca08c6d6a43c6e/tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac", size = 154891, upload-time = "2025-10-08T22:01:09.082Z" }, + { url = "https://files.pythonhosted.org/packages/f9/3f/d9dd692199e3b3aab2e4e4dd948abd0f790d9ded8cd10cbaae276a898434/tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22", size = 148796, upload-time = "2025-10-08T22:01:10.266Z" }, + { url = "https://files.pythonhosted.org/packages/60/83/59bff4996c2cf9f9387a0f5a3394629c7efa5ef16142076a23a90f1955fa/tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f", size = 242121, upload-time = "2025-10-08T22:01:11.332Z" }, + { url = "https://files.pythonhosted.org/packages/45/e5/7c5119ff39de8693d6baab6c0b6dcb556d192c165596e9fc231ea1052041/tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52", size = 250070, upload-time = "2025-10-08T22:01:12.498Z" }, + { url = "https://files.pythonhosted.org/packages/45/12/ad5126d3a278f27e6701abde51d342aa78d06e27ce2bb596a01f7709a5a2/tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8", size = 245859, upload-time = "2025-10-08T22:01:13.551Z" }, + { url = "https://files.pythonhosted.org/packages/fb/a1/4d6865da6a71c603cfe6ad0e6556c73c76548557a8d658f9e3b142df245f/tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6", size = 250296, upload-time = "2025-10-08T22:01:14.614Z" }, + { url = "https://files.pythonhosted.org/packages/a0/b7/a7a7042715d55c9ba6e8b196d65d2cb662578b4d8cd17d882d45322b0d78/tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876", size = 97124, upload-time = "2025-10-08T22:01:15.629Z" }, + { url = "https://files.pythonhosted.org/packages/06/1e/f22f100db15a68b520664eb3328fb0ae4e90530887928558112c8d1f4515/tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878", size = 107698, upload-time = "2025-10-08T22:01:16.51Z" }, + { url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" }, + { url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" }, + { url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/d5/f4/0fbd014909748706c01d16824eadb0307115f9562a15cbb012cd9b3512c5/tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf", size = 248586, upload-time = "2025-10-08T22:01:21.164Z" }, + { url = "https://files.pythonhosted.org/packages/30/77/fed85e114bde5e81ecf9bc5da0cc69f2914b38f4708c80ae67d0c10180c5/tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f", size = 244792, upload-time = "2025-10-08T22:01:22.417Z" }, + { url = "https://files.pythonhosted.org/packages/55/92/afed3d497f7c186dc71e6ee6d4fcb0acfa5f7d0a1a2878f8beae379ae0cc/tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05", size = 248909, upload-time = "2025-10-08T22:01:23.859Z" }, + { url = "https://files.pythonhosted.org/packages/f8/84/ef50c51b5a9472e7265ce1ffc7f24cd4023d289e109f669bdb1553f6a7c2/tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606", size = 96946, upload-time = "2025-10-08T22:01:24.893Z" }, + { url = "https://files.pythonhosted.org/packages/b2/b7/718cd1da0884f281f95ccfa3a6cc572d30053cba64603f79d431d3c9b61b/tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999", size = 107705, upload-time = "2025-10-08T22:01:26.153Z" }, + { url = "https://files.pythonhosted.org/packages/19/94/aeafa14a52e16163008060506fcb6aa1949d13548d13752171a755c65611/tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e", size = 154244, upload-time = "2025-10-08T22:01:27.06Z" }, + { url = "https://files.pythonhosted.org/packages/db/e4/1e58409aa78eefa47ccd19779fc6f36787edbe7d4cd330eeeedb33a4515b/tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3", size = 148637, upload-time = "2025-10-08T22:01:28.059Z" }, + { url = "https://files.pythonhosted.org/packages/26/b6/d1eccb62f665e44359226811064596dd6a366ea1f985839c566cd61525ae/tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc", size = 241925, upload-time = "2025-10-08T22:01:29.066Z" }, + { url = "https://files.pythonhosted.org/packages/70/91/7cdab9a03e6d3d2bb11beae108da5bdc1c34bdeb06e21163482544ddcc90/tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0", size = 249045, upload-time = "2025-10-08T22:01:31.98Z" }, + { url = "https://files.pythonhosted.org/packages/15/1b/8c26874ed1f6e4f1fcfeb868db8a794cbe9f227299402db58cfcc858766c/tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879", size = 245835, upload-time = "2025-10-08T22:01:32.989Z" }, + { url = "https://files.pythonhosted.org/packages/fd/42/8e3c6a9a4b1a1360c1a2a39f0b972cef2cc9ebd56025168c4137192a9321/tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005", size = 253109, upload-time = "2025-10-08T22:01:34.052Z" }, + { url = "https://files.pythonhosted.org/packages/22/0c/b4da635000a71b5f80130937eeac12e686eefb376b8dee113b4a582bba42/tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463", size = 97930, upload-time = "2025-10-08T22:01:35.082Z" }, + { url = "https://files.pythonhosted.org/packages/b9/74/cb1abc870a418ae99cd5c9547d6bce30701a954e0e721821df483ef7223c/tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8", size = 107964, upload-time = "2025-10-08T22:01:36.057Z" }, + { url = "https://files.pythonhosted.org/packages/54/78/5c46fff6432a712af9f792944f4fcd7067d8823157949f4e40c56b8b3c83/tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77", size = 163065, upload-time = "2025-10-08T22:01:37.27Z" }, + { url = "https://files.pythonhosted.org/packages/39/67/f85d9bd23182f45eca8939cd2bc7050e1f90c41f4a2ecbbd5963a1d1c486/tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf", size = 159088, upload-time = "2025-10-08T22:01:38.235Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/4b546a0405b9cc0659b399f12b6adb750757baf04250b148d3c5059fc4eb/tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530", size = 268193, upload-time = "2025-10-08T22:01:39.712Z" }, + { url = "https://files.pythonhosted.org/packages/42/4f/2c12a72ae22cf7b59a7fe75b3465b7aba40ea9145d026ba41cb382075b0e/tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b", size = 275488, upload-time = "2025-10-08T22:01:40.773Z" }, + { url = "https://files.pythonhosted.org/packages/92/04/a038d65dbe160c3aa5a624e93ad98111090f6804027d474ba9c37c8ae186/tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67", size = 272669, upload-time = "2025-10-08T22:01:41.824Z" }, + { url = "https://files.pythonhosted.org/packages/be/2f/8b7c60a9d1612a7cbc39ffcca4f21a73bf368a80fc25bccf8253e2563267/tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f", size = 279709, upload-time = "2025-10-08T22:01:43.177Z" }, + { url = "https://files.pythonhosted.org/packages/7e/46/cc36c679f09f27ded940281c38607716c86cf8ba4a518d524e349c8b4874/tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0", size = 107563, upload-time = "2025-10-08T22:01:44.233Z" }, + { url = "https://files.pythonhosted.org/packages/84/ff/426ca8683cf7b753614480484f6437f568fd2fda2edbdf57a2d3d8b27a0b/tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba", size = 119756, upload-time = "2025-10-08T22:01:45.234Z" }, + { url = "https://files.pythonhosted.org/packages/77/b8/0135fadc89e73be292b473cb820b4f5a08197779206b33191e801feeae40/tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", size = 14408, upload-time = "2025-10-08T22:01:46.04Z" }, +] + +[[package]] +name = "tomlkit" +version = "0.13.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/18/0bbf3884e9eaa38819ebe46a7bd25dcd56b67434402b66a58c4b8e552575/tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", size = 185207, upload-time = "2025-06-05T07:13:44.947Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/75/8539d011f6be8e29f339c42e633aae3cb73bffa95dd0f9adec09b9c58e85/tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0", size = 38901, upload-time = "2025-06-05T07:13:43.546Z" }, +] + +[[package]] +name = "trailrunner" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pathspec" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4d/93/630e10bacd897daeb9ff5a408f4e7cb0fc2f243e7e3ef00f9e6cf319b11c/trailrunner-1.4.0.tar.gz", hash = "sha256:3fe61e259e6b2e5192f321c265985b7a0dc18497ced62b2da244f08104978398", size = 15836, upload-time = "2023-03-27T07:54:35.515Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/29/21001afea86bac5016c3940b43de3ce4786b0d8337d4ea79bb903c649ce3/trailrunner-1.4.0-py3-none-any.whl", hash = "sha256:a286d39f2723f28d167347f41cf8f232832648709366e722f55cf5545772a48e", size = 11071, upload-time = "2023-03-27T07:54:32.514Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "ufmt" +version = "2.7.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "black" }, + { name = "click" }, + { name = "libcst" }, + { name = "moreorless" }, + { name = "tomlkit" }, + { name = "trailrunner" }, + { name = "typing-extensions" }, + { name = "usort" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/24/8393cb5e96e640a858ac11c2ac65b28221b09c4a11f83210d2ab9d6108e5/ufmt-2.7.3.tar.gz", hash = "sha256:b661c575bfb95a617d04fa4fe5cde550d21eb848094b3f9c438165459bc04f77", size = 24425, upload-time = "2024-09-21T23:03:42.889Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/35/df52ce427d847396a3574887fef32f11f169834523493010b32b5600867c/ufmt-2.7.3-py3-none-any.whl", hash = "sha256:1a3d2515e3108ba7a68425ebdeb4cbb1fdfbcffbd031dac8f56a1f386a7b396e", size = 28186, upload-time = "2024-09-21T23:03:41.214Z" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + +[[package]] +name = "usort" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "click" }, + { name = "libcst" }, + { name = "moreorless" }, + { name = "stdlibs" }, + { name = "toml" }, + { name = "trailrunner" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/69/8bcbed123ec60ee3e529ec39ebb0bd405cc17bcf101094513ad05c326f6b/usort-1.1.0.tar.gz", hash = "sha256:a24d3a19c80d006b82d47319ec42cca740e4a1efceba35465e1fd49393a28966", size = 82981, upload-time = "2025-11-04T16:13:20.575Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/09/dc06e65fef86845b8471130e862825901b89c08652b4d38862f8d7446e6c/usort-1.1.0-py3-none-any.whl", hash = "sha256:5ae95f0be86d5a8a6fb7c9821e06f33ef4c235d193543926dc4bc0c276879dfe", size = 40751, upload-time = "2025-11-04T16:13:18.556Z" }, +] From 6eb306965954732965b4fd0f57e267801e1f67e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 21:04:58 +0100 Subject: [PATCH 64/90] Add support for env variable JUDGE0_SUPPRESS_PREVIEW_WARNING. (#19) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add support for env variable JUDGE0_SUPPRESS_PREVIEW_WARNING. * Minor change to preview warning suppression logic --------- Co-authored-by: Filip Karlo Došilović --- src/judge0/__init__.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index b2a4dcb4..b74df46e 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -65,6 +65,7 @@ JUDGE0_IMPLICIT_CE_CLIENT = None JUDGE0_IMPLICIT_EXTRA_CE_CLIENT = None +SUPPRESS_PREVIEW_WARNING = os.getenv("JUDGE0_SUPPRESS_PREVIEW_WARNING") logger = logging.getLogger(__name__) @@ -106,11 +107,12 @@ def _get_implicit_client(flavor: Flavor) -> Client: def _get_preview_client(flavor: Flavor) -> Union[Judge0CloudCE, Judge0CloudExtraCE]: - logger.warning( - "You are using a preview version of the client which is not recommended" - " for production.\n" - "For production, please specify your API key in the environment variable." - ) + if SUPPRESS_PREVIEW_WARNING is not None: + logger.warning( + "You are using a preview version of the client which is not recommended" + " for production.\n" + "For production, please specify your API key in the environment variable." + ) if flavor == Flavor.CE: return Judge0CloudCE() From 29ce7f7f6b3e8fa753b092b6967f5d540e6dadfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 21:11:01 +0100 Subject: [PATCH 65/90] Update Python language aliases to latest IDs. (#17) --- src/judge0/data.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/judge0/data.py b/src/judge0/data.py index 5182e7a5..70f04228 100644 --- a/src/judge0/data.py +++ b/src/judge0/data.py @@ -120,9 +120,9 @@ LanguageAlias.PHP: 98, LanguageAlias.PLAIN_TEXT: 43, LanguageAlias.PROLOG: 69, - LanguageAlias.PYTHON: 109, + LanguageAlias.PYTHON: 113, LanguageAlias.PYTHON2: 70, - LanguageAlias.PYTHON3: 109, + LanguageAlias.PYTHON3: 113, LanguageAlias.R: 99, LanguageAlias.RUBY: 72, LanguageAlias.RUST: 108, @@ -155,12 +155,12 @@ LanguageAlias.MPI_PYTHON: 8, LanguageAlias.MULTI_FILE: 89, LanguageAlias.NIM: 9, - LanguageAlias.PYTHON: 32, + LanguageAlias.PYTHON: 33, LanguageAlias.PYTHON2: 26, LanguageAlias.PYTHON2_PYPY: 26, - LanguageAlias.PYTHON3: 32, + LanguageAlias.PYTHON3: 33, LanguageAlias.PYTHON3_PYPY: 28, - LanguageAlias.PYTHON_FOR_ML: 32, + LanguageAlias.PYTHON_FOR_ML: 33, LanguageAlias.VISUAL_BASIC: 20, }, } From 9dc1c8561dd2101a873e90cb93f8ebf9587f104f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 21:13:38 +0100 Subject: [PATCH 66/90] Add Filesystem.find method (#18) --- README.md | 5 +---- src/judge0/filesystem.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 12a47643..08de5602 100644 --- a/README.md +++ b/README.md @@ -347,8 +347,5 @@ submission = Submission( result = judge0.run(submissions=submission) print(result.stdout) - -matches = [f for f in result.post_execution_filesystem if f.name == "my_dir2/my_file2.txt"] -f = matches[0] if matches else None -print(f) +print(result.post_execution_filesystem.find("./my_dir2/my_file2.txt")) ``` diff --git a/src/judge0/filesystem.py b/src/judge0/filesystem.py index 27fae223..b753dfc4 100644 --- a/src/judge0/filesystem.py +++ b/src/judge0/filesystem.py @@ -92,6 +92,27 @@ def encode(self) -> bytes: zip_file.writestr(file.name, file.content) return zip_buffer.getvalue() + def find(self, name: str) -> Optional[File]: + """Find file by name in Filesystem object. + + Parameters + ---------- + name : str + File name to find. + + Returns + ------- + File or None + Found File object or None if not found. + """ + if name.startswith("./"): + name = name[2:] + elif name.startswith("/"): + name = name[1:] + + matches = [f for f in self.files if f.name == name] + return matches[0] if matches else None + def __str__(self) -> str: """Create string representation of Filesystem object.""" return b64encode(self.encode()).decode() From 7265c92ea2a207b6fb684bf84acaf42ff725a16a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 21:25:40 +0100 Subject: [PATCH 67/90] Update version to 0.0.6 alpha release. (#21) --- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8595aac9..9f9c65dd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.1.0.dev0" +version = "0.0.6-alpha.1" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.10" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index b74df46e..f4679740 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -30,7 +30,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.1.0.dev0" +__version__ = "0.0.6-alpha.1" __all__ = [ "ATD", From 40ca59599cca54f60a646e45ec667532c200d9bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 21:37:43 +0100 Subject: [PATCH 68/90] Fix publish CI job. Update alpha version. --- .github/workflows/publish.yml | 2 +- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ab561792..a07edf53 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -30,7 +30,7 @@ jobs: if: github.event.inputs.repository == 'test' env: UV_PUBLISH_TOKEN: ${{ secrets.TEST_PYPI_TOKEN }} - run: uv publish --token $UV_PUBLISH_TOKEN --repository testpypi + run: uv publish --token $UV_PUBLISH_TOKEN --index-url https://test.pypi.org/legacy/ - name: Publish to Regular PyPI if: github.event.inputs.repository == 'pypi' diff --git a/pyproject.toml b/pyproject.toml index 9f9c65dd..a7be43f2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.0.6-alpha.1" +version = "0.0.6-alpha.2" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.10" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index f4679740..de66d975 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -30,7 +30,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.0.6-alpha.1" +__version__ = "0.0.6-alpha.2" __all__ = [ "ATD", From 771c04f22f9519c1e09bcaa5563b8d2607d59a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 21:43:21 +0100 Subject: [PATCH 69/90] Fix publish CI job to use publish url. Update alpha version. --- .github/workflows/publish.yml | 2 +- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a07edf53..416c9c8b 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -30,7 +30,7 @@ jobs: if: github.event.inputs.repository == 'test' env: UV_PUBLISH_TOKEN: ${{ secrets.TEST_PYPI_TOKEN }} - run: uv publish --token $UV_PUBLISH_TOKEN --index-url https://test.pypi.org/legacy/ + run: uv publish --token $UV_PUBLISH_TOKEN --publish-url https://test.pypi.org/legacy/ - name: Publish to Regular PyPI if: github.event.inputs.repository == 'pypi' diff --git a/pyproject.toml b/pyproject.toml index a7be43f2..36f56166 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.0.6-alpha.2" +version = "0.0.6-alpha.3" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.10" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index de66d975..0eb7d7f0 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -30,7 +30,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.0.6-alpha.2" +__version__ = "0.0.6-alpha.3" __all__ = [ "ATD", From 8864ca3202f9f2c30b1d789fe25d08a9dccaa856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 21:50:13 +0100 Subject: [PATCH 70/90] Release v0.0.6 --- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 36f56166..58a84aaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.0.6-alpha.3" +version = "0.0.6" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.10" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 0eb7d7f0..ae62b15f 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -30,7 +30,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.0.6-alpha.3" +__version__ = "0.0.6" __all__ = [ "ATD", From 3e4d088a966ab968cb6f15f85db91df735ffdfc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sun, 9 Nov 2025 21:59:51 +0100 Subject: [PATCH 71/90] Update to new minor release. --- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 58a84aaa..8595aac9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.0.6" +version = "0.1.0.dev0" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.10" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index ae62b15f..b74df46e 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -30,7 +30,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.0.6" +__version__ = "0.1.0.dev0" __all__ = [ "ATD", From fa3c86f074577cbb60757b76d1e5f34a74257c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 10 Nov 2025 00:45:26 +0100 Subject: [PATCH 72/90] Add Custom Judge0 Client example --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index 08de5602..aee1b648 100644 --- a/README.md +++ b/README.md @@ -349,3 +349,25 @@ result = judge0.run(submissions=submission) print(result.stdout) print(result.post_execution_filesystem.find("./my_dir2/my_file2.txt")) ``` + +### Custom Judge0 Client + +This example shows how to use Judge0 Python SDK with your own Judge0 instance. + +```python +import judge0 + +client = judge0.Client(endpoint="http://127.0.0.1:2358", auth_headers=None) + +source_code = """ +#include + +int main() { + printf("hello, world\\n"); + return 0; +} +""" + +result = judge0.run(client=client, source_code=source_code, language=judge0.C) +print(result.stdout) +``` From 3c8efcc23836f800d6f46262d61a714c9ebb9c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 10 Nov 2025 00:58:11 +0100 Subject: [PATCH 73/90] Simplify custom client example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aee1b648..db853f01 100644 --- a/README.md +++ b/README.md @@ -357,7 +357,7 @@ This example shows how to use Judge0 Python SDK with your own Judge0 instance. ```python import judge0 -client = judge0.Client(endpoint="http://127.0.0.1:2358", auth_headers=None) +client = judge0.Client("http://127.0.0.1:2358", None) source_code = """ #include From 0955d857ac2ec5715cfc886cf3b0c61ca2c7b87b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 10 Nov 2025 01:00:34 +0100 Subject: [PATCH 74/90] Don't require auth_headers in judge0.Client --- README.md | 2 +- src/judge0/clients.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index db853f01..c2dc8ae7 100644 --- a/README.md +++ b/README.md @@ -357,7 +357,7 @@ This example shows how to use Judge0 Python SDK with your own Judge0 instance. ```python import judge0 -client = judge0.Client("http://127.0.0.1:2358", None) +client = judge0.Client("http://127.0.0.1:2358") source_code = """ #include diff --git a/src/judge0/clients.py b/src/judge0/clients.py index 49d1ac61..7b50047c 100644 --- a/src/judge0/clients.py +++ b/src/judge0/clients.py @@ -33,7 +33,7 @@ class Client: def __init__( self, endpoint, - auth_headers, + auth_headers=None, *, retry_strategy: Optional[RetryStrategy] = None, ) -> None: From fd2ab3c80e7c6bd48d952ae63c14a817d68b8ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 10 Nov 2025 21:27:04 +0100 Subject: [PATCH 75/90] Fix bug in suppressing preview warning message. --- src/judge0/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index b74df46e..069c96ca 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -65,9 +65,9 @@ JUDGE0_IMPLICIT_CE_CLIENT = None JUDGE0_IMPLICIT_EXTRA_CE_CLIENT = None -SUPPRESS_PREVIEW_WARNING = os.getenv("JUDGE0_SUPPRESS_PREVIEW_WARNING") logger = logging.getLogger(__name__) +suppress_preview_warning = os.getenv("JUDGE0_SUPPRESS_PREVIEW_WARNING") is not None def _get_implicit_client(flavor: Flavor) -> Client: @@ -107,7 +107,7 @@ def _get_implicit_client(flavor: Flavor) -> Client: def _get_preview_client(flavor: Flavor) -> Union[Judge0CloudCE, Judge0CloudExtraCE]: - if SUPPRESS_PREVIEW_WARNING is not None: + if not suppress_preview_warning: logger.warning( "You are using a preview version of the client which is not recommended" " for production.\n" From 61324c3d602ebaed1b8f95b3fc9dc9dfc1196aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 10 Nov 2025 21:30:15 +0100 Subject: [PATCH 76/90] Bump to version 0.0.7 --- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8595aac9..e0f27ab2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.1.0.dev0" +version = "0.0.7" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.10" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 069c96ca..28a89f41 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -30,7 +30,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.1.0.dev0" +__version__ = "0.0.7" __all__ = [ "ATD", From 78ef628afa416f9acfba6bbd5dca23e1d4037c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 10 Nov 2025 21:37:45 +0100 Subject: [PATCH 77/90] Prepare for next release --- pyproject.toml | 2 +- src/judge0/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e0f27ab2..8595aac9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "judge0" -version = "0.0.7" +version = "0.1.0.dev0" description = "The official Python SDK for Judge0." readme = "README.md" requires-python = ">=3.10" diff --git a/src/judge0/__init__.py b/src/judge0/__init__.py index 28a89f41..069c96ca 100644 --- a/src/judge0/__init__.py +++ b/src/judge0/__init__.py @@ -30,7 +30,7 @@ from .retry import MaxRetries, MaxWaitTime, RegularPeriodRetry from .submission import Submission -__version__ = "0.0.7" +__version__ = "0.1.0.dev0" __all__ = [ "ATD", From fcef3785ee00bd5ebc4f436d1996065a88a0cf5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 10 Nov 2025 21:57:20 +0100 Subject: [PATCH 78/90] Update simple example with Ollama --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c2dc8ae7..6976a0b2 100644 --- a/README.md +++ b/README.md @@ -246,8 +246,12 @@ client = Client( headers={"Authorization": "Bearer " + os.environ.get("OLLAMA_API_KEY")}, ) -system = "You are a helpful assistant that can execute Python code. Only respond with the code to be executed and nothing else. Strip backticks in code blocks." -prompt = "Calculate how many r's are in the word 'strawberry'." +system = """ +You are a helpful assistant that can execute code written in the C programming language. +Only respond with the code written in the C programming language that needs to be executed and nothing else. +Strip the backticks in code blocks. +""" +prompt = "How many r's are in the word 'strawberry'." response = client.chat( model="gpt-oss:120b-cloud", @@ -258,10 +262,10 @@ response = client.chat( ) code = response["message"]["content"] -print(f"Generated code:\n{code}") +print(f"CODE GENERATED BY THE MODEL:\n{code}\n") -result = judge0.run(source_code=code, language=judge0.PYTHON) -print(f"Execution result:\n{result.stdout}") +result = judge0.run(source_code=code, language=judge0.C) +print(f"CODE EXECUTION RESULT:\n{result.stdout}") ``` #### Tool Calling (a.k.a. Function Calling) with Ollama From bc2c693299081811858fe81dc07fe0e0637c881a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 10 Nov 2025 22:58:16 +0100 Subject: [PATCH 79/90] Update Ollama examples --- README.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 6976a0b2..d88e865b 100644 --- a/README.md +++ b/README.md @@ -251,7 +251,7 @@ You are a helpful assistant that can execute code written in the C programming l Only respond with the code written in the C programming language that needs to be executed and nothing else. Strip the backticks in code blocks. """ -prompt = "How many r's are in the word 'strawberry'." +prompt = "How many r's are in the word 'strawberry'?" response = client.chat( model="gpt-oss:120b-cloud", @@ -284,20 +284,20 @@ client = Client( model="qwen3-coder:480b-cloud" messages=[ - {"role": "user", "content": "Calculate how many r's are in the word 'strawberry'."}, + {"role": "user", "content": "How many r's are in the word 'strawberry'?"}, ] tools = [{ "type": "function", "function": { - "name": "execute_python", - "description": "Execute Python code and return result", + "name": "execute_c", + "description": "Execute the C programming language code.", "parameters": { "type": "object", "properties": { "code": { "type": "string", - "description": "The Python code to execute" + "description": "The code written in the C programming language." } }, "required": ["code"] @@ -312,16 +312,21 @@ messages.append(response_message) if response_message.tool_calls: for tool_call in response_message.tool_calls: - if tool_call.function.name == "execute_python": - result = judge0.run(source_code=tool_call.function.arguments["code"], language=judge0.PYTHON) + if tool_call.function.name == "execute_c": + code = tool_call.function.arguments["code"] + print(f"CODE GENERATED BY THE MODEL:\n{code}\n") + + result = judge0.run(source_code=code, language=judge0.C) + print(f"CODE EXECUTION RESULT:\n{result.stdout}\n") + messages.append({ "role": "tool", - "tool_name": "execute_python", + "tool_name": "execute_c", "content": result.stdout, }) final_response = client.chat(model=model, messages=messages) -print(final_response["message"]["content"]) +print(f'FINAL RESPONSE BY THE MODEL:\n{final_response["message"]["content"]}') ``` ### Filesystem From 319a2a883aa63cf6dc99d1d98c9517c2560c0034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 10 Nov 2025 23:16:54 +0100 Subject: [PATCH 80/90] Add comments for filesystem example --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index d88e865b..3f4f937f 100644 --- a/README.md +++ b/README.md @@ -331,6 +331,10 @@ print(f'FINAL RESPONSE BY THE MODEL:\n{final_response["message"]["content"]}') ### Filesystem +This example shows how to use Judge0 Python SDK to: +1. Create a submission with additional files in the filesystem which will be available during the execution. +2. Read the files after the execution which were created during the execution. + ```python import judge0 from judge0 import Filesystem, File, Submission @@ -355,6 +359,7 @@ submission = Submission( ) result = judge0.run(submissions=submission) + print(result.stdout) print(result.post_execution_filesystem.find("./my_dir2/my_file2.txt")) ``` From 1a1fd19d3c36c270488bbae31d5cd569b28065a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 16 Nov 2025 22:41:00 +0100 Subject: [PATCH 81/90] Add Multi-Agent System For Iterative Code Generation, Execution, And Debugging --- README.md | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/README.md b/README.md index 3f4f937f..9cccc218 100644 --- a/README.md +++ b/README.md @@ -236,6 +236,7 @@ print(client.get_languages()) #### Simple Example with Ollama ```python +# pip install judge0 ollama import os from ollama import Client import judge0 @@ -271,6 +272,7 @@ print(f"CODE EXECUTION RESULT:\n{result.stdout}") #### Tool Calling (a.k.a. Function Calling) with Ollama ```python +# pip install judge0 ollama import os from ollama import Client import judge0 @@ -329,6 +331,87 @@ final_response = client.chat(model=model, messages=messages) print(f'FINAL RESPONSE BY THE MODEL:\n{final_response["message"]["content"]}') ``` +#### Multi-Agent System For Iterative Code Generation, Execution, And Debugging + +```python +# pip install judge0 ag2[openai] +from typing import Annotated, Optional + +from autogen import ConversableAgent, LLMConfig, register_function +from autogen.tools import Tool +from pydantic import BaseModel, Field +import judge0 + + +class PythonCodeExecutionTool(Tool): + def __init__(self) -> None: + class CodeExecutionRequest(BaseModel): + code: Annotated[str, Field(description="Python code to execute")] + + async def execute_python_code( + code_execution_request: CodeExecutionRequest, + ) -> Optional[str]: + result = judge0.run( + source_code=code_execution_request.code, + language=judge0.PYTHON, + redirect_stderr_to_stdout=True, + ) + return result.stdout + + super().__init__( + name="python_execute_code", + description="Executes Python code and returns the result.", + func_or_tool=execute_python_code, + ) + + +python_executor = PythonCodeExecutionTool() + +llm_config = LLMConfig( + { + "api_type": "openai", + "base_url": "http://localhost:11434/v1", + "api_key": "ollama", + "model": "qwen3-coder:30b", + } +) + +code_runner = ConversableAgent( + name="code_runner", + system_message="You are a code executor agent, when you don't execute code write the message 'TERMINATE' by itself.", + human_input_mode="NEVER", + llm_config=llm_config, +) + +question_agent = ConversableAgent( + name="question_agent", + system_message=( + "You are a developer AI agent. " + "Send all your code suggestions to the python_executor tool where it will be executed and result returned to you. " + "Keep refining the code until it works." + ), + llm_config=llm_config, +) + +register_function( + python_executor, + caller=question_agent, + executor=code_runner, + description="Run Python code", +) + +result = code_runner.initiate_chat( + recipient=question_agent, + message=( + "Write Python code to print the current Python version followed by the numbers 1 to 11. " + "Make a syntax error in the first version and fix it in the second version." + ), + max_turns=5, +) + +print(f"Result: {result.summary}") +``` + ### Filesystem This example shows how to use Judge0 Python SDK to: From a0f21c4737836e58aa0c49092a9b0b986939b1cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Sun, 16 Nov 2025 22:49:40 +0100 Subject: [PATCH 82/90] Update example to work with Ollama Cloud --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9cccc218..27d674dc 100644 --- a/README.md +++ b/README.md @@ -238,10 +238,11 @@ print(client.get_languages()) ```python # pip install judge0 ollama import os + from ollama import Client import judge0 -# Get your Ollama Cloud API key from https://ollama.com. +# Get your free tier Ollama Cloud API key at https://ollama.com. client = Client( host="https://ollama.com", headers={"Authorization": "Bearer " + os.environ.get("OLLAMA_API_KEY")}, @@ -274,10 +275,11 @@ print(f"CODE EXECUTION RESULT:\n{result.stdout}") ```python # pip install judge0 ollama import os + from ollama import Client import judge0 -# Get your Ollama Cloud API key from https://ollama.com. +# Get your free tier Ollama Cloud API key at https://ollama.com. client = Client( host="https://ollama.com", headers={"Authorization": "Bearer " + os.environ.get("OLLAMA_API_KEY")}, @@ -335,6 +337,7 @@ print(f'FINAL RESPONSE BY THE MODEL:\n{final_response["message"]["content"]}') ```python # pip install judge0 ag2[openai] +import os from typing import Annotated, Optional from autogen import ConversableAgent, LLMConfig, register_function @@ -367,12 +370,13 @@ class PythonCodeExecutionTool(Tool): python_executor = PythonCodeExecutionTool() +# Get your free tier Ollama Cloud API key at https://ollama.com. llm_config = LLMConfig( { "api_type": "openai", - "base_url": "http://localhost:11434/v1", - "api_key": "ollama", - "model": "qwen3-coder:30b", + "base_url": "https://ollama.com/v1", + "api_key": os.environ.get("OLLAMA_API_KEY"), + "model": "qwen3-coder:480b-cloud", } ) From 177ff092a5aebe20f536c61bb7aefa6e33e94e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 17 Nov 2025 00:14:53 +0100 Subject: [PATCH 83/90] Add Kaggle Dataset Visualization With LLM-Generated Code Using Ollama And Judge0 --- README.md | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 27d674dc..7d15228e 100644 --- a/README.md +++ b/README.md @@ -233,7 +233,7 @@ print(client.get_languages()) ### Running LLM-Generated Code -#### Simple Example with Ollama +#### Simple Example With Ollama ```python # pip install judge0 ollama @@ -270,7 +270,7 @@ result = judge0.run(source_code=code, language=judge0.C) print(f"CODE EXECUTION RESULT:\n{result.stdout}") ``` -#### Tool Calling (a.k.a. Function Calling) with Ollama +#### Tool Calling (a.k.a. Function Calling) With Ollama ```python # pip install judge0 ollama @@ -416,6 +416,108 @@ result = code_runner.initiate_chat( print(f"Result: {result.summary}") ``` +#### Kaggle Dataset Visualization With LLM-Generated Code Using Ollama And Judge0 + +```python +# pip install judge0 ollama requests +import os +import zipfile + +import judge0 +import requests +from judge0 import File, Filesystem +from ollama import Client + +# Step 1: Download the dataset from Kaggle. +dataset_url = "https://www.kaggle.com/api/v1/datasets/download/gregorut/videogamesales" +dataset_zip_path = "vgsales.zip" +dataset_csv_path = "vgsales.csv" # P.S.: We know the CSV file name inside the zip. + +if not os.path.exists(dataset_csv_path): # Download only if not already downloaded. + with requests.get(dataset_url) as response: + with open(dataset_zip_path, "wb") as f: + f.write(response.content) + with zipfile.ZipFile(dataset_zip_path, "r") as f: + f.extractall(".") + +# Step 2: Prepare the submission for Judge0. +with open(dataset_csv_path, "r") as f: + submission = judge0.Submission( + language=judge0.PYTHON_FOR_ML, + additional_files=Filesystem( + content=[ + File(name=dataset_csv_path, content=f.read()), + ] + ), + ) + +# Step 3: Initialize Ollama Client. Get your free tier Ollama Cloud API key at https://ollama.com. +client = Client( + host="https://ollama.com", + headers={"Authorization": "Bearer " + os.environ.get("OLLAMA_API_KEY")}, +) + +# Step 4: Prepare the prompt, messages, tools, and choose the model. +prompt = f""" +I have a CSV that contains a list of video games with sales greater than 100,000 copies. It's saved in the file {dataset_csv_path}. +These are the columns: +- 'Rank': Ranking of overall sales +- 'Name': The games name +- 'Platform': Platform of the games release (i.e. PC,PS4, etc.) +- 'Year': Year of the game's release +- 'Genre': Genre of the game +- 'Publisher': Publisher of the game +- 'NA_Sales': Sales in North America (in millions) +- 'EU_Sales': Sales in Europe (in millions) +- 'JP_Sales': Sales in Japan (in millions) +- 'Other_Sales': Sales in the rest of the world (in millions) +- 'Global_Sales': Total worldwide sales. + +I want to better understand how the sales are distributed across different genres over the years. +Write Python code that analyzes the dataset based on my request, produces right chart and saves it as an image file. +""" +messages = [{"role": "user", "content": prompt}] +tools = [ + { + "type": "function", + "function": { + "name": "execute_python", + "description": "Execute the Python programming language code.", + "parameters": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "The code written in the Python programming language.", + } + }, + "required": ["code"], + }, + }, + } +] +model = "qwen3-coder:480b-cloud" + +# Step 5: Start the interaction with the model. +response = client.chat(model=model, messages=messages, tools=tools) +response_message = response["message"] + +if response_message.tool_calls: + for tool_call in response_message.tool_calls: + if tool_call.function.name == "execute_python": + code = tool_call.function.arguments["code"] + print(f"CODE GENERATED BY THE MODEL:\n{code}\n") + + submission.source_code = code + result = judge0.run(submissions=submission) + + for f in result.post_execution_filesystem: + if f.name.endswith((".png", ".jpg", ".jpeg")): + with open(f.name, "wb") as img_file: + img_file.write(f.content) + print(f"Generated image saved as: {f.name}\n") +``` + ### Filesystem This example shows how to use Judge0 Python SDK to: From c4016fb07c1555eb623f8b42f019e9bc38ea8e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 17 Nov 2025 01:57:38 +0100 Subject: [PATCH 84/90] Add Minimal Example Using smolagents With Ollama And Judge0 --- README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/README.md b/README.md index 7d15228e..1f811139 100644 --- a/README.md +++ b/README.md @@ -518,6 +518,49 @@ if response_message.tool_calls: print(f"Generated image saved as: {f.name}\n") ``` +#### Minimal Example Using `smolagents` With Ollama And Judge0 + +```python +# pip install judge0 smolagents[openai] +import os +from typing import Any + +import judge0 +from smolagents import CodeAgent, OpenAIServerModel, Tool +from smolagents.local_python_executor import CodeOutput, PythonExecutor + + +class Judge0PythonExecutor(PythonExecutor): + def send_tools(self, tools: dict[str, Tool]) -> None: + pass + + def send_variables(self, variables: dict[str, Any]) -> None: + pass + + def __call__(self, code_action: str) -> CodeOutput: + source_code = f"final_answer = lambda x : print(x)\n{code_action}" + result = judge0.run(source_code=source_code, language=judge0.PYTHON_FOR_ML) + return CodeOutput( + output=result.stdout, + logs=result.stderr or "", + is_final_answer=result.exit_code == 0, + ) + + +# Get your free tier Ollama Cloud API key at https://ollama.com. +model = OpenAIServerModel( + model_id="gpt-oss:120b-cloud", + api_base="https://ollama.com/v1", + api_key=os.environ["OLLAMA_API_KEY"], +) + +agent = CodeAgent(tools=[], model=model) +agent.python_executor = Judge0PythonExecutor() + +result = agent.run("How many r's are in the word 'strawberry'?") +print(result) +``` + ### Filesystem This example shows how to use Judge0 Python SDK to: From 0eea3ac7a1264cf47d777d6e6459ab33492fc2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herman=20Zvonimir=20Do=C5=A1ilovi=C4=87?= Date: Mon, 17 Nov 2025 02:07:26 +0100 Subject: [PATCH 85/90] Add example Generating And Saving An Image File --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index 1f811139..71f241d5 100644 --- a/README.md +++ b/README.md @@ -568,6 +568,7 @@ This example shows how to use Judge0 Python SDK to: 2. Read the files after the execution which were created during the execution. ```python +# pip install judge0 import judge0 from judge0 import Filesystem, File, Submission @@ -601,6 +602,7 @@ print(result.post_execution_filesystem.find("./my_dir2/my_file2.txt")) This example shows how to use Judge0 Python SDK with your own Judge0 instance. ```python +# pip install judge0 import judge0 client = judge0.Client("http://127.0.0.1:2358") @@ -617,3 +619,24 @@ int main() { result = judge0.run(client=client, source_code=source_code, language=judge0.C) print(result.stdout) ``` + +### Generating And Saving An Image File + +```python +# pip install judge0 +import judge0 + +source_code = """ +import matplotlib.pyplot as plt + +plt.plot([x for x in range(10)], [x**2 for x in range(10)]) +plt.savefig("chart.png") +""" + +result = judge0.run(source_code=source_code, language=judge0.PYTHON_FOR_ML) + +image = result.post_execution_filesystem.find("chart.png") +with open(image.name, "wb") as f: + f.write(image.content) +print(f"Generated image saved as: {image.name}\n") +``` From 0847529f78f72ed77a6e39866f4bc638e2ef5198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Fri, 28 Nov 2025 18:25:01 +0100 Subject: [PATCH 86/90] Filter only release tag versions (without prereleases). (#28) --- .github/workflows/docs.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 182c3f95..de80d4e6 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,8 +17,12 @@ jobs: fetch-depth: 0 # Fetch the full history ref: ${{ github.ref }} # Check out the current branch or tag - - name: Fetch tags only - run: git fetch --tags --no-recurse-submodules + - name: Fetch version tags only (vx.y.z) + run: | + TAGS=$(git ls-remote --tags origin 'v*[0-9].[0-9].[0-9]' | sed 's/.*refs\/tags\///' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$') + for tag in $TAGS; do + git fetch origin "refs/tags/$tag:refs/tags/$tag" --no-recurse-submodules + done - name: Set up Python uses: actions/setup-python@v4 @@ -33,12 +37,12 @@ jobs: - name: Build documentation run: uv run sphinx-multiversion docs/source docs/build/html --keep-going --no-color - - name: Get the latest tag + - name: Get the latest stable tag run: | # Fetch all tags git fetch --tags - # Get the latest tag - latest_tag=$(git tag --sort=-creatordate | head -n 1) + # Get the latest stable tag + latest_tag=$(git tag --sort=-creatordate | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1) echo "LATEST_RELEASE=$latest_tag" >> $GITHUB_ENV - name: Generate index.html for judge0.github.io/judge0-python. From 38b13f961cbf3389d20a17aa21c336430b7f625c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Fri, 28 Nov 2025 18:43:32 +0100 Subject: [PATCH 87/90] Add tag filtering for sphinx-multiversion config as well. --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f4c02c87..4ab5eccb 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -102,7 +102,7 @@ napoleon_google_docstring = False # Whitelist pattern for tags (set to None to ignore all tags) -smv_tag_whitelist = r"^.*$" +smv_tag_whitelist = r"^v[0-9]+\.[0-9]+\.[0-9]+$" # Whitelist pattern for branches (set to None to ignore all branches) smv_branch_whitelist = r"^master$" # Whitelist pattern for remotes (set to None to use local branches only) From 48df1b960a36c4c1f07908fcbae20f4d0eb17bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Mon, 1 Dec 2025 11:22:17 +0100 Subject: [PATCH 88/90] Add docs for client resolution. (#30) --- docs/source/in_depth/client_resolution.rst | 53 +++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/docs/source/in_depth/client_resolution.rst b/docs/source/in_depth/client_resolution.rst index dfdd5321..808a705b 100644 --- a/docs/source/in_depth/client_resolution.rst +++ b/docs/source/in_depth/client_resolution.rst @@ -1,4 +1,55 @@ Client Resolution ================= -TODO: Describe the approach to client resolution. See `_get_implicit_client`. \ No newline at end of file +The Judge0 Python SDK supports two main client flavors: Community Edition (CE) and Extra Community Edition (Extra CE), which correspond to the Judge0 Cloud editions. When you use functions like ``judge0.run`` or ``judge0.execute`` without explicitly providing a client instance, the SDK automatically resolves and initializes a client for you. This process, handled by the internal ``_get_implicit_client`` function, follows a specific order of priority. + +The SDK determines which client to use based on environment variables. Here's the resolution order: + +1. **Custom Client (Self-Hosted)** + +The SDK first checks for a self-hosted Judge0 instance. If you have your own deployment of Judge0, you can configure the SDK to use it by setting the following environment variables: + +* For CE flavor: + * ``JUDGE0_CE_ENDPOINT``: The URL of your self-hosted Judge0 CE instance. + * ``JUDGE0_CE_AUTH_HEADERS``: A JSON string representing the authentication headers. +* For Extra CE flavor: + * ``JUDGE0_EXTRA_CE_ENDPOINT``: The URL of your self-hosted Judge0 Extra CE instance. + * ``JUDGE0_EXTRA_CE_AUTH_HEADERS``: A JSON string representing the authentication headers. + +If these variables are set, the SDK will initialize a ``Client`` instance with your custom endpoint and headers. + +2. **Hub Clients** + +If a custom client is not configured, the SDK will try to find API keys for one of the supported hub clients. The SDK checks for the following environment variables in order: + +* **Judge0 Cloud**: + * ``JUDGE0_CLOUD_CE_AUTH_HEADERS`` for ``Judge0CloudCE`` + * ``JUDGE0_CLOUD_EXTRA_CE_AUTH_HEADERS` for ``Judge0CloudExtraCE`` + +* **RapidAPI**: + * ``JUDGE0_RAPID_API_KEY`` for both ``RapidJudge0CE`` and ``RapidJudge0ExtraCE`` + +* **AllThingsDev**: + * ``JUDGE0_ATD_API_KEY`` for both ``ATDJudge0CE`` and ``ATDJudge0ExtraCE`` + +The first API key found determines the client that will be used. + +3. **Preview Client** + +If none of the above environment variables are set, the SDK falls back to using a **preview client**. This is an unauthenticated client that connects to the official Judge0 Cloud service. It initializes ``Judge0CloudCE()`` and ``Judge0CloudExtraCE()`` for the CE and Extra CE flavors, respectively. + +When the preview client is used, a warning message is logged to the console, as this option is not recommended for production use. To suppress this warning, you can set the ``JUDGE0_SUPPRESS_PREVIEW_WARNING`` environment variable. + +Example Resolution Flow +----------------------- + +When you call a function like ``judge0.run(..., flavor=judge0.CE)``, the SDK will: + +1. Check if ``JUDGE0_IMPLICIT_CE_CLIENT`` is already initialized. If so, use it. +2. Check for ``JUDGE0_CE_ENDPOINT`` and ``JUDGE0_CE_AUTH_HEADERS`` to configure a ``Client``. +3. Check for ``JUDGE0_CLOUD_CE_AUTH_HEADERS`` to configure a ``Judge0CloudCE`` client. +4. Check for ``JUDGE0_RAPID_API_KEY`` to configure a ``RapidJudge0CE`` client. +5. Check for ``JUDGE0_ATD_API_KEY`` to configure an ``ATDJudge0CE`` client. +6. If none of the above are found, initialize a preview ``Judge0CloudCE`` client and log a warning. + +This implicit client resolution makes it easy to get started with the Judge0 Python SDK while providing the flexibility to configure it for different environments and services. From afb0f24630c361dbc78c8b3bd9f9b085db496086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sat, 13 Dec 2025 11:32:38 +0100 Subject: [PATCH 89/90] Add step to generate CNAME file for documentation --- .github/workflows/docs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index de80d4e6..f368c870 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -56,6 +56,9 @@ jobs: env: latest_release: ${{ env.LATEST_RELEASE }} + - name: Generate CNAME file + run: echo "python.docs.judge0.com" > docs/build/html/CNAME + - name: Upload artifacts uses: actions/upload-artifact@v4 with: From 4365a1b31100234b388b120d0a77b5497a803127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Karlo=20Do=C5=A1ilovi=C4=87?= Date: Sat, 20 Dec 2025 16:20:54 +0100 Subject: [PATCH 90/90] Add new docs dependency: sphinx-autobuild. Add livehtml cmd in makefile. Update documentation with new contribution instructions for building documentation. (#31) - Add new docs dependency: sphinx-autobuild - Add livehtml cmd to makefile - Update documentation with new contribution instructions for building documentation. --- docs/Makefile | 3 + docs/source/conf.py | 2 +- .../contributors_guide/contributing.rst | 17 +- pyproject.toml | 1 + uv.lock | 260 ++++++++++++++++++ 5 files changed, 273 insertions(+), 10 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index faf5089f..a6abb3fb 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: + uv run sphinx-autobuild -b dirhtml --pre-build "rm -rf $(BUILDDIR)" "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 4ab5eccb..4968baf8 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -69,7 +69,7 @@ }, "awesome_external_links": True, "main_nav_links": { - "Home": "https://judge0.github.io/judge0-python/", + "Home": "index", "Judge0": "https://judge0.com/", }, } diff --git a/docs/source/contributors_guide/contributing.rst b/docs/source/contributors_guide/contributing.rst index 7c4e240d..a6697d4f 100644 --- a/docs/source/contributors_guide/contributing.rst +++ b/docs/source/contributors_guide/contributing.rst @@ -39,22 +39,21 @@ Preparing the development setup Building documentation ---------------------- -Documentation is built using Sphinx. To build the documentation, run the +Documentation is built using Sphinx. While working on a documentation, you can run .. code-block:: console $ cd docs - $ make html + $ make livehtml -You should inspect the changes in the documentation by opening the -``docs/build/html/index.html`` file in your browser. +The ``make livehtml`` command will start a live HTTP server, watch the `docs` directory for changes, +and rebuild the documentation on every change, enabling you to continuously work on the documentation, +without having to manually rebuild it after every change. -.. note:: - If you are having trouble with the documentation and are seeing unexpected - output, delete the ``docs/build`` directory and rerun the ``make html`` command. +You can inspect the changes by opening the ``http://localhost:8000`` in your browser. -You'll see a different output since the documentation is build with -`sphinx-multiversion `_ extension. +.. You'll see a different output since the documentation is build with +.. `sphinx-multiversion `_ extension. Testing ------- diff --git a/pyproject.toml b/pyproject.toml index 8595aac9..c1bb46e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,6 +48,7 @@ docs = [ "sphinxawesome-theme==5.3.2", "sphinx-autodoc-typehints==2.3.0", "sphinx-multiversion==0.2.4", + "sphinx-autobuild>=2024.10.3", ] dev = [{ include-group = "test" }, { include-group = "docs" }] diff --git a/uv.lock b/uv.lock index 8d05bf15..c1d266eb 100644 --- a/uv.lock +++ b/uv.lock @@ -26,6 +26,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, ] +[[package]] +name = "anyio" +version = "4.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/16/ce/8a777047513153587e5434fd752e89334ac33e379aa3497db860eeb60377/anyio-4.12.0.tar.gz", hash = "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0", size = 228266, upload-time = "2025-11-28T23:37:38.911Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/9c/36c5c37947ebfb8c7f22e0eb6e4d188ee2d53aa3880f3f2744fb894f0cb1/anyio-4.12.0-py3-none-any.whl", hash = "sha256:dad2376a628f98eeca4881fc56cd06affd18f659b17a747d3ff0307ced94b1bb", size = 113362, upload-time = "2025-11-28T23:36:57.897Z" }, +] + [[package]] name = "attrs" version = "25.4.0" @@ -363,6 +377,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/7d/76a278fa43250441ed9300c344f889c7fb1817080c8fb8996b840bf421c2/flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75", size = 4994, upload-time = "2023-01-25T14:27:12.32Z" }, ] +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + [[package]] name = "idna" version = "3.11" @@ -418,6 +441,8 @@ dev = [ { name = "pytest-cov" }, { name = "python-dotenv" }, { name = "sphinx" }, + { name = "sphinx-autobuild", version = "2024.10.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "sphinx-autobuild", version = "2025.8.25", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx-autodoc-typehints" }, { name = "sphinx-multiversion" }, { name = "sphinxawesome-theme" }, @@ -425,6 +450,8 @@ dev = [ ] docs = [ { name = "sphinx" }, + { name = "sphinx-autobuild", version = "2024.10.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "sphinx-autobuild", version = "2025.8.25", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "sphinx-autodoc-typehints" }, { name = "sphinx-multiversion" }, { name = "sphinxawesome-theme" }, @@ -450,6 +477,7 @@ dev = [ { name = "pytest-cov", specifier = "==6.0.0" }, { name = "python-dotenv", specifier = "==1.0.1" }, { name = "sphinx", specifier = "==8.1.3" }, + { name = "sphinx-autobuild", specifier = ">=2024.10.3" }, { name = "sphinx-autodoc-typehints", specifier = "==2.3.0" }, { name = "sphinx-multiversion", specifier = "==0.2.4" }, { name = "sphinxawesome-theme", specifier = "==5.3.2" }, @@ -457,6 +485,7 @@ dev = [ ] docs = [ { name = "sphinx", specifier = "==8.1.3" }, + { name = "sphinx-autobuild", specifier = ">=2024.10.3" }, { name = "sphinx-autodoc-typehints", specifier = "==2.3.0" }, { name = "sphinx-multiversion", specifier = "==0.2.4" }, { name = "sphinxawesome-theme", specifier = "==5.3.2" }, @@ -1057,6 +1086,48 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125, upload-time = "2024-10-13T20:27:10.448Z" }, ] +[[package]] +name = "sphinx-autobuild" +version = "2024.10.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.11'" }, + { name = "sphinx", marker = "python_full_version < '3.11'" }, + { name = "starlette", marker = "python_full_version < '3.11'" }, + { name = "uvicorn", marker = "python_full_version < '3.11'" }, + { name = "watchfiles", marker = "python_full_version < '3.11'" }, + { name = "websockets", marker = "python_full_version < '3.11'" }, +] +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-autobuild" +version = "2025.8.25" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.13.*'", + "python_full_version >= '3.11' and python_full_version < '3.13'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.11'" }, + { name = "sphinx", marker = "python_full_version >= '3.11'" }, + { name = "starlette", marker = "python_full_version >= '3.11'" }, + { name = "uvicorn", marker = "python_full_version >= '3.11'" }, + { name = "watchfiles", marker = "python_full_version >= '3.11'" }, + { name = "websockets", marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e0/3c/a59a3a453d4133777f7ed2e83c80b7dc817d43c74b74298ca0af869662ad/sphinx_autobuild-2025.8.25.tar.gz", hash = "sha256:9cf5aab32853c8c31af572e4fecdc09c997e2b8be5a07daf2a389e270e85b213", size = 15200, upload-time = "2025-08-25T18:44:55.436Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/20/56411b52f917696995f5ad27d2ea7e9492c84a043c5b49a3a3173573cd93/sphinx_autobuild-2025.8.25-py3-none-any.whl", hash = "sha256:b750ac7d5a18603e4665294323fd20f6dcc0a984117026d1986704fa68f0379a", size = 12535, upload-time = "2025-08-25T18:44:54.164Z" }, +] + [[package]] name = "sphinx-autodoc-typehints" version = "2.3.0" @@ -1149,6 +1220,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, ] +[[package]] +name = "starlette" +version = "0.50.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ba/b8/73a0e6a6e079a9d9cfa64113d771e421640b6f679a52eeb9b32f72d871a1/starlette-0.50.0.tar.gz", hash = "sha256:a2a17b22203254bcbc2e1f926d2d55f3f9497f769416b3190768befe598fa3ca", size = 2646985, upload-time = "2025-11-01T15:25:27.516Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/52/1064f510b141bd54025f9b55105e26d1fa970b9be67ad766380a3c9b74b0/starlette-0.50.0-py3-none-any.whl", hash = "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca", size = 74033, upload-time = "2025-11-01T15:25:25.461Z" }, +] + [[package]] name = "stdlibs" version = "2025.10.28" @@ -1303,3 +1387,179 @@ sdist = { url = "https://files.pythonhosted.org/packages/df/69/8bcbed123ec60ee3e wheels = [ { url = "https://files.pythonhosted.org/packages/dc/09/dc06e65fef86845b8471130e862825901b89c08652b4d38862f8d7446e6c/usort-1.1.0-py3-none-any.whl", hash = "sha256:5ae95f0be86d5a8a6fb7c9821e06f33ef4c235d193543926dc4bc0c276879dfe", size = 40751, upload-time = "2025-11-04T16:13:18.556Z" }, ] + +[[package]] +name = "uvicorn" +version = "0.38.0" +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/cb/ce/f06b84e2697fef4688ca63bdb2fdf113ca0a3be33f94488f2cadb690b0cf/uvicorn-0.38.0.tar.gz", hash = "sha256:fd97093bdd120a2609fc0d3afe931d4d4ad688b6e75f0f929fde1bc36fe0e91d", size = 80605, upload-time = "2025-10-18T13:46:44.63Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/d9/d88e73ca598f4f6ff671fb5fde8a32925c2e08a637303a1d12883c7305fa/uvicorn-0.38.0-py3-none-any.whl", hash = "sha256:48c0afd214ceb59340075b4a052ea1ee91c16fbc2a9b1469cca0e54566977b02", size = 68109, upload-time = "2025-10-18T13:46:42.958Z" }, +] + +[[package]] +name = "watchfiles" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/c9/8869df9b2a2d6c59d79220a4db37679e74f807c559ffe5265e08b227a210/watchfiles-1.1.1.tar.gz", hash = "sha256:a173cb5c16c4f40ab19cecf48a534c409f7ea983ab8fed0741304a1c0a31b3f2", size = 94440, upload-time = "2025-10-14T15:06:21.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/1a/206e8cf2dd86fddf939165a57b4df61607a1e0add2785f170a3f616b7d9f/watchfiles-1.1.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:eef58232d32daf2ac67f42dea51a2c80f0d03379075d44a587051e63cc2e368c", size = 407318, upload-time = "2025-10-14T15:04:18.753Z" }, + { url = "https://files.pythonhosted.org/packages/b3/0f/abaf5262b9c496b5dad4ed3c0e799cbecb1f8ea512ecb6ddd46646a9fca3/watchfiles-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03fa0f5237118a0c5e496185cafa92878568b652a2e9a9382a5151b1a0380a43", size = 394478, upload-time = "2025-10-14T15:04:20.297Z" }, + { url = "https://files.pythonhosted.org/packages/b1/04/9cc0ba88697b34b755371f5ace8d3a4d9a15719c07bdc7bd13d7d8c6a341/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ca65483439f9c791897f7db49202301deb6e15fe9f8fe2fed555bf986d10c31", size = 449894, upload-time = "2025-10-14T15:04:21.527Z" }, + { url = "https://files.pythonhosted.org/packages/d2/9c/eda4615863cd8621e89aed4df680d8c3ec3da6a4cf1da113c17decd87c7f/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f0ab1c1af0cb38e3f598244c17919fb1a84d1629cc08355b0074b6d7f53138ac", size = 459065, upload-time = "2025-10-14T15:04:22.795Z" }, + { url = "https://files.pythonhosted.org/packages/84/13/f28b3f340157d03cbc8197629bc109d1098764abe1e60874622a0be5c112/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bc570d6c01c206c46deb6e935a260be44f186a2f05179f52f7fcd2be086a94d", size = 488377, upload-time = "2025-10-14T15:04:24.138Z" }, + { url = "https://files.pythonhosted.org/packages/86/93/cfa597fa9389e122488f7ffdbd6db505b3b915ca7435ecd7542e855898c2/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e84087b432b6ac94778de547e08611266f1f8ffad28c0ee4c82e028b0fc5966d", size = 595837, upload-time = "2025-10-14T15:04:25.057Z" }, + { url = "https://files.pythonhosted.org/packages/57/1e/68c1ed5652b48d89fc24d6af905d88ee4f82fa8bc491e2666004e307ded1/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:620bae625f4cb18427b1bb1a2d9426dc0dd5a5ba74c7c2cdb9de405f7b129863", size = 473456, upload-time = "2025-10-14T15:04:26.497Z" }, + { url = "https://files.pythonhosted.org/packages/d5/dc/1a680b7458ffa3b14bb64878112aefc8f2e4f73c5af763cbf0bd43100658/watchfiles-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:544364b2b51a9b0c7000a4b4b02f90e9423d97fbbf7e06689236443ebcad81ab", size = 455614, upload-time = "2025-10-14T15:04:27.539Z" }, + { url = "https://files.pythonhosted.org/packages/61/a5/3d782a666512e01eaa6541a72ebac1d3aae191ff4a31274a66b8dd85760c/watchfiles-1.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bbe1ef33d45bc71cf21364df962af171f96ecaeca06bd9e3d0b583efb12aec82", size = 630690, upload-time = "2025-10-14T15:04:28.495Z" }, + { url = "https://files.pythonhosted.org/packages/9b/73/bb5f38590e34687b2a9c47a244aa4dd50c56a825969c92c9c5fc7387cea1/watchfiles-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1a0bb430adb19ef49389e1ad368450193a90038b5b752f4ac089ec6942c4dff4", size = 622459, upload-time = "2025-10-14T15:04:29.491Z" }, + { url = "https://files.pythonhosted.org/packages/f1/ac/c9bb0ec696e07a20bd58af5399aeadaef195fb2c73d26baf55180fe4a942/watchfiles-1.1.1-cp310-cp310-win32.whl", hash = "sha256:3f6d37644155fb5beca5378feb8c1708d5783145f2a0f1c4d5a061a210254844", size = 272663, upload-time = "2025-10-14T15:04:30.435Z" }, + { url = "https://files.pythonhosted.org/packages/11/a0/a60c5a7c2ec59fa062d9a9c61d02e3b6abd94d32aac2d8344c4bdd033326/watchfiles-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:a36d8efe0f290835fd0f33da35042a1bb5dc0e83cbc092dcf69bce442579e88e", size = 287453, upload-time = "2025-10-14T15:04:31.53Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f8/2c5f479fb531ce2f0564eda479faecf253d886b1ab3630a39b7bf7362d46/watchfiles-1.1.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f57b396167a2565a4e8b5e56a5a1c537571733992b226f4f1197d79e94cf0ae5", size = 406529, upload-time = "2025-10-14T15:04:32.899Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cd/f515660b1f32f65df671ddf6f85bfaca621aee177712874dc30a97397977/watchfiles-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:421e29339983e1bebc281fab40d812742268ad057db4aee8c4d2bce0af43b741", size = 394384, upload-time = "2025-10-14T15:04:33.761Z" }, + { url = "https://files.pythonhosted.org/packages/7b/c3/28b7dc99733eab43fca2d10f55c86e03bd6ab11ca31b802abac26b23d161/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e43d39a741e972bab5d8100b5cdacf69db64e34eb19b6e9af162bccf63c5cc6", size = 448789, upload-time = "2025-10-14T15:04:34.679Z" }, + { url = "https://files.pythonhosted.org/packages/4a/24/33e71113b320030011c8e4316ccca04194bf0cbbaeee207f00cbc7d6b9f5/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f537afb3276d12814082a2e9b242bdcf416c2e8fd9f799a737990a1dbe906e5b", size = 460521, upload-time = "2025-10-14T15:04:35.963Z" }, + { url = "https://files.pythonhosted.org/packages/f4/c3/3c9a55f255aa57b91579ae9e98c88704955fa9dac3e5614fb378291155df/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2cd9e04277e756a2e2d2543d65d1e2166d6fd4c9b183f8808634fda23f17b14", size = 488722, upload-time = "2025-10-14T15:04:37.091Z" }, + { url = "https://files.pythonhosted.org/packages/49/36/506447b73eb46c120169dc1717fe2eff07c234bb3232a7200b5f5bd816e9/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f3f58818dc0b07f7d9aa7fe9eb1037aecb9700e63e1f6acfed13e9fef648f5d", size = 596088, upload-time = "2025-10-14T15:04:38.39Z" }, + { url = "https://files.pythonhosted.org/packages/82/ab/5f39e752a9838ec4d52e9b87c1e80f1ee3ccdbe92e183c15b6577ab9de16/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bb9f66367023ae783551042d31b1d7fd422e8289eedd91f26754a66f44d5cff", size = 472923, upload-time = "2025-10-14T15:04:39.666Z" }, + { url = "https://files.pythonhosted.org/packages/af/b9/a419292f05e302dea372fa7e6fda5178a92998411f8581b9830d28fb9edb/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aebfd0861a83e6c3d1110b78ad54704486555246e542be3e2bb94195eabb2606", size = 456080, upload-time = "2025-10-14T15:04:40.643Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c3/d5932fd62bde1a30c36e10c409dc5d54506726f08cb3e1d8d0ba5e2bc8db/watchfiles-1.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5fac835b4ab3c6487b5dbad78c4b3724e26bcc468e886f8ba8cc4306f68f6701", size = 629432, upload-time = "2025-10-14T15:04:41.789Z" }, + { url = "https://files.pythonhosted.org/packages/f7/77/16bddd9779fafb795f1a94319dc965209c5641db5bf1edbbccace6d1b3c0/watchfiles-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:399600947b170270e80134ac854e21b3ccdefa11a9529a3decc1327088180f10", size = 623046, upload-time = "2025-10-14T15:04:42.718Z" }, + { url = "https://files.pythonhosted.org/packages/46/ef/f2ecb9a0f342b4bfad13a2787155c6ee7ce792140eac63a34676a2feeef2/watchfiles-1.1.1-cp311-cp311-win32.whl", hash = "sha256:de6da501c883f58ad50db3a32ad397b09ad29865b5f26f64c24d3e3281685849", size = 271473, upload-time = "2025-10-14T15:04:43.624Z" }, + { url = "https://files.pythonhosted.org/packages/94/bc/f42d71125f19731ea435c3948cad148d31a64fccde3867e5ba4edee901f9/watchfiles-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:35c53bd62a0b885bf653ebf6b700d1bf05debb78ad9292cf2a942b23513dc4c4", size = 287598, upload-time = "2025-10-14T15:04:44.516Z" }, + { url = "https://files.pythonhosted.org/packages/57/c9/a30f897351f95bbbfb6abcadafbaca711ce1162f4db95fc908c98a9165f3/watchfiles-1.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:57ca5281a8b5e27593cb7d82c2ac927ad88a96ed406aa446f6344e4328208e9e", size = 277210, upload-time = "2025-10-14T15:04:45.883Z" }, + { url = "https://files.pythonhosted.org/packages/74/d5/f039e7e3c639d9b1d09b07ea412a6806d38123f0508e5f9b48a87b0a76cc/watchfiles-1.1.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8c89f9f2f740a6b7dcc753140dd5e1ab9215966f7a3530d0c0705c83b401bd7d", size = 404745, upload-time = "2025-10-14T15:04:46.731Z" }, + { url = "https://files.pythonhosted.org/packages/a5/96/a881a13aa1349827490dab2d363c8039527060cfcc2c92cc6d13d1b1049e/watchfiles-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd404be08018c37350f0d6e34676bd1e2889990117a2b90070b3007f172d0610", size = 391769, upload-time = "2025-10-14T15:04:48.003Z" }, + { url = "https://files.pythonhosted.org/packages/4b/5b/d3b460364aeb8da471c1989238ea0e56bec24b6042a68046adf3d9ddb01c/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8526e8f916bb5b9a0a777c8317c23ce65de259422bba5b31325a6fa6029d33af", size = 449374, upload-time = "2025-10-14T15:04:49.179Z" }, + { url = "https://files.pythonhosted.org/packages/b9/44/5769cb62d4ed055cb17417c0a109a92f007114a4e07f30812a73a4efdb11/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2edc3553362b1c38d9f06242416a5d8e9fe235c204a4072e988ce2e5bb1f69f6", size = 459485, upload-time = "2025-10-14T15:04:50.155Z" }, + { url = "https://files.pythonhosted.org/packages/19/0c/286b6301ded2eccd4ffd0041a1b726afda999926cf720aab63adb68a1e36/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30f7da3fb3f2844259cba4720c3fc7138eb0f7b659c38f3bfa65084c7fc7abce", size = 488813, upload-time = "2025-10-14T15:04:51.059Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2b/8530ed41112dd4a22f4dcfdb5ccf6a1baad1ff6eed8dc5a5f09e7e8c41c7/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8979280bdafff686ba5e4d8f97840f929a87ed9cdf133cbbd42f7766774d2aa", size = 594816, upload-time = "2025-10-14T15:04:52.031Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d2/f5f9fb49489f184f18470d4f99f4e862a4b3e9ac2865688eb2099e3d837a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcc5c24523771db3a294c77d94771abcfcb82a0e0ee8efd910c37c59ec1b31bb", size = 475186, upload-time = "2025-10-14T15:04:53.064Z" }, + { url = "https://files.pythonhosted.org/packages/cf/68/5707da262a119fb06fbe214d82dd1fe4a6f4af32d2d14de368d0349eb52a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db5d7ae38ff20153d542460752ff397fcf5c96090c1230803713cf3147a6803", size = 456812, upload-time = "2025-10-14T15:04:55.174Z" }, + { url = "https://files.pythonhosted.org/packages/66/ab/3cbb8756323e8f9b6f9acb9ef4ec26d42b2109bce830cc1f3468df20511d/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:28475ddbde92df1874b6c5c8aaeb24ad5be47a11f87cde5a28ef3835932e3e94", size = 630196, upload-time = "2025-10-14T15:04:56.22Z" }, + { url = "https://files.pythonhosted.org/packages/78/46/7152ec29b8335f80167928944a94955015a345440f524d2dfe63fc2f437b/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:36193ed342f5b9842edd3532729a2ad55c4160ffcfa3700e0d54be496b70dd43", size = 622657, upload-time = "2025-10-14T15:04:57.521Z" }, + { url = "https://files.pythonhosted.org/packages/0a/bf/95895e78dd75efe9a7f31733607f384b42eb5feb54bd2eb6ed57cc2e94f4/watchfiles-1.1.1-cp312-cp312-win32.whl", hash = "sha256:859e43a1951717cc8de7f4c77674a6d389b106361585951d9e69572823f311d9", size = 272042, upload-time = "2025-10-14T15:04:59.046Z" }, + { url = "https://files.pythonhosted.org/packages/87/0a/90eb755f568de2688cb220171c4191df932232c20946966c27a59c400850/watchfiles-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:91d4c9a823a8c987cce8fa2690923b069966dabb196dd8d137ea2cede885fde9", size = 288410, upload-time = "2025-10-14T15:05:00.081Z" }, + { url = "https://files.pythonhosted.org/packages/36/76/f322701530586922fbd6723c4f91ace21364924822a8772c549483abed13/watchfiles-1.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:a625815d4a2bdca61953dbba5a39d60164451ef34c88d751f6c368c3ea73d404", size = 278209, upload-time = "2025-10-14T15:05:01.168Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f4/f750b29225fe77139f7ae5de89d4949f5a99f934c65a1f1c0b248f26f747/watchfiles-1.1.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:130e4876309e8686a5e37dba7d5e9bc77e6ed908266996ca26572437a5271e18", size = 404321, upload-time = "2025-10-14T15:05:02.063Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/f07a295cde762644aa4c4bb0f88921d2d141af45e735b965fb2e87858328/watchfiles-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f3bde70f157f84ece3765b42b4a52c6ac1a50334903c6eaf765362f6ccca88a", size = 391783, upload-time = "2025-10-14T15:05:03.052Z" }, + { url = "https://files.pythonhosted.org/packages/bc/11/fc2502457e0bea39a5c958d86d2cb69e407a4d00b85735ca724bfa6e0d1a/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e0b1fe858430fc0251737ef3824c54027bedb8c37c38114488b8e131cf8219", size = 449279, upload-time = "2025-10-14T15:05:04.004Z" }, + { url = "https://files.pythonhosted.org/packages/e3/1f/d66bc15ea0b728df3ed96a539c777acfcad0eb78555ad9efcaa1274688f0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f27db948078f3823a6bb3b465180db8ebecf26dd5dae6f6180bd87383b6b4428", size = 459405, upload-time = "2025-10-14T15:05:04.942Z" }, + { url = "https://files.pythonhosted.org/packages/be/90/9f4a65c0aec3ccf032703e6db02d89a157462fbb2cf20dd415128251cac0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:059098c3a429f62fc98e8ec62b982230ef2c8df68c79e826e37b895bc359a9c0", size = 488976, upload-time = "2025-10-14T15:05:05.905Z" }, + { url = "https://files.pythonhosted.org/packages/37/57/ee347af605d867f712be7029bb94c8c071732a4b44792e3176fa3c612d39/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfb5862016acc9b869bb57284e6cb35fdf8e22fe59f7548858e2f971d045f150", size = 595506, upload-time = "2025-10-14T15:05:06.906Z" }, + { url = "https://files.pythonhosted.org/packages/a8/78/cc5ab0b86c122047f75e8fc471c67a04dee395daf847d3e59381996c8707/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:319b27255aacd9923b8a276bb14d21a5f7ff82564c744235fc5eae58d95422ae", size = 474936, upload-time = "2025-10-14T15:05:07.906Z" }, + { url = "https://files.pythonhosted.org/packages/62/da/def65b170a3815af7bd40a3e7010bf6ab53089ef1b75d05dd5385b87cf08/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c755367e51db90e75b19454b680903631d41f9e3607fbd941d296a020c2d752d", size = 456147, upload-time = "2025-10-14T15:05:09.138Z" }, + { url = "https://files.pythonhosted.org/packages/57/99/da6573ba71166e82d288d4df0839128004c67d2778d3b566c138695f5c0b/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c22c776292a23bfc7237a98f791b9ad3144b02116ff10d820829ce62dff46d0b", size = 630007, upload-time = "2025-10-14T15:05:10.117Z" }, + { url = "https://files.pythonhosted.org/packages/a8/51/7439c4dd39511368849eb1e53279cd3454b4a4dbace80bab88feeb83c6b5/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3a476189be23c3686bc2f4321dd501cb329c0a0469e77b7b534ee10129ae6374", size = 622280, upload-time = "2025-10-14T15:05:11.146Z" }, + { url = "https://files.pythonhosted.org/packages/95/9c/8ed97d4bba5db6fdcdb2b298d3898f2dd5c20f6b73aee04eabe56c59677e/watchfiles-1.1.1-cp313-cp313-win32.whl", hash = "sha256:bf0a91bfb5574a2f7fc223cf95eeea79abfefa404bf1ea5e339c0c1560ae99a0", size = 272056, upload-time = "2025-10-14T15:05:12.156Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/c14e28429f744a260d8ceae18bf58c1d5fa56b50d006a7a9f80e1882cb0d/watchfiles-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:52e06553899e11e8074503c8e716d574adeeb7e68913115c4b3653c53f9bae42", size = 288162, upload-time = "2025-10-14T15:05:13.208Z" }, + { url = "https://files.pythonhosted.org/packages/dc/61/fe0e56c40d5cd29523e398d31153218718c5786b5e636d9ae8ae79453d27/watchfiles-1.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:ac3cc5759570cd02662b15fbcd9d917f7ecd47efe0d6b40474eafd246f91ea18", size = 277909, upload-time = "2025-10-14T15:05:14.49Z" }, + { url = "https://files.pythonhosted.org/packages/79/42/e0a7d749626f1e28c7108a99fb9bf524b501bbbeb9b261ceecde644d5a07/watchfiles-1.1.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:563b116874a9a7ce6f96f87cd0b94f7faf92d08d0021e837796f0a14318ef8da", size = 403389, upload-time = "2025-10-14T15:05:15.777Z" }, + { url = "https://files.pythonhosted.org/packages/15/49/08732f90ce0fbbc13913f9f215c689cfc9ced345fb1bcd8829a50007cc8d/watchfiles-1.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3ad9fe1dae4ab4212d8c91e80b832425e24f421703b5a42ef2e4a1e215aff051", size = 389964, upload-time = "2025-10-14T15:05:16.85Z" }, + { url = "https://files.pythonhosted.org/packages/27/0d/7c315d4bd5f2538910491a0393c56bf70d333d51bc5b34bee8e68e8cea19/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce70f96a46b894b36eba678f153f052967a0d06d5b5a19b336ab0dbbd029f73e", size = 448114, upload-time = "2025-10-14T15:05:17.876Z" }, + { url = "https://files.pythonhosted.org/packages/c3/24/9e096de47a4d11bc4df41e9d1e61776393eac4cb6eb11b3e23315b78b2cc/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cb467c999c2eff23a6417e58d75e5828716f42ed8289fe6b77a7e5a91036ca70", size = 460264, upload-time = "2025-10-14T15:05:18.962Z" }, + { url = "https://files.pythonhosted.org/packages/cc/0f/e8dea6375f1d3ba5fcb0b3583e2b493e77379834c74fd5a22d66d85d6540/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:836398932192dae4146c8f6f737d74baeac8b70ce14831a239bdb1ca882fc261", size = 487877, upload-time = "2025-10-14T15:05:20.094Z" }, + { url = "https://files.pythonhosted.org/packages/ac/5b/df24cfc6424a12deb41503b64d42fbea6b8cb357ec62ca84a5a3476f654a/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:743185e7372b7bc7c389e1badcc606931a827112fbbd37f14c537320fca08620", size = 595176, upload-time = "2025-10-14T15:05:21.134Z" }, + { url = "https://files.pythonhosted.org/packages/8f/b5/853b6757f7347de4e9b37e8cc3289283fb983cba1ab4d2d7144694871d9c/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afaeff7696e0ad9f02cbb8f56365ff4686ab205fcf9c4c5b6fdfaaa16549dd04", size = 473577, upload-time = "2025-10-14T15:05:22.306Z" }, + { url = "https://files.pythonhosted.org/packages/e1/f7/0a4467be0a56e80447c8529c9fce5b38eab4f513cb3d9bf82e7392a5696b/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7eb7da0eb23aa2ba036d4f616d46906013a68caf61b7fdbe42fc8b25132e77", size = 455425, upload-time = "2025-10-14T15:05:23.348Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e0/82583485ea00137ddf69bc84a2db88bd92ab4a6e3c405e5fb878ead8d0e7/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:831a62658609f0e5c64178211c942ace999517f5770fe9436be4c2faeba0c0ef", size = 628826, upload-time = "2025-10-14T15:05:24.398Z" }, + { url = "https://files.pythonhosted.org/packages/28/9a/a785356fccf9fae84c0cc90570f11702ae9571036fb25932f1242c82191c/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:f9a2ae5c91cecc9edd47e041a930490c31c3afb1f5e6d71de3dc671bfaca02bf", size = 622208, upload-time = "2025-10-14T15:05:25.45Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f4/0872229324ef69b2c3edec35e84bd57a1289e7d3fe74588048ed8947a323/watchfiles-1.1.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:d1715143123baeeaeadec0528bb7441103979a1d5f6fd0e1f915383fea7ea6d5", size = 404315, upload-time = "2025-10-14T15:05:26.501Z" }, + { url = "https://files.pythonhosted.org/packages/7b/22/16d5331eaed1cb107b873f6ae1b69e9ced582fcf0c59a50cd84f403b1c32/watchfiles-1.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:39574d6370c4579d7f5d0ad940ce5b20db0e4117444e39b6d8f99db5676c52fd", size = 390869, upload-time = "2025-10-14T15:05:27.649Z" }, + { url = "https://files.pythonhosted.org/packages/b2/7e/5643bfff5acb6539b18483128fdc0ef2cccc94a5b8fbda130c823e8ed636/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7365b92c2e69ee952902e8f70f3ba6360d0d596d9299d55d7d386df84b6941fb", size = 449919, upload-time = "2025-10-14T15:05:28.701Z" }, + { url = "https://files.pythonhosted.org/packages/51/2e/c410993ba5025a9f9357c376f48976ef0e1b1aefb73b97a5ae01a5972755/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bfff9740c69c0e4ed32416f013f3c45e2ae42ccedd1167ef2d805c000b6c71a5", size = 460845, upload-time = "2025-10-14T15:05:30.064Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a4/2df3b404469122e8680f0fcd06079317e48db58a2da2950fb45020947734/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b27cf2eb1dda37b2089e3907d8ea92922b673c0c427886d4edc6b94d8dfe5db3", size = 489027, upload-time = "2025-10-14T15:05:31.064Z" }, + { url = "https://files.pythonhosted.org/packages/ea/84/4587ba5b1f267167ee715b7f66e6382cca6938e0a4b870adad93e44747e6/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:526e86aced14a65a5b0ec50827c745597c782ff46b571dbfe46192ab9e0b3c33", size = 595615, upload-time = "2025-10-14T15:05:32.074Z" }, + { url = "https://files.pythonhosted.org/packages/6a/0f/c6988c91d06e93cd0bb3d4a808bcf32375ca1904609835c3031799e3ecae/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04e78dd0b6352db95507fd8cb46f39d185cf8c74e4cf1e4fbad1d3df96faf510", size = 474836, upload-time = "2025-10-14T15:05:33.209Z" }, + { url = "https://files.pythonhosted.org/packages/b4/36/ded8aebea91919485b7bbabbd14f5f359326cb5ec218cd67074d1e426d74/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c85794a4cfa094714fb9c08d4a218375b2b95b8ed1666e8677c349906246c05", size = 455099, upload-time = "2025-10-14T15:05:34.189Z" }, + { url = "https://files.pythonhosted.org/packages/98/e0/8c9bdba88af756a2fce230dd365fab2baf927ba42cd47521ee7498fd5211/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:74d5012b7630714b66be7b7b7a78855ef7ad58e8650c73afc4c076a1f480a8d6", size = 630626, upload-time = "2025-10-14T15:05:35.216Z" }, + { url = "https://files.pythonhosted.org/packages/2a/84/a95db05354bf2d19e438520d92a8ca475e578c647f78f53197f5a2f17aaf/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:8fbe85cb3201c7d380d3d0b90e63d520f15d6afe217165d7f98c9c649654db81", size = 622519, upload-time = "2025-10-14T15:05:36.259Z" }, + { url = "https://files.pythonhosted.org/packages/1d/ce/d8acdc8de545de995c339be67711e474c77d643555a9bb74a9334252bd55/watchfiles-1.1.1-cp314-cp314-win32.whl", hash = "sha256:3fa0b59c92278b5a7800d3ee7733da9d096d4aabcfabb9a928918bd276ef9b9b", size = 272078, upload-time = "2025-10-14T15:05:37.63Z" }, + { url = "https://files.pythonhosted.org/packages/c4/c9/a74487f72d0451524be827e8edec251da0cc1fcf111646a511ae752e1a3d/watchfiles-1.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:c2047d0b6cea13b3316bdbafbfa0c4228ae593d995030fda39089d36e64fc03a", size = 287664, upload-time = "2025-10-14T15:05:38.95Z" }, + { url = "https://files.pythonhosted.org/packages/df/b8/8ac000702cdd496cdce998c6f4ee0ca1f15977bba51bdf07d872ebdfc34c/watchfiles-1.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:842178b126593addc05acf6fce960d28bc5fae7afbaa2c6c1b3a7b9460e5be02", size = 277154, upload-time = "2025-10-14T15:05:39.954Z" }, + { url = "https://files.pythonhosted.org/packages/47/a8/e3af2184707c29f0f14b1963c0aace6529f9d1b8582d5b99f31bbf42f59e/watchfiles-1.1.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:88863fbbc1a7312972f1c511f202eb30866370ebb8493aef2812b9ff28156a21", size = 403820, upload-time = "2025-10-14T15:05:40.932Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ec/e47e307c2f4bd75f9f9e8afbe3876679b18e1bcec449beca132a1c5ffb2d/watchfiles-1.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:55c7475190662e202c08c6c0f4d9e345a29367438cf8e8037f3155e10a88d5a5", size = 390510, upload-time = "2025-10-14T15:05:41.945Z" }, + { url = "https://files.pythonhosted.org/packages/d5/a0/ad235642118090f66e7b2f18fd5c42082418404a79205cdfca50b6309c13/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f53fa183d53a1d7a8852277c92b967ae99c2d4dcee2bfacff8868e6e30b15f7", size = 448408, upload-time = "2025-10-14T15:05:43.385Z" }, + { url = "https://files.pythonhosted.org/packages/df/85/97fa10fd5ff3332ae17e7e40e20784e419e28521549780869f1413742e9d/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6aae418a8b323732fa89721d86f39ec8f092fc2af67f4217a2b07fd3e93c6101", size = 458968, upload-time = "2025-10-14T15:05:44.404Z" }, + { url = "https://files.pythonhosted.org/packages/47/c2/9059c2e8966ea5ce678166617a7f75ecba6164375f3b288e50a40dc6d489/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f096076119da54a6080e8920cbdaac3dbee667eb91dcc5e5b78840b87415bd44", size = 488096, upload-time = "2025-10-14T15:05:45.398Z" }, + { url = "https://files.pythonhosted.org/packages/94/44/d90a9ec8ac309bc26db808a13e7bfc0e4e78b6fc051078a554e132e80160/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00485f441d183717038ed2e887a7c868154f216877653121068107b227a2f64c", size = 596040, upload-time = "2025-10-14T15:05:46.502Z" }, + { url = "https://files.pythonhosted.org/packages/95/68/4e3479b20ca305cfc561db3ed207a8a1c745ee32bf24f2026a129d0ddb6e/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a55f3e9e493158d7bfdb60a1165035f1cf7d320914e7b7ea83fe22c6023b58fc", size = 473847, upload-time = "2025-10-14T15:05:47.484Z" }, + { url = "https://files.pythonhosted.org/packages/4f/55/2af26693fd15165c4ff7857e38330e1b61ab8c37d15dc79118cdba115b7a/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c91ed27800188c2ae96d16e3149f199d62f86c7af5f5f4d2c61a3ed8cd3666c", size = 455072, upload-time = "2025-10-14T15:05:48.928Z" }, + { url = "https://files.pythonhosted.org/packages/66/1d/d0d200b10c9311ec25d2273f8aad8c3ef7cc7ea11808022501811208a750/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:311ff15a0bae3714ffb603e6ba6dbfba4065ab60865d15a6ec544133bdb21099", size = 629104, upload-time = "2025-10-14T15:05:49.908Z" }, + { url = "https://files.pythonhosted.org/packages/e3/bd/fa9bb053192491b3867ba07d2343d9f2252e00811567d30ae8d0f78136fe/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a916a2932da8f8ab582f242c065f5c81bed3462849ca79ee357dd9551b0e9b01", size = 622112, upload-time = "2025-10-14T15:05:50.941Z" }, + { url = "https://files.pythonhosted.org/packages/ba/4c/a888c91e2e326872fa4705095d64acd8aa2fb9c1f7b9bd0588f33850516c/watchfiles-1.1.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:17ef139237dfced9da49fb7f2232c86ca9421f666d78c264c7ffca6601d154c3", size = 409611, upload-time = "2025-10-14T15:06:05.809Z" }, + { url = "https://files.pythonhosted.org/packages/1e/c7/5420d1943c8e3ce1a21c0a9330bcf7edafb6aa65d26b21dbb3267c9e8112/watchfiles-1.1.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:672b8adf25b1a0d35c96b5888b7b18699d27d4194bac8beeae75be4b7a3fc9b2", size = 396889, upload-time = "2025-10-14T15:06:07.035Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e5/0072cef3804ce8d3aaddbfe7788aadff6b3d3f98a286fdbee9fd74ca59a7/watchfiles-1.1.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77a13aea58bc2b90173bc69f2a90de8e282648939a00a602e1dc4ee23e26b66d", size = 451616, upload-time = "2025-10-14T15:06:08.072Z" }, + { url = "https://files.pythonhosted.org/packages/83/4e/b87b71cbdfad81ad7e83358b3e447fedd281b880a03d64a760fe0a11fc2e/watchfiles-1.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b495de0bb386df6a12b18335a0285dda90260f51bdb505503c02bcd1ce27a8b", size = 458413, upload-time = "2025-10-14T15:06:09.209Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8e/e500f8b0b77be4ff753ac94dc06b33d8f0d839377fee1b78e8c8d8f031bf/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db476ab59b6765134de1d4fe96a1a9c96ddf091683599be0f26147ea1b2e4b88", size = 408250, upload-time = "2025-10-14T15:06:10.264Z" }, + { url = "https://files.pythonhosted.org/packages/bd/95/615e72cd27b85b61eec764a5ca51bd94d40b5adea5ff47567d9ebc4d275a/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89eef07eee5e9d1fda06e38822ad167a044153457e6fd997f8a858ab7564a336", size = 396117, upload-time = "2025-10-14T15:06:11.28Z" }, + { url = "https://files.pythonhosted.org/packages/c9/81/e7fe958ce8a7fb5c73cc9fb07f5aeaf755e6aa72498c57d760af760c91f8/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce19e06cbda693e9e7686358af9cd6f5d61312ab8b00488bc36f5aabbaf77e24", size = 450493, upload-time = "2025-10-14T15:06:12.321Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d4/ed38dd3b1767193de971e694aa544356e63353c33a85d948166b5ff58b9e/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e6f39af2eab0118338902798b5aa6664f46ff66bc0280de76fca67a7f262a49", size = 457546, upload-time = "2025-10-14T15:06:13.372Z" }, +] + +[[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/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/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +]