From eef657a4e70495a97f1384609334dd31649b6f27 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Thu, 7 Aug 2025 00:21:02 +0300 Subject: [PATCH 001/198] Initial commit --- .github/workflows/lint.yaml | 35 +++++++ .gitignore | 31 ++++++ .pre-commit-config.yaml | 18 ++++ LICENSE.txt | 7 ++ README.md | 186 ++++++++++++++++++++++++++++++++++++ pyproject.toml | 63 ++++++++++++ samples/Pipfile | 15 +++ samples/pyproject.toml | 19 ++++ 8 files changed, 374 insertions(+) create mode 100644 .github/workflows/lint.yaml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 pyproject.toml create mode 100644 samples/Pipfile create mode 100644 samples/pyproject.toml diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 00000000..7f67e803 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,35 @@ +# GitHub Action workflow enforcing our code style. + +name: Lint + +# Trigger the workflow on both push (to the main repository, on the main branch) +# and pull requests (against the main repository, but from any repo, from any branch). +on: + push: + branches: + - main + pull_request: + +# Brand new concurrency setting! This ensures that not more than one run can be triggered for the same commit. +# It is useful for pull requests coming from the main repository since both triggers will match. +concurrency: lint-${{ github.sha }} + +jobs: + lint: + runs-on: ubuntu-latest + + env: + # The Python version your project uses. Feel free to change this if required. + PYTHON_VERSION: "3.12" + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python ${{ env.PYTHON_VERSION }} + uses: actions/setup-python@v5 + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Run pre-commit hooks + uses: pre-commit/action@v3.0.1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..233eb87e --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Files generated by the interpreter +__pycache__/ +*.py[cod] + +# Environment specific +.venv +venv +.env +env + +# Unittest reports +.coverage* + +# Logs +*.log + +# PyEnv version selector +.python-version + +# Built objects +*.so +dist/ +build/ + +# IDEs +# PyCharm +.idea/ +# VSCode +.vscode/ +# MacOS +.DS_Store diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..c0a8de23 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,18 @@ +# Pre-commit configuration. +# See https://github.com/python-discord/code-jam-template/tree/main#pre-commit-run-linting-before-committing + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.12.2 + hooks: + - id: ruff-check + - id: ruff-format diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..5a04926b --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,7 @@ +Copyright 2021 Python Discord + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..3bf4bfba --- /dev/null +++ b/README.md @@ -0,0 +1,186 @@ +# Python Discord Code Jam Repository Template + +## A primer + +Hello code jam participants! We've put together this repository template for you to use in [our code jams](https://pythondiscord.com/events/) or even other Python events! + +This document contains the following information: + +1. [What does this template contain?](#what-does-this-template-contain) +2. [How do I use this template?](#how-do-i-use-this-template) +3. [How do I adapt this template to my project?](#how-do-i-adapt-this-template-to-my-project) + +> [!TIP] +> You can also look at [our style guide](https://pythondiscord.com/events/code-jams/code-style-guide/) to get more information about what we consider a maintainable code style. + +## What does this template contain? + +Here is a quick rundown of what each file in this repository contains: + +- [`LICENSE.txt`](LICENSE.txt): [The MIT License](https://opensource.org/licenses/MIT), an OSS approved license which grants rights to everyone to use and modify your project, and limits your liability. We highly recommend you to read the license. +- [`.gitignore`](.gitignore): A list of files and directories that will be ignored by Git. Most of them are auto-generated or contain data that you wouldn't want to share publicly. +- [`pyproject.toml`](pyproject.toml): Configuration and metadata for the project, as well as the linting tool Ruff. If you're interested, you can read more about `pyproject.toml` in the [Python Packaging documentation](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/). +- [`.pre-commit-config.yaml`](.pre-commit-config.yaml): The configuration of the [pre-commit](https://pre-commit.com/) tool. +- [`.github/workflows/lint.yaml`](.github/workflows/lint.yaml): A [GitHub Actions](https://github.com/features/actions) workflow, a set of actions run by GitHub on their server after each push, to ensure the style requirements are met. + +Each of these files have comments for you to understand easily, and modify to fit your needs. + +### Ruff: general style rules + +Our first tool is Ruff. It will check your codebase and warn you about any non-conforming lines. +It is run with the command `ruff check` in the project root. + +Here is a sample output: + +```shell +$ ruff check +app.py:1:5: N802 Function name `helloWorld` should be lowercase +app.py:1:5: ANN201 Missing return type annotation for public function `helloWorld` +app.py:2:5: D400 First line should end with a period +app.py:2:5: D403 First word of the first line should be capitalized: `docstring` -> `Docstring` +app.py:3:15: W292 No newline at end of file +Found 5 errors. +``` + +Each line corresponds to an error. The first part is the file path, then the line number, and the column index. +Then comes the error code, a unique identifier of the error, and then a human-readable message. + +If, for any reason, you do not wish to comply with this specific error on a specific line, you can add `# noqa: CODE` at the end of the line. +For example: + +```python +def helloWorld(): # noqa: N802 + ... + +``` + +This will ignore the function naming issue and pass linting. + +> [!WARNING] +> We do not recommend ignoring errors unless you have a good reason to do so. + +### Ruff: formatting + +Ruff also comes with a formatter, which can be run with the command `ruff format`. +It follows the same code style enforced by [Black](https://black.readthedocs.io/en/stable/index.html), so there's no need to pick between them. + +### Pre-commit: run linting before committing + +The second tool doesn't check your code, but rather makes sure that you actually *do* check it. + +It makes use of a feature called [Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) which allow you to run a piece of code before running `git commit`. +The good thing about it is that it will cancel your commit if the lint doesn't pass. You won't have to wait for GitHub Actions to report issues and have a second fix commit. + +It is *installed* by running `pre-commit install` and can be run manually by calling only `pre-commit`. + +[Lint before you push!](https://soundcloud.com/lemonsaurusrex/lint-before-you-push) + +#### List of hooks + +- `check-toml`: Lints and corrects your TOML files. +- `check-yaml`: Lints and corrects your YAML files. +- `end-of-file-fixer`: Makes sure you always have an empty line at the end of your file. +- `trailing-whitespace`: Removes whitespaces at the end of each line. +- `ruff-check`: Runs the Ruff linter. +- `ruff-format`: Runs the Ruff formatter. + +## How do I use this template? + +### Creating your team repository + +One person in the team, preferably the leader, will have to create the repository and add other members as collaborators. + +1. In the top right corner of your screen, where **Clone** usually is, you have a **Use this template** button to click. + ![use-this-template-button](https://docs.github.com/assets/images/help/repository/use-this-template-button.png) +2. Give the repository a name and a description. + ![create-repository-name](https://docs.github.com/assets/images/help/repository/create-repository-name.png) +3. Click **Create repository from template**. +4. Click **Settings** in your newly created repository. + ![repo-actions-settings](https://docs.github.com/assets/images/help/repository/repo-actions-settings.png) +5. In the "Access" section of the sidebar, click **Collaborators**. + ![collaborators-settings](https://github.com/python-discord/code-jam-template/assets/63936253/c150110e-d1b5-4e4d-93e0-0a2cf1de352b) +6. Click **Add people**. +7. Insert the names of each of your teammates, and invite them. Once they have accepted the invitation in their email, they will have write access to the repository. + +You are now ready to go! Sit down, relax, and wait for the kickstart! + +> [!IMPORTANT] +> Don't forget to change the project name, description, and authors at the top of the [`pyproject.toml`](pyproject.toml) file, and swap "Python Discord" in the [`LICENSE.txt`](LICENSE.txt) file for the name of each of your team members or the name of your team *after* the start of the code jam. + +### Using the default pip setup + +Our default setup includes a dependency group to be used with a [virtual environment](https://docs.python.org/3/library/venv.html). +It works with pip and uv, and we recommend this if you have never used any other dependency manager, although if you have, feel free to switch to it. +More on that [below](#how-do-i-adapt-this-template-to-my-project). + +Dependency groups are a relatively new feature, specified in [PEP 735](https://peps.python.org/pep-0735/). +You can read more about them in the [Python Packaging User Guide](https://packaging.python.org/en/latest/specifications/dependency-groups/). + +#### Creating the environment + +Create a virtual environment in the folder `.venv`. + +```shell +python -m venv .venv +``` + +#### Entering the environment + +It will change based on your operating system and shell. + +```shell +# Linux, Bash +$ source .venv/bin/activate +# Linux, Fish +$ source .venv/bin/activate.fish +# Linux, Csh +$ source .venv/bin/activate.csh +# Linux, PowerShell Core +$ .venv/bin/Activate.ps1 +# Windows, cmd.exe +> .venv\Scripts\activate.bat +# Windows, PowerShell +> .venv\Scripts\Activate.ps1 +``` + +#### Installing the dependencies + +Once the environment is created and activated, use this command to install the development dependencies. + +```shell +pip install --group dev +``` + +#### Exiting the environment + +Interestingly enough, it is the same for every platform. + +```shell +deactivate +``` + +Once the environment is activated, all the commands listed previously should work. + +> [!IMPORTANT] +> We highly recommend that you run `pre-commit install` as soon as possible. + +## How do I adapt this template to my project? + +If you wish to use Pipenv or Poetry, you will have to move the dependencies in [`pyproject.toml`](pyproject.toml) to the development dependencies of your tool. + +We've included a porting to both [Poetry](samples/pyproject.toml) and [Pipenv](samples/Pipfile) in the [`samples` folder](samples). +Note that the Poetry [`pyproject.toml`](samples/pyproject.toml) file does not include the Ruff configuration, so if you simply replace the file then the Ruff configuration will be lost. + +When installing new dependencies, don't forget to [pin](https://pip.pypa.io/en/stable/topics/repeatable-installs/#pinning-the-package-versions) them by adding a version tag at the end. +For example, if I wish to install [Click](https://click.palletsprojects.com/en/8.1.x/), a quick look at [PyPI](https://pypi.org/project/click/) tells me that `8.1.7` is the latest version. +I will then add `click~=8.1`, without the last number, to my requirements file or dependency manager. + +> [!IMPORTANT] +> A code jam project is left unmaintained after the end of the event. If the dependencies aren't pinned, the project will break after any major change in an API. + +## Final words + +> [!IMPORTANT] +> Don't forget to replace this README with an actual description of your project! Images are also welcome! + +We hope this template will be helpful. Good luck in the jam! diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..6a232d06 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,63 @@ +[project] +# This section contains metadata about your project. +# Don't forget to change the name, description, and authors to match your project! +name = "code-jam-template" +description = "Add your description here" +authors = [ + { name = "Your Name" } +] +version = "0.1.0" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [] + +[dependency-groups] +# This `dev` group contains all the development requirements for our linting toolchain. +# Don't forget to pin your dependencies! +# This list will have to be migrated if you wish to use another dependency manager. +dev = [ + "pre-commit~=4.2.0", + "ruff~=0.12.2", +] + +[tool.ruff] +# Increase the line length. This breaks PEP8 but it is way easier to work with. +# The original reason for this limit was a standard vim terminal is only 79 characters, +# but this doesn't really apply anymore. +line-length = 119 +# Target Python 3.12. If you decide to use a different version of Python +# you will need to update this value. +target-version = "py312" +# Automatically fix auto-fixable issues. +fix = true +# The directory containing the source code. If you choose a different project layout +# you will need to update this value. +src = ["src"] + +[tool.ruff.lint] +# Enable all linting rules. +select = ["ALL"] +# Ignore some of the most obnoxious linting errors. +ignore = [ + # Missing docstrings. + "D100", + "D104", + "D105", + "D106", + "D107", + # Docstring whitespace. + "D203", + "D213", + # Docstring punctuation. + "D415", + # Docstring quotes. + "D301", + # Builtins. + "A", + # Print statements. + "T20", + # TODOs. + "TD002", + "TD003", + "FIX", +] diff --git a/samples/Pipfile b/samples/Pipfile new file mode 100644 index 00000000..dedd0c50 --- /dev/null +++ b/samples/Pipfile @@ -0,0 +1,15 @@ +# Sample Pipfile. + +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] + +[dev-packages] +ruff = "~=0.12.2" +pre-commit = "~=4.2.0" + +[requires] +python_version = "3.12" diff --git a/samples/pyproject.toml b/samples/pyproject.toml new file mode 100644 index 00000000..b486e506 --- /dev/null +++ b/samples/pyproject.toml @@ -0,0 +1,19 @@ +# Sample poetry configuration. + +[tool.poetry] +name = "Name" +version = "0.1.0" +description = "Description" +authors = ["Author 1 "] +license = "MIT" + +[tool.poetry.dependencies] +python = "3.12.*" + +[tool.poetry.dev-dependencies] +ruff = "~0.12.2" +pre-commit = "~4.2.0" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" From 172b19156741158b25c7f051c81adff05172ae0e Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Sat, 9 Aug 2025 22:02:13 +0300 Subject: [PATCH 002/198] Declare a base structure for the 3 chapters --- src/backend/README.md | 0 src/editor/README.md | 0 src/gallery/README.md | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/backend/README.md create mode 100644 src/editor/README.md create mode 100644 src/gallery/README.md diff --git a/src/backend/README.md b/src/backend/README.md new file mode 100644 index 00000000..e69de29b diff --git a/src/editor/README.md b/src/editor/README.md new file mode 100644 index 00000000..e69de29b diff --git a/src/gallery/README.md b/src/gallery/README.md new file mode 100644 index 00000000..e69de29b From 902dfc19a89b828c4745e437c11269f08f4fbecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Sun, 10 Aug 2025 07:21:33 +0200 Subject: [PATCH 003/198] Gallery: First draft of README --- src/gallery/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/gallery/README.md b/src/gallery/README.md index e69de29b..0c673507 100644 --- a/src/gallery/README.md +++ b/src/gallery/README.md @@ -0,0 +1,11 @@ +**Warning: incomplete. TODOS in the Issues section, comment 'dibs' if you want to solve it yourself.** + +## Concept + +This is the section of the project that manages the Image Gallery. It's a 3D place that has on display every picture that every user has ever posted on the app. + +You are able to navigate the room in 3D from a first-person perspective, being able to fly around the place. You also have the ability to share its different artworks by generating a link that will place you on the exact spot to admire said piece in all of its glory. + +## Development + +We utilize the [*pyscript*](https://github.com/pyscript/pyscript) framework, which allows the execution of Python code inside the browser, including also some very useful interop with JavaScript. This last feature has been very important for the making of this section, as it allows us to have [three.js](https://github.com/mrdoob/three.js) bindings that enable fast 3D rendering in the web browser (the interface in question being similar to how you can use compiled *C* code through libraries like *numpy*). From 90813f68395ee2663fe1f9bf3685e88bd2888d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Sun, 10 Aug 2025 07:45:14 +0200 Subject: [PATCH 004/198] Gallery: minimum functional PyScript setup w/ instructions Placeholder material taken from one of PyScript's official example projects (https://pyscript.com/@examples/webgl-icosahedron/latest) --- src/gallery/README.md | 9 ++ src/gallery/assets/css/examples.css | 59 ++++++++ src/gallery/assets/css/icosahedron.css | 64 +++++++++ src/gallery/index.html | 59 ++++++++ src/gallery/main.py | 182 +++++++++++++++++++++++++ src/gallery/pyscript.toml | 3 + 6 files changed, 376 insertions(+) create mode 100644 src/gallery/assets/css/examples.css create mode 100644 src/gallery/assets/css/icosahedron.css create mode 100644 src/gallery/index.html create mode 100644 src/gallery/main.py create mode 100644 src/gallery/pyscript.toml diff --git a/src/gallery/README.md b/src/gallery/README.md index 0c673507..c2772632 100644 --- a/src/gallery/README.md +++ b/src/gallery/README.md @@ -1,5 +1,14 @@ **Warning: incomplete. TODOS in the Issues section, comment 'dibs' if you want to solve it yourself.** +## Dev guide + +The easiest way to test the website locally is just to run a basic HTTP server. You can do that in Python by running the following in the directory that contains this file: + +``` +python3 -m http.server +``` + + ## Concept This is the section of the project that manages the Image Gallery. It's a 3D place that has on display every picture that every user has ever posted on the app. diff --git a/src/gallery/assets/css/examples.css b/src/gallery/assets/css/examples.css new file mode 100644 index 00000000..3f769c7d --- /dev/null +++ b/src/gallery/assets/css/examples.css @@ -0,0 +1,59 @@ +body { + margin: 0; +} + +.pyscript { + margin: 0.5rem; +} + +html { + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + Roboto, + "Helvetica Neue", + Arial, + "Noto Sans", + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji"; + line-height: 1.5; +} + +nav { + position: sticky; + width: 100%; + top: 0; + left: 0; + z-index: 9999; +} + +.logo { + padding-right: 10px; + font-size: 28px; + height: 30px; + max-width: inherit; +} + +.title { + text-decoration: none; + text-decoration-line: none; + text-decoration-style: initial; + text-decoration-color: initial; + font-weight: 400; + font-size: 1.5em; + line-height: 2em; + white-space: nowrap; +} + +.app-header { + display: flex; + align-items: center; + padding: 0.5rem 1rem; +} + diff --git a/src/gallery/assets/css/icosahedron.css b/src/gallery/assets/css/icosahedron.css new file mode 100644 index 00000000..a10f157b --- /dev/null +++ b/src/gallery/assets/css/icosahedron.css @@ -0,0 +1,64 @@ +body { + margin: 0; + text-align: center; + background-color: black; + cursor: crosshair; +} + +canvas { + display: block; + width: 100%; + height: 100%; +} + +.header { + top: 45%; + color: #dddddd; +} + +.footer { + bottom: 3%; +} + +.description { + color: gray; + padding-top: 50px; +} + +.btn { + border-radius: 30px; + padding: 10px 30px; +} + +a, +a:hover, +a:visited { + color: red; + text-decoration: none; +} + +.disable-selection { + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* Internet Explorer */ + -khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */ + -webkit-user-select: none; /* Chrome, Safari, and Opera */ + -webkit-touch-callout: none; /* Disable Android and iOS callouts*/ +} + +h1::after { + content: " V 2.0"; + font-size: 12px; + position: absolute; + top: 3px; + padding-left: 5px; + font-weight: 400; +} + +h2::after { + content: "2"; + font-size: 12px; + position: absolute; + top: 14px; + padding-left: 5px; +} + diff --git a/src/gallery/index.html b/src/gallery/index.html new file mode 100644 index 00000000..d5cfbe22 --- /dev/null +++ b/src/gallery/index.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + Raycaster Icosahedron + + + + + + + + + +

Loading...

+
+ +
+
+
+
+
+
+
+
+
+
+
+ + + + + + + diff --git a/src/gallery/main.py b/src/gallery/main.py new file mode 100644 index 00000000..e225acdc --- /dev/null +++ b/src/gallery/main.py @@ -0,0 +1,182 @@ +## PLACEHOLDER, TAKEN FROM: +## https://pyscript.com/@examples/webgl-icosahedron/latest + +from pyodide.ffi import to_js +from pyscript import when, window, document +from js import Math, THREE, performance, Object +import asyncio + +mouse = THREE.Vector2.new() + +renderer = THREE.WebGLRenderer.new({"antialias": True}) +renderer.setSize(1000, 1000) +renderer.shadowMap.enabled = False +renderer.shadowMap.type = THREE.PCFSoftShadowMap +renderer.shadowMap.needsUpdate = True + +document.body.appendChild(renderer.domElement) + + +@when("mousemove", "body") +def onMouseMove(event): + event.preventDefault() + mouse.x = (event.clientX / window.innerWidth) * 2 - 1 + mouse.y = -(event.clientY / window.innerHeight) * 2 + 1 + + +camera = THREE.PerspectiveCamera.new(35, window.innerWidth / window.innerHeight, 1, 500) +scene = THREE.Scene.new() +cameraRange = 3 + +camera.aspect = window.innerWidth / window.innerHeight +camera.updateProjectionMatrix() +renderer.setSize(window.innerWidth, window.innerHeight) + +setcolor = "#000000" + +scene.background = THREE.Color.new(setcolor) +scene.fog = THREE.Fog.new(setcolor, 2.5, 3.5) + +sceneGroup = THREE.Object3D.new() +particularGroup = THREE.Object3D.new() + + +def mathRandom(num=1): + setNumber = -Math.random() * num + Math.random() * num + return setNumber + + +particularGroup = THREE.Object3D.new() +modularGroup = THREE.Object3D.new() + +perms = { + "flatShading": True, + "color": "#111111", + "transparent": False, + "opacity": 1, + "wireframe": False, +} +perms = Object.fromEntries(to_js(perms)) + +particle_perms = {"color": "#FFFFFF", "side": THREE.DoubleSide} +particle_perms = Object.fromEntries(to_js(particle_perms)) + + +def create_cubes(mathRandom, modularGroup): + i = 0 + while i < 30: + geometry = THREE.IcosahedronGeometry.new() + material = THREE.MeshStandardMaterial.new(perms) + cube = THREE.Mesh.new(geometry, material) + cube.speedRotation = Math.random() * 0.1 + cube.positionX = mathRandom() + cube.positionY = mathRandom() + cube.positionZ = mathRandom() + cube.castShadow = True + cube.receiveShadow = True + newScaleValue = mathRandom(0.3) + cube.scale.set(newScaleValue, newScaleValue, newScaleValue) + cube.rotation.x = mathRandom(180 * Math.PI / 180) + cube.rotation.y = mathRandom(180 * Math.PI / 180) + cube.rotation.z = mathRandom(180 * Math.PI / 180) + cube.position.set(cube.positionX, cube.positionY, cube.positionZ) + modularGroup.add(cube) + i += 1 + + +create_cubes(mathRandom, modularGroup) + + +def generateParticle(mathRandom, particularGroup, num, amp=2): + gmaterial = THREE.MeshPhysicalMaterial.new(particle_perms) + gparticular = THREE.CircleGeometry.new(0.2, 5) + i = 0 + while i < num: + pscale = 0.001 + Math.abs(mathRandom(0.03)) + particular = THREE.Mesh.new(gparticular, gmaterial) + particular.position.set(mathRandom(amp), mathRandom(amp), mathRandom(amp)) + particular.rotation.set(mathRandom(), mathRandom(), mathRandom()) + particular.scale.set(pscale, pscale, pscale) + particular.speedValue = mathRandom(1) + particularGroup.add(particular) + i += 1 + + +generateParticle(mathRandom, particularGroup, 200, 2) + +sceneGroup.add(particularGroup) +scene.add(modularGroup) +scene.add(sceneGroup) + +camera.position.set(0, 0, cameraRange) +cameraValue = False + +ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.1) + +light = THREE.SpotLight.new(0xFFFFFF, 3) +light.position.set(5, 5, 2) +light.castShadow = True +light.shadow.mapSize.width = 10000 +light.shadow.mapSize.height = light.shadow.mapSize.width +light.penumbra = 0.5 + +lightBack = THREE.PointLight.new(0x0FFFFF, 1) +lightBack.position.set(0, -3, -1) + +scene.add(sceneGroup) +scene.add(light) +scene.add(lightBack) + +rectSize = 2 +intensity = 14 +rectLight = THREE.RectAreaLight.new(0x0FFFFF, intensity, rectSize, rectSize) +rectLight.position.set(0, 0, 1) +rectLight.lookAt(0, 0, 0) +scene.add(rectLight) + +raycaster = THREE.Raycaster.new() +uSpeed = 0.1 + +time = 0.0003 +camera.lookAt(scene.position) + + +async def main(): + while True: + time = performance.now() * 0.0003 + i = 0 + while i < particularGroup.children.length: + newObject = particularGroup.children[i] + newObject.rotation.x += newObject.speedValue / 10 + newObject.rotation.y += newObject.speedValue / 10 + newObject.rotation.z += newObject.speedValue / 10 + i += 1 + + i = 0 + while i < modularGroup.children.length: + newCubes = modularGroup.children[i] + newCubes.rotation.x += 0.008 + newCubes.rotation.y += 0.005 + newCubes.rotation.z += 0.003 + + newCubes.position.x = ( + Math.sin(time * newCubes.positionZ) * newCubes.positionY + ) + newCubes.position.y = ( + Math.cos(time * newCubes.positionX) * newCubes.positionZ + ) + newCubes.position.z = ( + Math.sin(time * newCubes.positionY) * newCubes.positionX + ) + i += 1 + + particularGroup.rotation.y += 0.005 + + modularGroup.rotation.y -= ((mouse.x * 4) + modularGroup.rotation.y) * uSpeed + modularGroup.rotation.x -= ((-mouse.y * 4) + modularGroup.rotation.x) * uSpeed + + renderer.render(scene, camera) + await asyncio.sleep(0.02) + + +asyncio.ensure_future(main()) diff --git a/src/gallery/pyscript.toml b/src/gallery/pyscript.toml new file mode 100644 index 00000000..e1d89c68 --- /dev/null +++ b/src/gallery/pyscript.toml @@ -0,0 +1,3 @@ +name = "Image Gallery" +description = "An online Image Gallery rendered through Three.js and WebGL and programmed in PyScript." + From 41a7ffaaa4fc13184976ebde83ca9ea0041dc62a Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sun, 10 Aug 2025 12:40:34 +0100 Subject: [PATCH 005/198] Add basic drawing tool. --- pyproject.toml | 4 +- src/editor/__init__.py | 0 src/editor/main.py | 18 + src/editor/scripts/editor.py | 114 ++++ uv.lock | 1152 ++++++++++++++++++++++++++++++++++ 5 files changed, 1287 insertions(+), 1 deletion(-) create mode 100644 src/editor/__init__.py create mode 100644 src/editor/main.py create mode 100644 src/editor/scripts/editor.py create mode 100644 uv.lock diff --git a/pyproject.toml b/pyproject.toml index 6a232d06..331ce5eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,9 @@ authors = [ version = "0.1.0" readme = "README.md" requires-python = ">=3.12" -dependencies = [] +dependencies = [ + "nicegui>=2.22.2", +] [dependency-groups] # This `dev` group contains all the development requirements for our linting toolchain. diff --git a/src/editor/__init__.py b/src/editor/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/editor/main.py b/src/editor/main.py new file mode 100644 index 00000000..1ad18b0f --- /dev/null +++ b/src/editor/main.py @@ -0,0 +1,18 @@ +from nicegui import app, ui + +app.add_static_files("/scripts", "scripts") + + +ui.add_head_html(""" + + +""") + +ui.add_body_html(""" +
+ +
+ +""") + +ui.run() diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py new file mode 100644 index 00000000..9824f7d2 --- /dev/null +++ b/src/editor/scripts/editor.py @@ -0,0 +1,114 @@ +from js import Math, MouseEvent, document, window +from pyscript import when + +canvas = document.getElementById("image-canvas") +ctx = canvas.getContext("2d") + +display_height = window.innerHeight * 0.8 +display_width = display_height * (2**0.5) + +SCALE = 2 + +canvas.style.height = f"{display_height}px" # 80vh +canvas.style.width = f"{display_width}px" # Same ratio as an A4 sheet of paper + +canvas.height = display_height * SCALE +canvas.width = display_width * SCALE + +ctx.strokeStyle = "black" +ctx.lineWidth = 10 +ctx.lineCap = "round" +ctx.lineJoin = "round" + +drawing = False +rect = canvas.getBoundingClientRect() + + +def get_canvas_coords(event: MouseEvent) -> tuple[float, float]: + """Give the canvas coordinates. + + Args: + event (MouseEvent): The mouse event + + Returns: + tuple[float, float]: The x and y coordinates + + """ + x = (event.clientX - rect.left) * SCALE + y = (event.clientY - rect.top) * SCALE + return (x, y) + + +@when("mousedown", "#image-canvas") +def start_path(event: MouseEvent) -> None: + """Start drawing the path. + + Args: + event (MouseEvent): The mouse event + + """ + global drawing + drawing = True + x, y = get_canvas_coords(event) + ctx.beginPath() + ctx.moveTo(x, y) + + +@when("mousemove", "#image-canvas") +def mouse_tracker(event: MouseEvent) -> None: + """Draw the path following the mouse. + + Args: + event (MouseEvent): The mouse event + + """ + if not drawing: + return + x, y = get_canvas_coords(event) + ctx.lineTo(x, y) + ctx.stroke() + + +@when("mouseup", "#image-canvas") +def stop_path(_: MouseEvent) -> None: + """Stop drawing path. + + Args: + event (MouseEvent): The mouse event + + """ + global drawing + if not drawing: + return + drawing = False + + +@when("mouseout", "#image-canvas") +def leaves_canvas(event: MouseEvent) -> None: + """Handle mouse leaving canvas. + + Args: + event (MouseEvent): The mouse event + + """ + global drawing + if not drawing: + return + x, y = get_canvas_coords(event) + ctx.lineTo(x, y) + ctx.stroke() # Draws the line to the point on the edge where the mouse leaves the canvas + drawing = False + + +@when("click", "#image-canvas") +def canvas_click(event: MouseEvent) -> None: + """Handle mouse clicking canvas. + + Args: + event (MouseEvent): The mouse event + + """ + x, y = get_canvas_coords(event) + ctx.beginPath() + ctx.ellipse(x, y, ctx.lineWidth / 6, ctx.lineWidth / 6, 0, 0, 2 * Math.PI) + ctx.stroke() diff --git a/uv.lock b/uv.lock new file mode 100644 index 00000000..9a29edbf --- /dev/null +++ b/uv.lock @@ -0,0 +1,1152 @@ +version = 1 +revision = 3 +requires-python = ">=3.12" + +[[package]] +name = "aiofiles" +version = "24.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/03/a88171e277e8caa88a4c77808c20ebb04ba74cc4681bf1e9416c862de237/aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c", size = 30247, upload-time = "2024-06-24T11:02:03.584Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/45/30bb92d442636f570cb5651bc661f52b610e2eec3f891a5dc3a4c3667db0/aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5", size = 15896, upload-time = "2024-06-24T11:02:01.529Z" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.12.15" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/e7/d92a237d8802ca88483906c388f7c201bbe96cd80a165ffd0ac2f6a8d59f/aiohttp-3.12.15.tar.gz", hash = "sha256:4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2", size = 7823716, upload-time = "2025-07-29T05:52:32.215Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/97/77cb2450d9b35f517d6cf506256bf4f5bda3f93a66b4ad64ba7fc917899c/aiohttp-3.12.15-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:802d3868f5776e28f7bf69d349c26fc0efadb81676d0afa88ed00d98a26340b7", size = 702333, upload-time = "2025-07-29T05:50:46.507Z" }, + { url = "https://files.pythonhosted.org/packages/83/6d/0544e6b08b748682c30b9f65640d006e51f90763b41d7c546693bc22900d/aiohttp-3.12.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2800614cd560287be05e33a679638e586a2d7401f4ddf99e304d98878c29444", size = 476948, upload-time = "2025-07-29T05:50:48.067Z" }, + { url = "https://files.pythonhosted.org/packages/3a/1d/c8c40e611e5094330284b1aea8a4b02ca0858f8458614fa35754cab42b9c/aiohttp-3.12.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8466151554b593909d30a0a125d638b4e5f3836e5aecde85b66b80ded1cb5b0d", size = 469787, upload-time = "2025-07-29T05:50:49.669Z" }, + { url = "https://files.pythonhosted.org/packages/38/7d/b76438e70319796bfff717f325d97ce2e9310f752a267bfdf5192ac6082b/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e5a495cb1be69dae4b08f35a6c4579c539e9b5706f606632102c0f855bcba7c", size = 1716590, upload-time = "2025-07-29T05:50:51.368Z" }, + { url = "https://files.pythonhosted.org/packages/79/b1/60370d70cdf8b269ee1444b390cbd72ce514f0d1cd1a715821c784d272c9/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6404dfc8cdde35c69aaa489bb3542fb86ef215fc70277c892be8af540e5e21c0", size = 1699241, upload-time = "2025-07-29T05:50:53.628Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2b/4968a7b8792437ebc12186db31523f541943e99bda8f30335c482bea6879/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ead1c00f8521a5c9070fcb88f02967b1d8a0544e6d85c253f6968b785e1a2ab", size = 1754335, upload-time = "2025-07-29T05:50:55.394Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c1/49524ed553f9a0bec1a11fac09e790f49ff669bcd14164f9fab608831c4d/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6990ef617f14450bc6b34941dba4f12d5613cbf4e33805932f853fbd1cf18bfb", size = 1800491, upload-time = "2025-07-29T05:50:57.202Z" }, + { url = "https://files.pythonhosted.org/packages/de/5e/3bf5acea47a96a28c121b167f5ef659cf71208b19e52a88cdfa5c37f1fcc/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd736ed420f4db2b8148b52b46b88ed038d0354255f9a73196b7bbce3ea97545", size = 1719929, upload-time = "2025-07-29T05:50:59.192Z" }, + { url = "https://files.pythonhosted.org/packages/39/94/8ae30b806835bcd1cba799ba35347dee6961a11bd507db634516210e91d8/aiohttp-3.12.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c5092ce14361a73086b90c6efb3948ffa5be2f5b6fbcf52e8d8c8b8848bb97c", size = 1635733, upload-time = "2025-07-29T05:51:01.394Z" }, + { url = "https://files.pythonhosted.org/packages/7a/46/06cdef71dd03acd9da7f51ab3a9107318aee12ad38d273f654e4f981583a/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:aaa2234bb60c4dbf82893e934d8ee8dea30446f0647e024074237a56a08c01bd", size = 1696790, upload-time = "2025-07-29T05:51:03.657Z" }, + { url = "https://files.pythonhosted.org/packages/02/90/6b4cfaaf92ed98d0ec4d173e78b99b4b1a7551250be8937d9d67ecb356b4/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6d86a2fbdd14192e2f234a92d3b494dd4457e683ba07e5905a0b3ee25389ac9f", size = 1718245, upload-time = "2025-07-29T05:51:05.911Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e6/2593751670fa06f080a846f37f112cbe6f873ba510d070136a6ed46117c6/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a041e7e2612041a6ddf1c6a33b883be6a421247c7afd47e885969ee4cc58bd8d", size = 1658899, upload-time = "2025-07-29T05:51:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/8f/28/c15bacbdb8b8eb5bf39b10680d129ea7410b859e379b03190f02fa104ffd/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5015082477abeafad7203757ae44299a610e89ee82a1503e3d4184e6bafdd519", size = 1738459, upload-time = "2025-07-29T05:51:09.56Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/c269cbc4faa01fb10f143b1670633a8ddd5b2e1ffd0548f7aa49cb5c70e2/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56822ff5ddfd1b745534e658faba944012346184fbfe732e0d6134b744516eea", size = 1766434, upload-time = "2025-07-29T05:51:11.423Z" }, + { url = "https://files.pythonhosted.org/packages/52/b0/4ff3abd81aa7d929b27d2e1403722a65fc87b763e3a97b3a2a494bfc63bc/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2acbbfff69019d9014508c4ba0401822e8bae5a5fdc3b6814285b71231b60f3", size = 1726045, upload-time = "2025-07-29T05:51:13.689Z" }, + { url = "https://files.pythonhosted.org/packages/71/16/949225a6a2dd6efcbd855fbd90cf476052e648fb011aa538e3b15b89a57a/aiohttp-3.12.15-cp312-cp312-win32.whl", hash = "sha256:d849b0901b50f2185874b9a232f38e26b9b3d4810095a7572eacea939132d4e1", size = 423591, upload-time = "2025-07-29T05:51:15.452Z" }, + { url = "https://files.pythonhosted.org/packages/2b/d8/fa65d2a349fe938b76d309db1a56a75c4fb8cc7b17a398b698488a939903/aiohttp-3.12.15-cp312-cp312-win_amd64.whl", hash = "sha256:b390ef5f62bb508a9d67cb3bba9b8356e23b3996da7062f1a57ce1a79d2b3d34", size = 450266, upload-time = "2025-07-29T05:51:17.239Z" }, + { url = "https://files.pythonhosted.org/packages/f2/33/918091abcf102e39d15aba2476ad9e7bd35ddb190dcdd43a854000d3da0d/aiohttp-3.12.15-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9f922ffd05034d439dde1c77a20461cf4a1b0831e6caa26151fe7aa8aaebc315", size = 696741, upload-time = "2025-07-29T05:51:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2a/7495a81e39a998e400f3ecdd44a62107254803d1681d9189be5c2e4530cd/aiohttp-3.12.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2ee8a8ac39ce45f3e55663891d4b1d15598c157b4d494a4613e704c8b43112cd", size = 474407, upload-time = "2025-07-29T05:51:21.165Z" }, + { url = "https://files.pythonhosted.org/packages/49/fc/a9576ab4be2dcbd0f73ee8675d16c707cfc12d5ee80ccf4015ba543480c9/aiohttp-3.12.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3eae49032c29d356b94eee45a3f39fdf4b0814b397638c2f718e96cfadf4c4e4", size = 466703, upload-time = "2025-07-29T05:51:22.948Z" }, + { url = "https://files.pythonhosted.org/packages/09/2f/d4bcc8448cf536b2b54eed48f19682031ad182faa3a3fee54ebe5b156387/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97752ff12cc12f46a9b20327104448042fce5c33a624f88c18f66f9368091c7", size = 1705532, upload-time = "2025-07-29T05:51:25.211Z" }, + { url = "https://files.pythonhosted.org/packages/f1/f3/59406396083f8b489261e3c011aa8aee9df360a96ac8fa5c2e7e1b8f0466/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:894261472691d6fe76ebb7fcf2e5870a2ac284c7406ddc95823c8598a1390f0d", size = 1686794, upload-time = "2025-07-29T05:51:27.145Z" }, + { url = "https://files.pythonhosted.org/packages/dc/71/164d194993a8d114ee5656c3b7ae9c12ceee7040d076bf7b32fb98a8c5c6/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5fa5d9eb82ce98959fc1031c28198b431b4d9396894f385cb63f1e2f3f20ca6b", size = 1738865, upload-time = "2025-07-29T05:51:29.366Z" }, + { url = "https://files.pythonhosted.org/packages/1c/00/d198461b699188a93ead39cb458554d9f0f69879b95078dce416d3209b54/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0fa751efb11a541f57db59c1dd821bec09031e01452b2b6217319b3a1f34f3d", size = 1788238, upload-time = "2025-07-29T05:51:31.285Z" }, + { url = "https://files.pythonhosted.org/packages/85/b8/9e7175e1fa0ac8e56baa83bf3c214823ce250d0028955dfb23f43d5e61fd/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5346b93e62ab51ee2a9d68e8f73c7cf96ffb73568a23e683f931e52450e4148d", size = 1710566, upload-time = "2025-07-29T05:51:33.219Z" }, + { url = "https://files.pythonhosted.org/packages/59/e4/16a8eac9df39b48ae102ec030fa9f726d3570732e46ba0c592aeeb507b93/aiohttp-3.12.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:049ec0360f939cd164ecbfd2873eaa432613d5e77d6b04535e3d1fbae5a9e645", size = 1624270, upload-time = "2025-07-29T05:51:35.195Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f8/cd84dee7b6ace0740908fd0af170f9fab50c2a41ccbc3806aabcb1050141/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b52dcf013b57464b6d1e51b627adfd69a8053e84b7103a7cd49c030f9ca44461", size = 1677294, upload-time = "2025-07-29T05:51:37.215Z" }, + { url = "https://files.pythonhosted.org/packages/ce/42/d0f1f85e50d401eccd12bf85c46ba84f947a84839c8a1c2c5f6e8ab1eb50/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:9b2af240143dd2765e0fb661fd0361a1b469cab235039ea57663cda087250ea9", size = 1708958, upload-time = "2025-07-29T05:51:39.328Z" }, + { url = "https://files.pythonhosted.org/packages/d5/6b/f6fa6c5790fb602538483aa5a1b86fcbad66244997e5230d88f9412ef24c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ac77f709a2cde2cc71257ab2d8c74dd157c67a0558a0d2799d5d571b4c63d44d", size = 1651553, upload-time = "2025-07-29T05:51:41.356Z" }, + { url = "https://files.pythonhosted.org/packages/04/36/a6d36ad545fa12e61d11d1932eef273928b0495e6a576eb2af04297fdd3c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:47f6b962246f0a774fbd3b6b7be25d59b06fdb2f164cf2513097998fc6a29693", size = 1727688, upload-time = "2025-07-29T05:51:43.452Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c8/f195e5e06608a97a4e52c5d41c7927301bf757a8e8bb5bbf8cef6c314961/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:760fb7db442f284996e39cf9915a94492e1896baac44f06ae551974907922b64", size = 1761157, upload-time = "2025-07-29T05:51:45.643Z" }, + { url = "https://files.pythonhosted.org/packages/05/6a/ea199e61b67f25ba688d3ce93f63b49b0a4e3b3d380f03971b4646412fc6/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad702e57dc385cae679c39d318def49aef754455f237499d5b99bea4ef582e51", size = 1710050, upload-time = "2025-07-29T05:51:48.203Z" }, + { url = "https://files.pythonhosted.org/packages/b4/2e/ffeb7f6256b33635c29dbed29a22a723ff2dd7401fff42ea60cf2060abfb/aiohttp-3.12.15-cp313-cp313-win32.whl", hash = "sha256:f813c3e9032331024de2eb2e32a88d86afb69291fbc37a3a3ae81cc9917fb3d0", size = 422647, upload-time = "2025-07-29T05:51:50.718Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8e/78ee35774201f38d5e1ba079c9958f7629b1fd079459aea9467441dbfbf5/aiohttp-3.12.15-cp313-cp313-win_amd64.whl", hash = "sha256:1a649001580bdb37c6fdb1bebbd7e3bc688e8ec2b5c6f52edbb664662b17dc84", size = 449067, upload-time = "2025-07-29T05:51:52.549Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + +[[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 = "anyio" +version = "4.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252, upload-time = "2025-08-04T08:54:26.451Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" }, +] + +[[package]] +name = "attrs" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, +] + +[[package]] +name = "bidict" +version = "0.23.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/6e/026678aa5a830e07cd9498a05d3e7e650a4f56a42f267a53d22bcda1bdc9/bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71", size = 29093, upload-time = "2024-02-18T19:09:05.748Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5", size = 32764, upload-time = "2024-02-18T19:09:04.156Z" }, +] + +[[package]] +name = "certifi" +version = "2025.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, +] + +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, +] + +[[package]] +name = "code-jam-template" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "nicegui" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pre-commit" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [{ name = "nicegui", specifier = ">=2.22.2" }] + +[package.metadata.requires-dev] +dev = [ + { name = "pre-commit", specifier = "~=4.2.0" }, + { name = "ruff", specifier = "~=0.12.2" }, +] + +[[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 = "distlib" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, +] + +[[package]] +name = "docutils" +version = "0.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e9/86/5b41c32ecedcfdb4c77b28b6cb14234f252075f8cdb254531727a35547dd/docutils-0.22.tar.gz", hash = "sha256:ba9d57750e92331ebe7c08a1bbf7a7f8143b86c476acd51528b042216a6aad0f", size = 2277984, upload-time = "2025-07-29T15:20:31.06Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/57/8db39bc5f98f042e0153b1de9fb88e1a409a33cda4dd7f723c2ed71e01f6/docutils-0.22-py3-none-any.whl", hash = "sha256:4ed966a0e96a0477d852f7af31bdcb3adc049fbb35ccba358c2ea8a03287615e", size = 630709, upload-time = "2025-07-29T15:20:28.335Z" }, +] + +[[package]] +name = "fastapi" +version = "0.116.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/d7/6c8b3bfe33eeffa208183ec037fee0cce9f7f024089ab1c5d12ef04bd27c/fastapi-0.116.1.tar.gz", hash = "sha256:ed52cbf946abfd70c5a0dccb24673f0670deeb517a88b3544d03c2a6bf283143", size = 296485, upload-time = "2025-07-11T16:22:32.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/47/d63c60f59a59467fda0f93f46335c9d18526d7071f025cb5b89d5353ea42/fastapi-0.116.1-py3-none-any.whl", hash = "sha256:c46ac7c312df840f0c9e220f7964bada936781bc4e2e6eb71f1c4d7553786565", size = 95631, upload-time = "2025-07-11T16:22:30.485Z" }, +] + +[[package]] +name = "filelock" +version = "3.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/b1/b64018016eeb087db503b038296fd782586432b9c077fc5c7839e9cb6ef6/frozenlist-1.7.0.tar.gz", hash = "sha256:2e310d81923c2437ea8670467121cc3e9b0f76d3043cc1d2331d56c7fb7a3a8f", size = 45078, upload-time = "2025-06-09T23:02:35.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a2/c8131383f1e66adad5f6ecfcce383d584ca94055a34d683bbb24ac5f2f1c/frozenlist-1.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3dbf9952c4bb0e90e98aec1bd992b3318685005702656bc6f67c1a32b76787f2", size = 81424, upload-time = "2025-06-09T23:00:42.24Z" }, + { url = "https://files.pythonhosted.org/packages/4c/9d/02754159955088cb52567337d1113f945b9e444c4960771ea90eb73de8db/frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f5906d3359300b8a9bb194239491122e6cf1444c2efb88865426f170c262cdb", size = 47952, upload-time = "2025-06-09T23:00:43.481Z" }, + { url = "https://files.pythonhosted.org/packages/01/7a/0046ef1bd6699b40acd2067ed6d6670b4db2f425c56980fa21c982c2a9db/frozenlist-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3dabd5a8f84573c8d10d8859a50ea2dec01eea372031929871368c09fa103478", size = 46688, upload-time = "2025-06-09T23:00:44.793Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a2/a910bafe29c86997363fb4c02069df4ff0b5bc39d33c5198b4e9dd42d8f8/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa57daa5917f1738064f302bf2626281a1cb01920c32f711fbc7bc36111058a8", size = 243084, upload-time = "2025-06-09T23:00:46.125Z" }, + { url = "https://files.pythonhosted.org/packages/64/3e/5036af9d5031374c64c387469bfcc3af537fc0f5b1187d83a1cf6fab1639/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c193dda2b6d49f4c4398962810fa7d7c78f032bf45572b3e04dd5249dff27e08", size = 233524, upload-time = "2025-06-09T23:00:47.73Z" }, + { url = "https://files.pythonhosted.org/packages/06/39/6a17b7c107a2887e781a48ecf20ad20f1c39d94b2a548c83615b5b879f28/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe2b675cf0aaa6d61bf8fbffd3c274b3c9b7b1623beb3809df8a81399a4a9c4", size = 248493, upload-time = "2025-06-09T23:00:49.742Z" }, + { url = "https://files.pythonhosted.org/packages/be/00/711d1337c7327d88c44d91dd0f556a1c47fb99afc060ae0ef66b4d24793d/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8fc5d5cda37f62b262405cf9652cf0856839c4be8ee41be0afe8858f17f4c94b", size = 244116, upload-time = "2025-06-09T23:00:51.352Z" }, + { url = "https://files.pythonhosted.org/packages/24/fe/74e6ec0639c115df13d5850e75722750adabdc7de24e37e05a40527ca539/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d5ce521d1dd7d620198829b87ea002956e4319002ef0bc8d3e6d045cb4646e", size = 224557, upload-time = "2025-06-09T23:00:52.855Z" }, + { url = "https://files.pythonhosted.org/packages/8d/db/48421f62a6f77c553575201e89048e97198046b793f4a089c79a6e3268bd/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488d0a7d6a0008ca0db273c542098a0fa9e7dfaa7e57f70acef43f32b3f69dca", size = 241820, upload-time = "2025-06-09T23:00:54.43Z" }, + { url = "https://files.pythonhosted.org/packages/1d/fa/cb4a76bea23047c8462976ea7b7a2bf53997a0ca171302deae9d6dd12096/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:15a7eaba63983d22c54d255b854e8108e7e5f3e89f647fc854bd77a237e767df", size = 236542, upload-time = "2025-06-09T23:00:56.409Z" }, + { url = "https://files.pythonhosted.org/packages/5d/32/476a4b5cfaa0ec94d3f808f193301debff2ea42288a099afe60757ef6282/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1eaa7e9c6d15df825bf255649e05bd8a74b04a4d2baa1ae46d9c2d00b2ca2cb5", size = 249350, upload-time = "2025-06-09T23:00:58.468Z" }, + { url = "https://files.pythonhosted.org/packages/8d/ba/9a28042f84a6bf8ea5dbc81cfff8eaef18d78b2a1ad9d51c7bc5b029ad16/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4389e06714cfa9d47ab87f784a7c5be91d3934cd6e9a7b85beef808297cc025", size = 225093, upload-time = "2025-06-09T23:01:00.015Z" }, + { url = "https://files.pythonhosted.org/packages/bc/29/3a32959e68f9cf000b04e79ba574527c17e8842e38c91d68214a37455786/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:73bd45e1488c40b63fe5a7df892baf9e2a4d4bb6409a2b3b78ac1c6236178e01", size = 245482, upload-time = "2025-06-09T23:01:01.474Z" }, + { url = "https://files.pythonhosted.org/packages/80/e8/edf2f9e00da553f07f5fa165325cfc302dead715cab6ac8336a5f3d0adc2/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99886d98e1643269760e5fe0df31e5ae7050788dd288947f7f007209b8c33f08", size = 249590, upload-time = "2025-06-09T23:01:02.961Z" }, + { url = "https://files.pythonhosted.org/packages/1c/80/9a0eb48b944050f94cc51ee1c413eb14a39543cc4f760ed12657a5a3c45a/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:290a172aae5a4c278c6da8a96222e6337744cd9c77313efe33d5670b9f65fc43", size = 237785, upload-time = "2025-06-09T23:01:05.095Z" }, + { url = "https://files.pythonhosted.org/packages/f3/74/87601e0fb0369b7a2baf404ea921769c53b7ae00dee7dcfe5162c8c6dbf0/frozenlist-1.7.0-cp312-cp312-win32.whl", hash = "sha256:426c7bc70e07cfebc178bc4c2bf2d861d720c4fff172181eeb4a4c41d4ca2ad3", size = 39487, upload-time = "2025-06-09T23:01:06.54Z" }, + { url = "https://files.pythonhosted.org/packages/0b/15/c026e9a9fc17585a9d461f65d8593d281fedf55fbf7eb53f16c6df2392f9/frozenlist-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:563b72efe5da92e02eb68c59cb37205457c977aa7a449ed1b37e6939e5c47c6a", size = 43874, upload-time = "2025-06-09T23:01:07.752Z" }, + { url = "https://files.pythonhosted.org/packages/24/90/6b2cebdabdbd50367273c20ff6b57a3dfa89bd0762de02c3a1eb42cb6462/frozenlist-1.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee80eeda5e2a4e660651370ebffd1286542b67e268aa1ac8d6dbe973120ef7ee", size = 79791, upload-time = "2025-06-09T23:01:09.368Z" }, + { url = "https://files.pythonhosted.org/packages/83/2e/5b70b6a3325363293fe5fc3ae74cdcbc3e996c2a11dde2fd9f1fb0776d19/frozenlist-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d1a81c85417b914139e3a9b995d4a1c84559afc839a93cf2cb7f15e6e5f6ed2d", size = 47165, upload-time = "2025-06-09T23:01:10.653Z" }, + { url = "https://files.pythonhosted.org/packages/f4/25/a0895c99270ca6966110f4ad98e87e5662eab416a17e7fd53c364bf8b954/frozenlist-1.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cbb65198a9132ebc334f237d7b0df163e4de83fb4f2bdfe46c1e654bdb0c5d43", size = 45881, upload-time = "2025-06-09T23:01:12.296Z" }, + { url = "https://files.pythonhosted.org/packages/19/7c/71bb0bbe0832793c601fff68cd0cf6143753d0c667f9aec93d3c323f4b55/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dab46c723eeb2c255a64f9dc05b8dd601fde66d6b19cdb82b2e09cc6ff8d8b5d", size = 232409, upload-time = "2025-06-09T23:01:13.641Z" }, + { url = "https://files.pythonhosted.org/packages/c0/45/ed2798718910fe6eb3ba574082aaceff4528e6323f9a8570be0f7028d8e9/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6aeac207a759d0dedd2e40745575ae32ab30926ff4fa49b1635def65806fddee", size = 225132, upload-time = "2025-06-09T23:01:15.264Z" }, + { url = "https://files.pythonhosted.org/packages/ba/e2/8417ae0f8eacb1d071d4950f32f229aa6bf68ab69aab797b72a07ea68d4f/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bd8c4e58ad14b4fa7802b8be49d47993182fdd4023393899632c88fd8cd994eb", size = 237638, upload-time = "2025-06-09T23:01:16.752Z" }, + { url = "https://files.pythonhosted.org/packages/f8/b7/2ace5450ce85f2af05a871b8c8719b341294775a0a6c5585d5e6170f2ce7/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04fb24d104f425da3540ed83cbfc31388a586a7696142004c577fa61c6298c3f", size = 233539, upload-time = "2025-06-09T23:01:18.202Z" }, + { url = "https://files.pythonhosted.org/packages/46/b9/6989292c5539553dba63f3c83dc4598186ab2888f67c0dc1d917e6887db6/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a5c505156368e4ea6b53b5ac23c92d7edc864537ff911d2fb24c140bb175e60", size = 215646, upload-time = "2025-06-09T23:01:19.649Z" }, + { url = "https://files.pythonhosted.org/packages/72/31/bc8c5c99c7818293458fe745dab4fd5730ff49697ccc82b554eb69f16a24/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bd7eb96a675f18aa5c553eb7ddc24a43c8c18f22e1f9925528128c052cdbe00", size = 232233, upload-time = "2025-06-09T23:01:21.175Z" }, + { url = "https://files.pythonhosted.org/packages/59/52/460db4d7ba0811b9ccb85af996019f5d70831f2f5f255f7cc61f86199795/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:05579bf020096fe05a764f1f84cd104a12f78eaab68842d036772dc6d4870b4b", size = 227996, upload-time = "2025-06-09T23:01:23.098Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c9/f4b39e904c03927b7ecf891804fd3b4df3db29b9e487c6418e37988d6e9d/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:376b6222d114e97eeec13d46c486facd41d4f43bab626b7c3f6a8b4e81a5192c", size = 242280, upload-time = "2025-06-09T23:01:24.808Z" }, + { url = "https://files.pythonhosted.org/packages/b8/33/3f8d6ced42f162d743e3517781566b8481322be321b486d9d262adf70bfb/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0aa7e176ebe115379b5b1c95b4096fb1c17cce0847402e227e712c27bdb5a949", size = 217717, upload-time = "2025-06-09T23:01:26.28Z" }, + { url = "https://files.pythonhosted.org/packages/3e/e8/ad683e75da6ccef50d0ab0c2b2324b32f84fc88ceee778ed79b8e2d2fe2e/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3fbba20e662b9c2130dc771e332a99eff5da078b2b2648153a40669a6d0e36ca", size = 236644, upload-time = "2025-06-09T23:01:27.887Z" }, + { url = "https://files.pythonhosted.org/packages/b2/14/8d19ccdd3799310722195a72ac94ddc677541fb4bef4091d8e7775752360/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f3f4410a0a601d349dd406b5713fec59b4cee7e71678d5b17edda7f4655a940b", size = 238879, upload-time = "2025-06-09T23:01:29.524Z" }, + { url = "https://files.pythonhosted.org/packages/ce/13/c12bf657494c2fd1079a48b2db49fa4196325909249a52d8f09bc9123fd7/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e2cdfaaec6a2f9327bf43c933c0319a7c429058e8537c508964a133dffee412e", size = 232502, upload-time = "2025-06-09T23:01:31.287Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8b/e7f9dfde869825489382bc0d512c15e96d3964180c9499efcec72e85db7e/frozenlist-1.7.0-cp313-cp313-win32.whl", hash = "sha256:5fc4df05a6591c7768459caba1b342d9ec23fa16195e744939ba5914596ae3e1", size = 39169, upload-time = "2025-06-09T23:01:35.503Z" }, + { url = "https://files.pythonhosted.org/packages/35/89/a487a98d94205d85745080a37860ff5744b9820a2c9acbcdd9440bfddf98/frozenlist-1.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:52109052b9791a3e6b5d1b65f4b909703984b770694d3eb64fad124c835d7cba", size = 43219, upload-time = "2025-06-09T23:01:36.784Z" }, + { url = "https://files.pythonhosted.org/packages/56/d5/5c4cf2319a49eddd9dd7145e66c4866bdc6f3dbc67ca3d59685149c11e0d/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a6f86e4193bb0e235ef6ce3dde5cbabed887e0b11f516ce8a0f4d3b33078ec2d", size = 84345, upload-time = "2025-06-09T23:01:38.295Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/ec2c1e1dc16b85bc9d526009961953df9cec8481b6886debb36ec9107799/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:82d664628865abeb32d90ae497fb93df398a69bb3434463d172b80fc25b0dd7d", size = 48880, upload-time = "2025-06-09T23:01:39.887Z" }, + { url = "https://files.pythonhosted.org/packages/69/86/f9596807b03de126e11e7d42ac91e3d0b19a6599c714a1989a4e85eeefc4/frozenlist-1.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:912a7e8375a1c9a68325a902f3953191b7b292aa3c3fb0d71a216221deca460b", size = 48498, upload-time = "2025-06-09T23:01:41.318Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cb/df6de220f5036001005f2d726b789b2c0b65f2363b104bbc16f5be8084f8/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9537c2777167488d539bc5de2ad262efc44388230e5118868e172dd4a552b146", size = 292296, upload-time = "2025-06-09T23:01:42.685Z" }, + { url = "https://files.pythonhosted.org/packages/83/1f/de84c642f17c8f851a2905cee2dae401e5e0daca9b5ef121e120e19aa825/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f34560fb1b4c3e30ba35fa9a13894ba39e5acfc5f60f57d8accde65f46cc5e74", size = 273103, upload-time = "2025-06-09T23:01:44.166Z" }, + { url = "https://files.pythonhosted.org/packages/88/3c/c840bfa474ba3fa13c772b93070893c6e9d5c0350885760376cbe3b6c1b3/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:acd03d224b0175f5a850edc104ac19040d35419eddad04e7cf2d5986d98427f1", size = 292869, upload-time = "2025-06-09T23:01:45.681Z" }, + { url = "https://files.pythonhosted.org/packages/a6/1c/3efa6e7d5a39a1d5ef0abeb51c48fb657765794a46cf124e5aca2c7a592c/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2038310bc582f3d6a09b3816ab01737d60bf7b1ec70f5356b09e84fb7408ab1", size = 291467, upload-time = "2025-06-09T23:01:47.234Z" }, + { url = "https://files.pythonhosted.org/packages/4f/00/d5c5e09d4922c395e2f2f6b79b9a20dab4b67daaf78ab92e7729341f61f6/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8c05e4c8e5f36e5e088caa1bf78a687528f83c043706640a92cb76cd6999384", size = 266028, upload-time = "2025-06-09T23:01:48.819Z" }, + { url = "https://files.pythonhosted.org/packages/4e/27/72765be905619dfde25a7f33813ac0341eb6b076abede17a2e3fbfade0cb/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:765bb588c86e47d0b68f23c1bee323d4b703218037765dcf3f25c838c6fecceb", size = 284294, upload-time = "2025-06-09T23:01:50.394Z" }, + { url = "https://files.pythonhosted.org/packages/88/67/c94103a23001b17808eb7dd1200c156bb69fb68e63fcf0693dde4cd6228c/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:32dc2e08c67d86d0969714dd484fd60ff08ff81d1a1e40a77dd34a387e6ebc0c", size = 281898, upload-time = "2025-06-09T23:01:52.234Z" }, + { url = "https://files.pythonhosted.org/packages/42/34/a3e2c00c00f9e2a9db5653bca3fec306349e71aff14ae45ecc6d0951dd24/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:c0303e597eb5a5321b4de9c68e9845ac8f290d2ab3f3e2c864437d3c5a30cd65", size = 290465, upload-time = "2025-06-09T23:01:53.788Z" }, + { url = "https://files.pythonhosted.org/packages/bb/73/f89b7fbce8b0b0c095d82b008afd0590f71ccb3dee6eee41791cf8cd25fd/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a47f2abb4e29b3a8d0b530f7c3598badc6b134562b1a5caee867f7c62fee51e3", size = 266385, upload-time = "2025-06-09T23:01:55.769Z" }, + { url = "https://files.pythonhosted.org/packages/cd/45/e365fdb554159462ca12df54bc59bfa7a9a273ecc21e99e72e597564d1ae/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3d688126c242a6fabbd92e02633414d40f50bb6002fa4cf995a1d18051525657", size = 288771, upload-time = "2025-06-09T23:01:57.4Z" }, + { url = "https://files.pythonhosted.org/packages/00/11/47b6117002a0e904f004d70ec5194fe9144f117c33c851e3d51c765962d0/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:4e7e9652b3d367c7bd449a727dc79d5043f48b88d0cbfd4f9f1060cf2b414104", size = 288206, upload-time = "2025-06-09T23:01:58.936Z" }, + { url = "https://files.pythonhosted.org/packages/40/37/5f9f3c3fd7f7746082ec67bcdc204db72dad081f4f83a503d33220a92973/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1a85e345b4c43db8b842cab1feb41be5cc0b10a1830e6295b69d7310f99becaf", size = 282620, upload-time = "2025-06-09T23:02:00.493Z" }, + { url = "https://files.pythonhosted.org/packages/0b/31/8fbc5af2d183bff20f21aa743b4088eac4445d2bb1cdece449ae80e4e2d1/frozenlist-1.7.0-cp313-cp313t-win32.whl", hash = "sha256:3a14027124ddb70dfcee5148979998066897e79f89f64b13328595c4bdf77c81", size = 43059, upload-time = "2025-06-09T23:02:02.072Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ed/41956f52105b8dbc26e457c5705340c67c8cc2b79f394b79bffc09d0e938/frozenlist-1.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3bf8010d71d4507775f658e9823210b7427be36625b387221642725b515dcf3e", size = 47516, upload-time = "2025-06-09T23:02:03.779Z" }, + { url = "https://files.pythonhosted.org/packages/ee/45/b82e3c16be2182bff01179db177fe144d58b5dc787a7d4492c6ed8b9317f/frozenlist-1.7.0-py3-none-any.whl", hash = "sha256:9a5af342e34f7e97caf8c995864c7a396418ae2859cc6fdf1b1073020d516a7e", size = 13106, upload-time = "2025-06-09T23:02:34.204Z" }, +] + +[[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 = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httptools" +version = "0.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639, upload-time = "2024-10-16T19:45:08.902Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683, upload-time = "2024-10-16T19:44:30.175Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337, upload-time = "2024-10-16T19:44:31.786Z" }, + { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796, upload-time = "2024-10-16T19:44:32.825Z" }, + { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837, upload-time = "2024-10-16T19:44:33.974Z" }, + { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289, upload-time = "2024-10-16T19:44:35.111Z" }, + { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779, upload-time = "2024-10-16T19:44:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634, upload-time = "2024-10-16T19:44:37.357Z" }, + { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214, upload-time = "2024-10-16T19:44:38.738Z" }, + { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431, upload-time = "2024-10-16T19:44:39.818Z" }, + { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121, upload-time = "2024-10-16T19:44:41.189Z" }, + { url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805, upload-time = "2024-10-16T19:44:42.384Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858, upload-time = "2024-10-16T19:44:43.959Z" }, + { url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042, upload-time = "2024-10-16T19:44:45.071Z" }, + { url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682, upload-time = "2024-10-16T19:44:46.46Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "identify" +version = "2.6.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ca/ffbabe3635bb839aa36b3a893c91a9b0d368cb4d8073e03a12896970af82/identify-2.6.13.tar.gz", hash = "sha256:da8d6c828e773620e13bfa86ea601c5a5310ba4bcd65edf378198b56a1f9fb32", size = 99243, upload-time = "2025-08-09T19:35:00.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/ce/461b60a3ee109518c055953729bf9ed089a04db895d47e95444071dcdef2/identify-2.6.13-py2.py3-none-any.whl", hash = "sha256:60381139b3ae39447482ecc406944190f690d4a2997f2584062089848361b33b", size = 99153, upload-time = "2025-08-09T19:34:59.1Z" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "ifaddr" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/ac/fb4c578f4a3256561548cd825646680edcadb9440f3f68add95ade1eb791/ifaddr-0.2.0.tar.gz", hash = "sha256:cc0cbfcaabf765d44595825fb96a99bb12c79716b73b44330ea38ee2b0c4aed4", size = 10485, upload-time = "2022-06-15T21:40:27.561Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/1f/19ebc343cc71a7ffa78f17018535adc5cbdd87afb31d7c34874680148b32/ifaddr-0.2.0-py3-none-any.whl", hash = "sha256:085e0305cfe6f16ab12d72e2024030f5d52674afad6911bb1eee207177b8a748", size = 12314, upload-time = "2022-06-15T21:40:25.756Z" }, +] + +[[package]] +name = "itsdangerous" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, +] + +[[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 = "markdown2" +version = "2.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/42/f8/b2ae8bf5f28f9b510ae097415e6e4cb63226bb28d7ee01aec03a755ba03b/markdown2-2.5.4.tar.gz", hash = "sha256:a09873f0b3c23dbfae589b0080587df52ad75bb09a5fa6559147554736676889", size = 145652, upload-time = "2025-07-27T16:16:24.307Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/06/2697b5043c3ecb720ce0d243fc7cf5024c0b5b1e450506e9b21939019963/markdown2-2.5.4-py3-none-any.whl", hash = "sha256:3c4b2934e677be7fec0e6f2de4410e116681f4ad50ec8e5ba7557be506d3f439", size = 49954, upload-time = "2025-07-27T16:16:23.026Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, +] + +[[package]] +name = "multidict" +version = "6.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3d/2c/5dad12e82fbdf7470f29bff2171484bf07cb3b16ada60a6589af8f376440/multidict-6.6.3.tar.gz", hash = "sha256:798a9eb12dab0a6c2e29c1de6f3468af5cb2da6053a20dfa3344907eed0937cc", size = 101006, upload-time = "2025-06-30T15:53:46.929Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/a0/6b57988ea102da0623ea814160ed78d45a2645e4bbb499c2896d12833a70/multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:056bebbeda16b2e38642d75e9e5310c484b7c24e3841dc0fb943206a72ec89d6", size = 76514, upload-time = "2025-06-30T15:51:48.728Z" }, + { url = "https://files.pythonhosted.org/packages/07/7a/d1e92665b0850c6c0508f101f9cf0410c1afa24973e1115fe9c6a185ebf7/multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e5f481cccb3c5c5e5de5d00b5141dc589c1047e60d07e85bbd7dea3d4580d63f", size = 45394, upload-time = "2025-06-30T15:51:49.986Z" }, + { url = "https://files.pythonhosted.org/packages/52/6f/dd104490e01be6ef8bf9573705d8572f8c2d2c561f06e3826b081d9e6591/multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:10bea2ee839a759ee368b5a6e47787f399b41e70cf0c20d90dfaf4158dfb4e55", size = 43590, upload-time = "2025-06-30T15:51:51.331Z" }, + { url = "https://files.pythonhosted.org/packages/44/fe/06e0e01b1b0611e6581b7fd5a85b43dacc08b6cea3034f902f383b0873e5/multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:2334cfb0fa9549d6ce2c21af2bfbcd3ac4ec3646b1b1581c88e3e2b1779ec92b", size = 237292, upload-time = "2025-06-30T15:51:52.584Z" }, + { url = "https://files.pythonhosted.org/packages/ce/71/4f0e558fb77696b89c233c1ee2d92f3e1d5459070a0e89153c9e9e804186/multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8fee016722550a2276ca2cb5bb624480e0ed2bd49125b2b73b7010b9090e888", size = 258385, upload-time = "2025-06-30T15:51:53.913Z" }, + { url = "https://files.pythonhosted.org/packages/e3/25/cca0e68228addad24903801ed1ab42e21307a1b4b6dd2cf63da5d3ae082a/multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5511cb35f5c50a2db21047c875eb42f308c5583edf96bd8ebf7d770a9d68f6d", size = 242328, upload-time = "2025-06-30T15:51:55.672Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a3/46f2d420d86bbcb8fe660b26a10a219871a0fbf4d43cb846a4031533f3e0/multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:712b348f7f449948e0a6c4564a21c7db965af900973a67db432d724619b3c680", size = 268057, upload-time = "2025-06-30T15:51:57.037Z" }, + { url = "https://files.pythonhosted.org/packages/9e/73/1c743542fe00794a2ec7466abd3f312ccb8fad8dff9f36d42e18fb1ec33e/multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e4e15d2138ee2694e038e33b7c3da70e6b0ad8868b9f8094a72e1414aeda9c1a", size = 269341, upload-time = "2025-06-30T15:51:59.111Z" }, + { url = "https://files.pythonhosted.org/packages/a4/11/6ec9dcbe2264b92778eeb85407d1df18812248bf3506a5a1754bc035db0c/multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8df25594989aebff8a130f7899fa03cbfcc5d2b5f4a461cf2518236fe6f15961", size = 256081, upload-time = "2025-06-30T15:52:00.533Z" }, + { url = "https://files.pythonhosted.org/packages/9b/2b/631b1e2afeb5f1696846d747d36cda075bfdc0bc7245d6ba5c319278d6c4/multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:159ca68bfd284a8860f8d8112cf0521113bffd9c17568579e4d13d1f1dc76b65", size = 253581, upload-time = "2025-06-30T15:52:02.43Z" }, + { url = "https://files.pythonhosted.org/packages/bf/0e/7e3b93f79efeb6111d3bf9a1a69e555ba1d07ad1c11bceb56b7310d0d7ee/multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e098c17856a8c9ade81b4810888c5ad1914099657226283cab3062c0540b0643", size = 250750, upload-time = "2025-06-30T15:52:04.26Z" }, + { url = "https://files.pythonhosted.org/packages/ad/9e/086846c1d6601948e7de556ee464a2d4c85e33883e749f46b9547d7b0704/multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:67c92ed673049dec52d7ed39f8cf9ebbadf5032c774058b4406d18c8f8fe7063", size = 251548, upload-time = "2025-06-30T15:52:06.002Z" }, + { url = "https://files.pythonhosted.org/packages/8c/7b/86ec260118e522f1a31550e87b23542294880c97cfbf6fb18cc67b044c66/multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:bd0578596e3a835ef451784053cfd327d607fc39ea1a14812139339a18a0dbc3", size = 262718, upload-time = "2025-06-30T15:52:07.707Z" }, + { url = "https://files.pythonhosted.org/packages/8c/bd/22ce8f47abb0be04692c9fc4638508b8340987b18691aa7775d927b73f72/multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:346055630a2df2115cd23ae271910b4cae40f4e336773550dca4889b12916e75", size = 259603, upload-time = "2025-06-30T15:52:09.58Z" }, + { url = "https://files.pythonhosted.org/packages/07/9c/91b7ac1691be95cd1f4a26e36a74b97cda6aa9820632d31aab4410f46ebd/multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:555ff55a359302b79de97e0468e9ee80637b0de1fce77721639f7cd9440b3a10", size = 251351, upload-time = "2025-06-30T15:52:10.947Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5c/4d7adc739884f7a9fbe00d1eac8c034023ef8bad71f2ebe12823ca2e3649/multidict-6.6.3-cp312-cp312-win32.whl", hash = "sha256:73ab034fb8d58ff85c2bcbadc470efc3fafeea8affcf8722855fb94557f14cc5", size = 41860, upload-time = "2025-06-30T15:52:12.334Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a3/0fbc7afdf7cb1aa12a086b02959307848eb6bcc8f66fcb66c0cb57e2a2c1/multidict-6.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:04cbcce84f63b9af41bad04a54d4cc4e60e90c35b9e6ccb130be2d75b71f8c17", size = 45982, upload-time = "2025-06-30T15:52:13.6Z" }, + { url = "https://files.pythonhosted.org/packages/b8/95/8c825bd70ff9b02462dc18d1295dd08d3e9e4eb66856d292ffa62cfe1920/multidict-6.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:0f1130b896ecb52d2a1e615260f3ea2af55fa7dc3d7c3003ba0c3121a759b18b", size = 43210, upload-time = "2025-06-30T15:52:14.893Z" }, + { url = "https://files.pythonhosted.org/packages/52/1d/0bebcbbb4f000751fbd09957257903d6e002943fc668d841a4cf2fb7f872/multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:540d3c06d48507357a7d57721e5094b4f7093399a0106c211f33540fdc374d55", size = 75843, upload-time = "2025-06-30T15:52:16.155Z" }, + { url = "https://files.pythonhosted.org/packages/07/8f/cbe241b0434cfe257f65c2b1bcf9e8d5fb52bc708c5061fb29b0fed22bdf/multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9c19cea2a690f04247d43f366d03e4eb110a0dc4cd1bbeee4d445435428ed35b", size = 45053, upload-time = "2025-06-30T15:52:17.429Z" }, + { url = "https://files.pythonhosted.org/packages/32/d2/0b3b23f9dbad5b270b22a3ac3ea73ed0a50ef2d9a390447061178ed6bdb8/multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7af039820cfd00effec86bda5d8debef711a3e86a1d3772e85bea0f243a4bd65", size = 43273, upload-time = "2025-06-30T15:52:19.346Z" }, + { url = "https://files.pythonhosted.org/packages/fd/fe/6eb68927e823999e3683bc49678eb20374ba9615097d085298fd5b386564/multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:500b84f51654fdc3944e936f2922114349bf8fdcac77c3092b03449f0e5bc2b3", size = 237124, upload-time = "2025-06-30T15:52:20.773Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ab/320d8507e7726c460cb77117848b3834ea0d59e769f36fdae495f7669929/multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3fc723ab8a5c5ed6c50418e9bfcd8e6dceba6c271cee6728a10a4ed8561520c", size = 256892, upload-time = "2025-06-30T15:52:22.242Z" }, + { url = "https://files.pythonhosted.org/packages/76/60/38ee422db515ac69834e60142a1a69111ac96026e76e8e9aa347fd2e4591/multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:94c47ea3ade005b5976789baaed66d4de4480d0a0bf31cef6edaa41c1e7b56a6", size = 240547, upload-time = "2025-06-30T15:52:23.736Z" }, + { url = "https://files.pythonhosted.org/packages/27/fb/905224fde2dff042b030c27ad95a7ae744325cf54b890b443d30a789b80e/multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dbc7cf464cc6d67e83e136c9f55726da3a30176f020a36ead246eceed87f1cd8", size = 266223, upload-time = "2025-06-30T15:52:25.185Z" }, + { url = "https://files.pythonhosted.org/packages/76/35/dc38ab361051beae08d1a53965e3e1a418752fc5be4d3fb983c5582d8784/multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:900eb9f9da25ada070f8ee4a23f884e0ee66fe4e1a38c3af644256a508ad81ca", size = 267262, upload-time = "2025-06-30T15:52:26.969Z" }, + { url = "https://files.pythonhosted.org/packages/1f/a3/0a485b7f36e422421b17e2bbb5a81c1af10eac1d4476f2ff92927c730479/multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c6df517cf177da5d47ab15407143a89cd1a23f8b335f3a28d57e8b0a3dbb884", size = 254345, upload-time = "2025-06-30T15:52:28.467Z" }, + { url = "https://files.pythonhosted.org/packages/b4/59/bcdd52c1dab7c0e0d75ff19cac751fbd5f850d1fc39172ce809a74aa9ea4/multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4ef421045f13879e21c994b36e728d8e7d126c91a64b9185810ab51d474f27e7", size = 252248, upload-time = "2025-06-30T15:52:29.938Z" }, + { url = "https://files.pythonhosted.org/packages/bb/a4/2d96aaa6eae8067ce108d4acee6f45ced5728beda55c0f02ae1072c730d1/multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6c1e61bb4f80895c081790b6b09fa49e13566df8fbff817da3f85b3a8192e36b", size = 250115, upload-time = "2025-06-30T15:52:31.416Z" }, + { url = "https://files.pythonhosted.org/packages/25/d2/ed9f847fa5c7d0677d4f02ea2c163d5e48573de3f57bacf5670e43a5ffaa/multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e5e8523bb12d7623cd8300dbd91b9e439a46a028cd078ca695eb66ba31adee3c", size = 249649, upload-time = "2025-06-30T15:52:32.996Z" }, + { url = "https://files.pythonhosted.org/packages/1f/af/9155850372563fc550803d3f25373308aa70f59b52cff25854086ecb4a79/multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ef58340cc896219e4e653dade08fea5c55c6df41bcc68122e3be3e9d873d9a7b", size = 261203, upload-time = "2025-06-30T15:52:34.521Z" }, + { url = "https://files.pythonhosted.org/packages/36/2f/c6a728f699896252cf309769089568a33c6439626648843f78743660709d/multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc9dc435ec8699e7b602b94fe0cd4703e69273a01cbc34409af29e7820f777f1", size = 258051, upload-time = "2025-06-30T15:52:35.999Z" }, + { url = "https://files.pythonhosted.org/packages/d0/60/689880776d6b18fa2b70f6cc74ff87dd6c6b9b47bd9cf74c16fecfaa6ad9/multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9e864486ef4ab07db5e9cb997bad2b681514158d6954dd1958dfb163b83d53e6", size = 249601, upload-time = "2025-06-30T15:52:37.473Z" }, + { url = "https://files.pythonhosted.org/packages/75/5e/325b11f2222a549019cf2ef879c1f81f94a0d40ace3ef55cf529915ba6cc/multidict-6.6.3-cp313-cp313-win32.whl", hash = "sha256:5633a82fba8e841bc5c5c06b16e21529573cd654f67fd833650a215520a6210e", size = 41683, upload-time = "2025-06-30T15:52:38.927Z" }, + { url = "https://files.pythonhosted.org/packages/b1/ad/cf46e73f5d6e3c775cabd2a05976547f3f18b39bee06260369a42501f053/multidict-6.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:e93089c1570a4ad54c3714a12c2cef549dc9d58e97bcded193d928649cab78e9", size = 45811, upload-time = "2025-06-30T15:52:40.207Z" }, + { url = "https://files.pythonhosted.org/packages/c5/c9/2e3fe950db28fb7c62e1a5f46e1e38759b072e2089209bc033c2798bb5ec/multidict-6.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:c60b401f192e79caec61f166da9c924e9f8bc65548d4246842df91651e83d600", size = 43056, upload-time = "2025-06-30T15:52:41.575Z" }, + { url = "https://files.pythonhosted.org/packages/3a/58/aaf8114cf34966e084a8cc9517771288adb53465188843d5a19862cb6dc3/multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:02fd8f32d403a6ff13864b0851f1f523d4c988051eea0471d4f1fd8010f11134", size = 82811, upload-time = "2025-06-30T15:52:43.281Z" }, + { url = "https://files.pythonhosted.org/packages/71/af/5402e7b58a1f5b987a07ad98f2501fdba2a4f4b4c30cf114e3ce8db64c87/multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f3aa090106b1543f3f87b2041eef3c156c8da2aed90c63a2fbed62d875c49c37", size = 48304, upload-time = "2025-06-30T15:52:45.026Z" }, + { url = "https://files.pythonhosted.org/packages/39/65/ab3c8cafe21adb45b24a50266fd747147dec7847425bc2a0f6934b3ae9ce/multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e924fb978615a5e33ff644cc42e6aa241effcf4f3322c09d4f8cebde95aff5f8", size = 46775, upload-time = "2025-06-30T15:52:46.459Z" }, + { url = "https://files.pythonhosted.org/packages/49/ba/9fcc1b332f67cc0c0c8079e263bfab6660f87fe4e28a35921771ff3eea0d/multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:b9fe5a0e57c6dbd0e2ce81ca66272282c32cd11d31658ee9553849d91289e1c1", size = 229773, upload-time = "2025-06-30T15:52:47.88Z" }, + { url = "https://files.pythonhosted.org/packages/a4/14/0145a251f555f7c754ce2dcbcd012939bbd1f34f066fa5d28a50e722a054/multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b24576f208793ebae00280c59927c3b7c2a3b1655e443a25f753c4611bc1c373", size = 250083, upload-time = "2025-06-30T15:52:49.366Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d4/d5c0bd2bbb173b586c249a151a26d2fb3ec7d53c96e42091c9fef4e1f10c/multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:135631cb6c58eac37d7ac0df380294fecdc026b28837fa07c02e459c7fb9c54e", size = 228980, upload-time = "2025-06-30T15:52:50.903Z" }, + { url = "https://files.pythonhosted.org/packages/21/32/c9a2d8444a50ec48c4733ccc67254100c10e1c8ae8e40c7a2d2183b59b97/multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:274d416b0df887aef98f19f21578653982cfb8a05b4e187d4a17103322eeaf8f", size = 257776, upload-time = "2025-06-30T15:52:52.764Z" }, + { url = "https://files.pythonhosted.org/packages/68/d0/14fa1699f4ef629eae08ad6201c6b476098f5efb051b296f4c26be7a9fdf/multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e252017a817fad7ce05cafbe5711ed40faeb580e63b16755a3a24e66fa1d87c0", size = 256882, upload-time = "2025-06-30T15:52:54.596Z" }, + { url = "https://files.pythonhosted.org/packages/da/88/84a27570fbe303c65607d517a5f147cd2fc046c2d1da02b84b17b9bdc2aa/multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4cc8d848cd4fe1cdee28c13ea79ab0ed37fc2e89dd77bac86a2e7959a8c3bc", size = 247816, upload-time = "2025-06-30T15:52:56.175Z" }, + { url = "https://files.pythonhosted.org/packages/1c/60/dca352a0c999ce96a5d8b8ee0b2b9f729dcad2e0b0c195f8286269a2074c/multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9e236a7094b9c4c1b7585f6b9cca34b9d833cf079f7e4c49e6a4a6ec9bfdc68f", size = 245341, upload-time = "2025-06-30T15:52:57.752Z" }, + { url = "https://files.pythonhosted.org/packages/50/ef/433fa3ed06028f03946f3993223dada70fb700f763f70c00079533c34578/multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e0cb0ab69915c55627c933f0b555a943d98ba71b4d1c57bc0d0a66e2567c7471", size = 235854, upload-time = "2025-06-30T15:52:59.74Z" }, + { url = "https://files.pythonhosted.org/packages/1b/1f/487612ab56fbe35715320905215a57fede20de7db40a261759690dc80471/multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:81ef2f64593aba09c5212a3d0f8c906a0d38d710a011f2f42759704d4557d3f2", size = 243432, upload-time = "2025-06-30T15:53:01.602Z" }, + { url = "https://files.pythonhosted.org/packages/da/6f/ce8b79de16cd885c6f9052c96a3671373d00c59b3ee635ea93e6e81b8ccf/multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:b9cbc60010de3562545fa198bfc6d3825df430ea96d2cc509c39bd71e2e7d648", size = 252731, upload-time = "2025-06-30T15:53:03.517Z" }, + { url = "https://files.pythonhosted.org/packages/bb/fe/a2514a6aba78e5abefa1624ca85ae18f542d95ac5cde2e3815a9fbf369aa/multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70d974eaaa37211390cd02ef93b7e938de564bbffa866f0b08d07e5e65da783d", size = 247086, upload-time = "2025-06-30T15:53:05.48Z" }, + { url = "https://files.pythonhosted.org/packages/8c/22/b788718d63bb3cce752d107a57c85fcd1a212c6c778628567c9713f9345a/multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3713303e4a6663c6d01d648a68f2848701001f3390a030edaaf3fc949c90bf7c", size = 243338, upload-time = "2025-06-30T15:53:07.522Z" }, + { url = "https://files.pythonhosted.org/packages/22/d6/fdb3d0670819f2228f3f7d9af613d5e652c15d170c83e5f1c94fbc55a25b/multidict-6.6.3-cp313-cp313t-win32.whl", hash = "sha256:639ecc9fe7cd73f2495f62c213e964843826f44505a3e5d82805aa85cac6f89e", size = 47812, upload-time = "2025-06-30T15:53:09.263Z" }, + { url = "https://files.pythonhosted.org/packages/b6/d6/a9d2c808f2c489ad199723197419207ecbfbc1776f6e155e1ecea9c883aa/multidict-6.6.3-cp313-cp313t-win_amd64.whl", hash = "sha256:9f97e181f344a0ef3881b573d31de8542cc0dbc559ec68c8f8b5ce2c2e91646d", size = 53011, upload-time = "2025-06-30T15:53:11.038Z" }, + { url = "https://files.pythonhosted.org/packages/f2/40/b68001cba8188dd267590a111f9661b6256debc327137667e832bf5d66e8/multidict-6.6.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ce8b7693da41a3c4fde5871c738a81490cea5496c671d74374c8ab889e1834fb", size = 45254, upload-time = "2025-06-30T15:53:12.421Z" }, + { url = "https://files.pythonhosted.org/packages/d8/30/9aec301e9772b098c1f5c0ca0279237c9766d94b97802e9888010c64b0ed/multidict-6.6.3-py3-none-any.whl", hash = "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a", size = 12313, upload-time = "2025-06-30T15:53:45.437Z" }, +] + +[[package]] +name = "nicegui" +version = "2.22.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiofiles" }, + { name = "aiohttp" }, + { name = "certifi" }, + { name = "docutils" }, + { name = "fastapi" }, + { name = "h11" }, + { name = "httpx" }, + { name = "ifaddr" }, + { name = "itsdangerous" }, + { name = "jinja2" }, + { name = "markdown2" }, + { name = "orjson", marker = "platform_machine != 'i386' and platform_machine != 'i686'" }, + { name = "pygments" }, + { name = "python-engineio" }, + { name = "python-multipart" }, + { name = "python-socketio", extra = ["asyncio-client"] }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "uvicorn", extra = ["standard"] }, + { name = "vbuild" }, + { name = "watchfiles" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/81/aaf1432abf54f25d62a3c346a087db39c4d7a38833795c3f1eb90feab5fd/nicegui-2.22.2.tar.gz", hash = "sha256:5c0aaf2d2365c665ae42955b17d6fa7ba19526d7aa9bd02ab547917e7bd1338c", size = 13107276, upload-time = "2025-08-09T15:31:08.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/2b/141c85335df3982ca9a54da95d0c8954efe9756da8f2edaba2afbd262014/nicegui-2.22.2-py3-none-any.whl", hash = "sha256:a0e371918419af5bae7b22e6b55a29065a7a4222908af66584fd599e391b5b5f", size = 13494497, upload-time = "2025-08-09T15:31:05.235Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, +] + +[[package]] +name = "orjson" +version = "3.11.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/19/3b/fd9ff8ff64ae3900f11554d5cfc835fb73e501e043c420ad32ec574fe27f/orjson-3.11.1.tar.gz", hash = "sha256:48d82770a5fd88778063604c566f9c7c71820270c9cc9338d25147cbf34afd96", size = 5393373, upload-time = "2025-07-25T14:33:52.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/77/e55513826b712807caadb2b733eee192c1df105c6bbf0d965c253b72f124/orjson-3.11.1-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2b7c8be96db3a977367250c6367793a3c5851a6ca4263f92f0b48d00702f9910", size = 240955, upload-time = "2025-07-25T14:32:34.056Z" }, + { url = "https://files.pythonhosted.org/packages/c9/88/a78132dddcc9c3b80a9fa050b3516bb2c996a9d78ca6fb47c8da2a80a696/orjson-3.11.1-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:72e18088f567bd4a45db5e3196677d9ed1605e356e500c8e32dd6e303167a13d", size = 129294, upload-time = "2025-07-25T14:32:35.323Z" }, + { url = "https://files.pythonhosted.org/packages/09/02/6591e0dcb2af6bceea96cb1b5f4b48c1445492a3ef2891ac4aa306bb6f73/orjson-3.11.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d346e2ae1ce17888f7040b65a5a4a0c9734cb20ffbd228728661e020b4c8b3a5", size = 132310, upload-time = "2025-07-25T14:32:36.53Z" }, + { url = "https://files.pythonhosted.org/packages/e9/36/c1cfbc617bcfa4835db275d5e0fe9bbdbe561a4b53d3b2de16540ec29c50/orjson-3.11.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4bda5426ebb02ceb806a7d7ec9ba9ee5e0c93fca62375151a7b1c00bc634d06b", size = 128529, upload-time = "2025-07-25T14:32:37.817Z" }, + { url = "https://files.pythonhosted.org/packages/7c/bd/91a156c5df3aaf1d68b2ab5be06f1969955a8d3e328d7794f4338ac1d017/orjson-3.11.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10506cebe908542c4f024861102673db534fd2e03eb9b95b30d94438fa220abf", size = 130925, upload-time = "2025-07-25T14:32:39.03Z" }, + { url = "https://files.pythonhosted.org/packages/a3/4c/a65cc24e9a5f87c9833a50161ab97b5edbec98bec99dfbba13827549debc/orjson-3.11.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45202ee3f5494644e064c41abd1320497fb92fd31fc73af708708af664ac3b56", size = 132432, upload-time = "2025-07-25T14:32:40.619Z" }, + { url = "https://files.pythonhosted.org/packages/2e/4d/3fc3e5d7115f4f7d01b481e29e5a79bcbcc45711a2723242787455424f40/orjson-3.11.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5adaf01b92e0402a9ac5c3ebe04effe2bbb115f0914a0a53d34ea239a746289", size = 135069, upload-time = "2025-07-25T14:32:41.84Z" }, + { url = "https://files.pythonhosted.org/packages/dc/c6/7585aa8522af896060dc0cd7c336ba6c574ae854416811ee6642c505cc95/orjson-3.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6162a1a757a1f1f4a94bc6ffac834a3602e04ad5db022dd8395a54ed9dd51c81", size = 131045, upload-time = "2025-07-25T14:32:43.085Z" }, + { url = "https://files.pythonhosted.org/packages/6a/4e/b8a0a943793d2708ebc39e743c943251e08ee0f3279c880aefd8e9cb0c70/orjson-3.11.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:78404206977c9f946613d3f916727c189d43193e708d760ea5d4b2087d6b0968", size = 130597, upload-time = "2025-07-25T14:32:44.336Z" }, + { url = "https://files.pythonhosted.org/packages/72/2b/7d30e2aed2f585d5d385fb45c71d9b16ba09be58c04e8767ae6edc6c9282/orjson-3.11.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:db48f8e81072e26df6cdb0e9fff808c28597c6ac20a13d595756cf9ba1fed48a", size = 404207, upload-time = "2025-07-25T14:32:45.612Z" }, + { url = "https://files.pythonhosted.org/packages/1b/7e/772369ec66fcbce79477f0891918309594cd00e39b67a68d4c445d2ab754/orjson-3.11.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0c1e394e67ced6bb16fea7054d99fbdd99a539cf4d446d40378d4c06e0a8548d", size = 146628, upload-time = "2025-07-25T14:32:46.981Z" }, + { url = "https://files.pythonhosted.org/packages/b4/c8/62bdb59229d7e393ae309cef41e32cc1f0b567b21dfd0742da70efb8b40c/orjson-3.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e7a840752c93d4eecd1378e9bb465c3703e127b58f675cd5c620f361b6cf57a4", size = 135449, upload-time = "2025-07-25T14:32:48.727Z" }, + { url = "https://files.pythonhosted.org/packages/02/47/1c99aa60e19f781424eabeaacd9e999eafe5b59c81ead4273b773f0f3af1/orjson-3.11.1-cp312-cp312-win32.whl", hash = "sha256:4537b0e09f45d2b74cb69c7f39ca1e62c24c0488d6bf01cd24673c74cd9596bf", size = 136653, upload-time = "2025-07-25T14:32:50.622Z" }, + { url = "https://files.pythonhosted.org/packages/31/9a/132999929a2892ab07e916669accecc83e5bff17e11a1186b4c6f23231f0/orjson-3.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:dbee6b050062540ae404530cacec1bf25e56e8d87d8d9b610b935afeb6725cae", size = 131426, upload-time = "2025-07-25T14:32:51.883Z" }, + { url = "https://files.pythonhosted.org/packages/9c/77/d984ee5a1ca341090902e080b187721ba5d1573a8d9759e0c540975acfb2/orjson-3.11.1-cp312-cp312-win_arm64.whl", hash = "sha256:f55e557d4248322d87c4673e085c7634039ff04b47bfc823b87149ae12bef60d", size = 126635, upload-time = "2025-07-25T14:32:53.2Z" }, + { url = "https://files.pythonhosted.org/packages/c9/e9/880ef869e6f66279ce3a381a32afa0f34e29a94250146911eee029e56efc/orjson-3.11.1-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:53cfefe4af059e65aabe9683f76b9c88bf34b4341a77d329227c2424e0e59b0e", size = 240835, upload-time = "2025-07-25T14:32:54.507Z" }, + { url = "https://files.pythonhosted.org/packages/f0/1f/52039ef3d03eeea21763b46bc99ebe11d9de8510c72b7b5569433084a17e/orjson-3.11.1-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:93d5abed5a6f9e1b6f9b5bf6ed4423c11932b5447c2f7281d3b64e0f26c6d064", size = 129226, upload-time = "2025-07-25T14:32:55.908Z" }, + { url = "https://files.pythonhosted.org/packages/ee/da/59fdffc9465a760be2cd3764ef9cd5535eec8f095419f972fddb123b6d0e/orjson-3.11.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dbf06642f3db2966df504944cdd0eb68ca2717f0353bb20b20acd78109374a6", size = 132261, upload-time = "2025-07-25T14:32:57.538Z" }, + { url = "https://files.pythonhosted.org/packages/bb/5c/8610911c7e969db7cf928c8baac4b2f1e68d314bc3057acf5ca64f758435/orjson-3.11.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dddf4e78747fa7f2188273f84562017a3c4f0824485b78372513c1681ea7a894", size = 128614, upload-time = "2025-07-25T14:32:58.808Z" }, + { url = "https://files.pythonhosted.org/packages/f7/a1/a1db9d4310d014c90f3b7e9b72c6fb162cba82c5f46d0b345669eaebdd3a/orjson-3.11.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa3fe8653c9f57f0e16f008e43626485b6723b84b2f741f54d1258095b655912", size = 130968, upload-time = "2025-07-25T14:33:00.038Z" }, + { url = "https://files.pythonhosted.org/packages/56/ff/11acd1fd7c38ea7a1b5d6bf582ae3da05931bee64620995eb08fd63c77fe/orjson-3.11.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6334d2382aff975a61f6f4d1c3daf39368b887c7de08f7c16c58f485dcf7adb2", size = 132439, upload-time = "2025-07-25T14:33:01.354Z" }, + { url = "https://files.pythonhosted.org/packages/70/f9/bb564dd9450bf8725e034a8ad7f4ae9d4710a34caf63b85ce1c0c6d40af0/orjson-3.11.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3d0855b643f259ee0cb76fe3df4c04483354409a520a902b067c674842eb6b8", size = 135299, upload-time = "2025-07-25T14:33:03.079Z" }, + { url = "https://files.pythonhosted.org/packages/94/bb/c8eafe6051405e241dda3691db4d9132d3c3462d1d10a17f50837dd130b4/orjson-3.11.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0eacdfeefd0a79987926476eb16e0245546bedeb8febbbbcf4b653e79257a8e4", size = 131004, upload-time = "2025-07-25T14:33:04.416Z" }, + { url = "https://files.pythonhosted.org/packages/a2/40/bed8d7dcf1bd2df8813bf010a25f645863a2f75e8e0ebdb2b55784cf1a62/orjson-3.11.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0ed07faf9e4873518c60480325dcbc16d17c59a165532cccfb409b4cdbaeff24", size = 130583, upload-time = "2025-07-25T14:33:05.768Z" }, + { url = "https://files.pythonhosted.org/packages/57/e7/cfa2eb803ad52d74fbb5424a429b5be164e51d23f1d853e5e037173a5c48/orjson-3.11.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d6d308dd578ae3658f62bb9eba54801533225823cd3248c902be1ebc79b5e014", size = 404218, upload-time = "2025-07-25T14:33:07.117Z" }, + { url = "https://files.pythonhosted.org/packages/d5/21/bc703af5bc6e9c7e18dcf4404dcc4ec305ab9bb6c82d3aee5952c0c56abf/orjson-3.11.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c4aa13ca959ba6b15c0a98d3d204b850f9dc36c08c9ce422ffb024eb30d6e058", size = 146605, upload-time = "2025-07-25T14:33:08.55Z" }, + { url = "https://files.pythonhosted.org/packages/8f/fe/d26a0150534c4965a06f556aa68bf3c3b82999d5d7b0facd3af7b390c4af/orjson-3.11.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:be3d0653322abc9b68e5bcdaee6cfd58fcbe9973740ab222b87f4d687232ab1f", size = 135434, upload-time = "2025-07-25T14:33:09.967Z" }, + { url = "https://files.pythonhosted.org/packages/89/b6/1cb28365f08cbcffc464f8512320c6eb6db6a653f03d66de47ea3c19385f/orjson-3.11.1-cp313-cp313-win32.whl", hash = "sha256:4dd34e7e2518de8d7834268846f8cab7204364f427c56fb2251e098da86f5092", size = 136596, upload-time = "2025-07-25T14:33:11.333Z" }, + { url = "https://files.pythonhosted.org/packages/f9/35/7870d0d3ed843652676d84d8a6038791113eacc85237b673b925802826b8/orjson-3.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:d6895d32032b6362540e6d0694b19130bb4f2ad04694002dce7d8af588ca5f77", size = 131319, upload-time = "2025-07-25T14:33:12.614Z" }, + { url = "https://files.pythonhosted.org/packages/b7/3e/5bcd50fd865eb664d4edfdaaaff51e333593ceb5695a22c0d0a0d2b187ba/orjson-3.11.1-cp313-cp313-win_arm64.whl", hash = "sha256:bb7c36d5d3570fcbb01d24fa447a21a7fe5a41141fd88e78f7994053cc4e28f4", size = 126613, upload-time = "2025-07-25T14:33:13.927Z" }, + { url = "https://files.pythonhosted.org/packages/61/d8/0a5cd31ed100b4e569e143cb0cddefc21f0bcb8ce284f44bca0bb0e10f3d/orjson-3.11.1-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7b71ef394327b3d0b39f6ea7ade2ecda2731a56c6a7cbf0d6a7301203b92a89b", size = 240819, upload-time = "2025-07-25T14:33:15.223Z" }, + { url = "https://files.pythonhosted.org/packages/b9/95/7eb2c76c92192ceca16bc81845ff100bbb93f568b4b94d914b6a4da47d61/orjson-3.11.1-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:77c0fe28ed659b62273995244ae2aa430e432c71f86e4573ab16caa2f2e3ca5e", size = 129218, upload-time = "2025-07-25T14:33:16.637Z" }, + { url = "https://files.pythonhosted.org/packages/da/84/e6b67f301b18adbbc346882f456bea44daebbd032ba725dbd7b741e3a7f1/orjson-3.11.1-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:1495692f1f1ba2467df429343388a0ed259382835922e124c0cfdd56b3d1f727", size = 132238, upload-time = "2025-07-25T14:33:17.934Z" }, + { url = "https://files.pythonhosted.org/packages/84/78/a45a86e29d9b2f391f9d00b22da51bc4b46b86b788fd42df2c5fcf3e8005/orjson-3.11.1-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:08c6a762fca63ca4dc04f66c48ea5d2428db55839fec996890e1bfaf057b658c", size = 130998, upload-time = "2025-07-25T14:33:19.282Z" }, + { url = "https://files.pythonhosted.org/packages/ea/8f/6eb3ee6760d93b2ce996a8529164ee1f5bafbdf64b74c7314b68db622b32/orjson-3.11.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9e26794fe3976810b2c01fda29bd9ac7c91a3c1284b29cc9a383989f7b614037", size = 130559, upload-time = "2025-07-25T14:33:20.589Z" }, + { url = "https://files.pythonhosted.org/packages/1b/78/9572ae94bdba6813917c9387e7834224c011ea6b4530ade07d718fd31598/orjson-3.11.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4b4b4f8f0b1d3ef8dc73e55363a0ffe012a42f4e2f1a140bf559698dca39b3fa", size = 404231, upload-time = "2025-07-25T14:33:22.019Z" }, + { url = "https://files.pythonhosted.org/packages/1f/a3/68381ad0757e084927c5ee6cfdeab1c6c89405949ee493db557e60871c4c/orjson-3.11.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:848be553ea35aa89bfefbed2e27c8a41244c862956ab8ba00dc0b27e84fd58de", size = 146658, upload-time = "2025-07-25T14:33:23.675Z" }, + { url = "https://files.pythonhosted.org/packages/00/db/fac56acf77aab778296c3f541a3eec643266f28ecd71d6c0cba251e47655/orjson-3.11.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c964c29711a4b1df52f8d9966f015402a6cf87753a406c1c4405c407dd66fd45", size = 135443, upload-time = "2025-07-25T14:33:25.04Z" }, + { url = "https://files.pythonhosted.org/packages/76/b1/326fa4b87426197ead61c1eec2eeb3babc9eb33b480ac1f93894e40c8c08/orjson-3.11.1-cp314-cp314-win32.whl", hash = "sha256:33aada2e6b6bc9c540d396528b91e666cedb383740fee6e6a917f561b390ecb1", size = 136643, upload-time = "2025-07-25T14:33:26.449Z" }, + { url = "https://files.pythonhosted.org/packages/0f/8e/2987ae2109f3bfd39680f8a187d1bc09ad7f8fb019dcdc719b08c7242ade/orjson-3.11.1-cp314-cp314-win_amd64.whl", hash = "sha256:68e10fd804e44e36188b9952543e3fa22f5aa8394da1b5283ca2b423735c06e8", size = 131324, upload-time = "2025-07-25T14:33:27.896Z" }, + { url = "https://files.pythonhosted.org/packages/21/5f/253e08e6974752b124fbf3a4de3ad53baa766b0cb4a333d47706d307e396/orjson-3.11.1-cp314-cp314-win_arm64.whl", hash = "sha256:f3cf6c07f8b32127d836be8e1c55d4f34843f7df346536da768e9f73f22078a1", size = 126605, upload-time = "2025-07-25T14:33:29.244Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, +] + +[[package]] +name = "pre-commit" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, +] + +[[package]] +name = "propcache" +version = "0.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/16/43264e4a779dd8588c21a70f0709665ee8f611211bdd2c87d952cfa7c776/propcache-0.3.2.tar.gz", hash = "sha256:20d7d62e4e7ef05f221e0db2856b979540686342e7dd9973b815599c7057e168", size = 44139, upload-time = "2025-06-09T22:56:06.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/42/9ca01b0a6f48e81615dca4765a8f1dd2c057e0540f6116a27dc5ee01dfb6/propcache-0.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8de106b6c84506b31c27168582cd3cb3000a6412c16df14a8628e5871ff83c10", size = 73674, upload-time = "2025-06-09T22:54:30.551Z" }, + { url = "https://files.pythonhosted.org/packages/af/6e/21293133beb550f9c901bbece755d582bfaf2176bee4774000bd4dd41884/propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154", size = 43570, upload-time = "2025-06-09T22:54:32.296Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c8/0393a0a3a2b8760eb3bde3c147f62b20044f0ddac81e9d6ed7318ec0d852/propcache-0.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce26862344bdf836650ed2487c3d724b00fbfec4233a1013f597b78c1cb73615", size = 43094, upload-time = "2025-06-09T22:54:33.929Z" }, + { url = "https://files.pythonhosted.org/packages/37/2c/489afe311a690399d04a3e03b069225670c1d489eb7b044a566511c1c498/propcache-0.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca54bd347a253af2cf4544bbec232ab982f4868de0dd684246b67a51bc6b1db", size = 226958, upload-time = "2025-06-09T22:54:35.186Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ca/63b520d2f3d418c968bf596839ae26cf7f87bead026b6192d4da6a08c467/propcache-0.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55780d5e9a2ddc59711d727226bb1ba83a22dd32f64ee15594b9392b1f544eb1", size = 234894, upload-time = "2025-06-09T22:54:36.708Z" }, + { url = "https://files.pythonhosted.org/packages/11/60/1d0ed6fff455a028d678df30cc28dcee7af77fa2b0e6962ce1df95c9a2a9/propcache-0.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:035e631be25d6975ed87ab23153db6a73426a48db688070d925aa27e996fe93c", size = 233672, upload-time = "2025-06-09T22:54:38.062Z" }, + { url = "https://files.pythonhosted.org/packages/37/7c/54fd5301ef38505ab235d98827207176a5c9b2aa61939b10a460ca53e123/propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67", size = 224395, upload-time = "2025-06-09T22:54:39.634Z" }, + { url = "https://files.pythonhosted.org/packages/ee/1a/89a40e0846f5de05fdc6779883bf46ba980e6df4d2ff8fb02643de126592/propcache-0.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ca3aee1aa955438c4dba34fc20a9f390e4c79967257d830f137bd5a8a32ed3b", size = 212510, upload-time = "2025-06-09T22:54:41.565Z" }, + { url = "https://files.pythonhosted.org/packages/5e/33/ca98368586c9566a6b8d5ef66e30484f8da84c0aac3f2d9aec6d31a11bd5/propcache-0.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4f30862869fa2b68380d677cc1c5fcf1e0f2b9ea0cf665812895c75d0ca3b8", size = 222949, upload-time = "2025-06-09T22:54:43.038Z" }, + { url = "https://files.pythonhosted.org/packages/ba/11/ace870d0aafe443b33b2f0b7efdb872b7c3abd505bfb4890716ad7865e9d/propcache-0.3.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b77ec3c257d7816d9f3700013639db7491a434644c906a2578a11daf13176251", size = 217258, upload-time = "2025-06-09T22:54:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d2/86fd6f7adffcfc74b42c10a6b7db721d1d9ca1055c45d39a1a8f2a740a21/propcache-0.3.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cab90ac9d3f14b2d5050928483d3d3b8fb6b4018893fc75710e6aa361ecb2474", size = 213036, upload-time = "2025-06-09T22:54:46.243Z" }, + { url = "https://files.pythonhosted.org/packages/07/94/2d7d1e328f45ff34a0a284cf5a2847013701e24c2a53117e7c280a4316b3/propcache-0.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0b504d29f3c47cf6b9e936c1852246c83d450e8e063d50562115a6be6d3a2535", size = 227684, upload-time = "2025-06-09T22:54:47.63Z" }, + { url = "https://files.pythonhosted.org/packages/b7/05/37ae63a0087677e90b1d14710e532ff104d44bc1efa3b3970fff99b891dc/propcache-0.3.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:ce2ac2675a6aa41ddb2a0c9cbff53780a617ac3d43e620f8fd77ba1c84dcfc06", size = 234562, upload-time = "2025-06-09T22:54:48.982Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7c/3f539fcae630408d0bd8bf3208b9a647ccad10976eda62402a80adf8fc34/propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1", size = 222142, upload-time = "2025-06-09T22:54:50.424Z" }, + { url = "https://files.pythonhosted.org/packages/7c/d2/34b9eac8c35f79f8a962546b3e97e9d4b990c420ee66ac8255d5d9611648/propcache-0.3.2-cp312-cp312-win32.whl", hash = "sha256:df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1", size = 37711, upload-time = "2025-06-09T22:54:52.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/61/d582be5d226cf79071681d1b46b848d6cb03d7b70af7063e33a2787eaa03/propcache-0.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c", size = 41479, upload-time = "2025-06-09T22:54:53.234Z" }, + { url = "https://files.pythonhosted.org/packages/dc/d1/8c747fafa558c603c4ca19d8e20b288aa0c7cda74e9402f50f31eb65267e/propcache-0.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ca592ed634a73ca002967458187109265e980422116c0a107cf93d81f95af945", size = 71286, upload-time = "2025-06-09T22:54:54.369Z" }, + { url = "https://files.pythonhosted.org/packages/61/99/d606cb7986b60d89c36de8a85d58764323b3a5ff07770a99d8e993b3fa73/propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252", size = 42425, upload-time = "2025-06-09T22:54:55.642Z" }, + { url = "https://files.pythonhosted.org/packages/8c/96/ef98f91bbb42b79e9bb82bdd348b255eb9d65f14dbbe3b1594644c4073f7/propcache-0.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f08f1cc28bd2eade7a8a3d2954ccc673bb02062e3e7da09bc75d843386b342f", size = 41846, upload-time = "2025-06-09T22:54:57.246Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ad/3f0f9a705fb630d175146cd7b1d2bf5555c9beaed54e94132b21aac098a6/propcache-0.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1a342c834734edb4be5ecb1e9fb48cb64b1e2320fccbd8c54bf8da8f2a84c33", size = 208871, upload-time = "2025-06-09T22:54:58.975Z" }, + { url = "https://files.pythonhosted.org/packages/3a/38/2085cda93d2c8b6ec3e92af2c89489a36a5886b712a34ab25de9fbca7992/propcache-0.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a544caaae1ac73f1fecfae70ded3e93728831affebd017d53449e3ac052ac1e", size = 215720, upload-time = "2025-06-09T22:55:00.471Z" }, + { url = "https://files.pythonhosted.org/packages/61/c1/d72ea2dc83ac7f2c8e182786ab0fc2c7bd123a1ff9b7975bee671866fe5f/propcache-0.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310d11aa44635298397db47a3ebce7db99a4cc4b9bbdfcf6c98a60c8d5261cf1", size = 215203, upload-time = "2025-06-09T22:55:01.834Z" }, + { url = "https://files.pythonhosted.org/packages/af/81/b324c44ae60c56ef12007105f1460d5c304b0626ab0cc6b07c8f2a9aa0b8/propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3", size = 206365, upload-time = "2025-06-09T22:55:03.199Z" }, + { url = "https://files.pythonhosted.org/packages/09/73/88549128bb89e66d2aff242488f62869014ae092db63ccea53c1cc75a81d/propcache-0.3.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cabf5b5902272565e78197edb682017d21cf3b550ba0460ee473753f28d23c1", size = 196016, upload-time = "2025-06-09T22:55:04.518Z" }, + { url = "https://files.pythonhosted.org/packages/b9/3f/3bdd14e737d145114a5eb83cb172903afba7242f67c5877f9909a20d948d/propcache-0.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0a2f2235ac46a7aa25bdeb03a9e7060f6ecbd213b1f9101c43b3090ffb971ef6", size = 205596, upload-time = "2025-06-09T22:55:05.942Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ca/2f4aa819c357d3107c3763d7ef42c03980f9ed5c48c82e01e25945d437c1/propcache-0.3.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:92b69e12e34869a6970fd2f3da91669899994b47c98f5d430b781c26f1d9f387", size = 200977, upload-time = "2025-06-09T22:55:07.792Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4a/e65276c7477533c59085251ae88505caf6831c0e85ff8b2e31ebcbb949b1/propcache-0.3.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:54e02207c79968ebbdffc169591009f4474dde3b4679e16634d34c9363ff56b4", size = 197220, upload-time = "2025-06-09T22:55:09.173Z" }, + { url = "https://files.pythonhosted.org/packages/7c/54/fc7152e517cf5578278b242396ce4d4b36795423988ef39bb8cd5bf274c8/propcache-0.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4adfb44cb588001f68c5466579d3f1157ca07f7504fc91ec87862e2b8e556b88", size = 210642, upload-time = "2025-06-09T22:55:10.62Z" }, + { url = "https://files.pythonhosted.org/packages/b9/80/abeb4a896d2767bf5f1ea7b92eb7be6a5330645bd7fb844049c0e4045d9d/propcache-0.3.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fd3e6019dc1261cd0291ee8919dd91fbab7b169bb76aeef6c716833a3f65d206", size = 212789, upload-time = "2025-06-09T22:55:12.029Z" }, + { url = "https://files.pythonhosted.org/packages/b3/db/ea12a49aa7b2b6d68a5da8293dcf50068d48d088100ac016ad92a6a780e6/propcache-0.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4c181cad81158d71c41a2bce88edce078458e2dd5ffee7eddd6b05da85079f43", size = 205880, upload-time = "2025-06-09T22:55:13.45Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e5/9076a0bbbfb65d1198007059c65639dfd56266cf8e477a9707e4b1999ff4/propcache-0.3.2-cp313-cp313-win32.whl", hash = "sha256:8a08154613f2249519e549de2330cf8e2071c2887309a7b07fb56098f5170a02", size = 37220, upload-time = "2025-06-09T22:55:15.284Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f5/b369e026b09a26cd77aa88d8fffd69141d2ae00a2abaaf5380d2603f4b7f/propcache-0.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e41671f1594fc4ab0a6dec1351864713cb3a279910ae8b58f884a88a0a632c05", size = 40678, upload-time = "2025-06-09T22:55:16.445Z" }, + { url = "https://files.pythonhosted.org/packages/a4/3a/6ece377b55544941a08d03581c7bc400a3c8cd3c2865900a68d5de79e21f/propcache-0.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9a3cf035bbaf035f109987d9d55dc90e4b0e36e04bbbb95af3055ef17194057b", size = 76560, upload-time = "2025-06-09T22:55:17.598Z" }, + { url = "https://files.pythonhosted.org/packages/0c/da/64a2bb16418740fa634b0e9c3d29edff1db07f56d3546ca2d86ddf0305e1/propcache-0.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:156c03d07dc1323d8dacaa221fbe028c5c70d16709cdd63502778e6c3ccca1b0", size = 44676, upload-time = "2025-06-09T22:55:18.922Z" }, + { url = "https://files.pythonhosted.org/packages/36/7b/f025e06ea51cb72c52fb87e9b395cced02786610b60a3ed51da8af017170/propcache-0.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74413c0ba02ba86f55cf60d18daab219f7e531620c15f1e23d95563f505efe7e", size = 44701, upload-time = "2025-06-09T22:55:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/a4/00/faa1b1b7c3b74fc277f8642f32a4c72ba1d7b2de36d7cdfb676db7f4303e/propcache-0.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f066b437bb3fa39c58ff97ab2ca351db465157d68ed0440abecb21715eb24b28", size = 276934, upload-time = "2025-06-09T22:55:21.5Z" }, + { url = "https://files.pythonhosted.org/packages/74/ab/935beb6f1756e0476a4d5938ff44bf0d13a055fed880caf93859b4f1baf4/propcache-0.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1304b085c83067914721e7e9d9917d41ad87696bf70f0bc7dee450e9c71ad0a", size = 278316, upload-time = "2025-06-09T22:55:22.918Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9d/994a5c1ce4389610838d1caec74bdf0e98b306c70314d46dbe4fcf21a3e2/propcache-0.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab50cef01b372763a13333b4e54021bdcb291fc9a8e2ccb9c2df98be51bcde6c", size = 282619, upload-time = "2025-06-09T22:55:24.651Z" }, + { url = "https://files.pythonhosted.org/packages/2b/00/a10afce3d1ed0287cef2e09506d3be9822513f2c1e96457ee369adb9a6cd/propcache-0.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad3b2a085ec259ad2c2842666b2a0a49dea8463579c606426128925af1ed725", size = 265896, upload-time = "2025-06-09T22:55:26.049Z" }, + { url = "https://files.pythonhosted.org/packages/2e/a8/2aa6716ffa566ca57c749edb909ad27884680887d68517e4be41b02299f3/propcache-0.3.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:261fa020c1c14deafd54c76b014956e2f86991af198c51139faf41c4d5e83892", size = 252111, upload-time = "2025-06-09T22:55:27.381Z" }, + { url = "https://files.pythonhosted.org/packages/36/4f/345ca9183b85ac29c8694b0941f7484bf419c7f0fea2d1e386b4f7893eed/propcache-0.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:46d7f8aa79c927e5f987ee3a80205c987717d3659f035c85cf0c3680526bdb44", size = 268334, upload-time = "2025-06-09T22:55:28.747Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ca/fcd54f78b59e3f97b3b9715501e3147f5340167733d27db423aa321e7148/propcache-0.3.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:6d8f3f0eebf73e3c0ff0e7853f68be638b4043c65a70517bb575eff54edd8dbe", size = 255026, upload-time = "2025-06-09T22:55:30.184Z" }, + { url = "https://files.pythonhosted.org/packages/8b/95/8e6a6bbbd78ac89c30c225210a5c687790e532ba4088afb8c0445b77ef37/propcache-0.3.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:03c89c1b14a5452cf15403e291c0ccd7751d5b9736ecb2c5bab977ad6c5bcd81", size = 250724, upload-time = "2025-06-09T22:55:31.646Z" }, + { url = "https://files.pythonhosted.org/packages/ee/b0/0dd03616142baba28e8b2d14ce5df6631b4673850a3d4f9c0f9dd714a404/propcache-0.3.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cc17efde71e12bbaad086d679ce575268d70bc123a5a71ea7ad76f70ba30bba", size = 268868, upload-time = "2025-06-09T22:55:33.209Z" }, + { url = "https://files.pythonhosted.org/packages/c5/98/2c12407a7e4fbacd94ddd32f3b1e3d5231e77c30ef7162b12a60e2dd5ce3/propcache-0.3.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:acdf05d00696bc0447e278bb53cb04ca72354e562cf88ea6f9107df8e7fd9770", size = 271322, upload-time = "2025-06-09T22:55:35.065Z" }, + { url = "https://files.pythonhosted.org/packages/35/91/9cb56efbb428b006bb85db28591e40b7736847b8331d43fe335acf95f6c8/propcache-0.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4445542398bd0b5d32df908031cb1b30d43ac848e20470a878b770ec2dcc6330", size = 265778, upload-time = "2025-06-09T22:55:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4c/b0fe775a2bdd01e176b14b574be679d84fc83958335790f7c9a686c1f468/propcache-0.3.2-cp313-cp313t-win32.whl", hash = "sha256:f86e5d7cd03afb3a1db8e9f9f6eff15794e79e791350ac48a8c924e6f439f394", size = 41175, upload-time = "2025-06-09T22:55:38.436Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ff/47f08595e3d9b5e149c150f88d9714574f1a7cbd89fe2817158a952674bf/propcache-0.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9704bedf6e7cbe3c65eca4379a9b53ee6a83749f047808cbb5044d40d7d72198", size = 44857, upload-time = "2025-06-09T22:55:39.687Z" }, + { url = "https://files.pythonhosted.org/packages/cc/35/cc0aaecf278bb4575b8555f2b137de5ab821595ddae9da9d3cd1da4072c7/propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f", size = 12663, upload-time = "2025-06-09T22:56:04.484Z" }, +] + +[[package]] +name = "pscript" +version = "0.7.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/59/68/f918702e270eddc5f7c54108f6a2f2afc2d299985820dbb0db9beb77d66d/pscript-0.7.7.tar.gz", hash = "sha256:8632f7a4483f235514aadee110edee82eb6d67336bf68744a7b18d76e50442f8", size = 176138, upload-time = "2022-01-10T10:55:02.559Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/bc/980e2ebd442d2a8f1d22780f73db76f2a1df3bf79b3fb501b054b4b4dd03/pscript-0.7.7-py3-none-any.whl", hash = "sha256:b0fdac0df0393a4d7497153fea6a82e6429f32327c4c0a4817f1cd68adc08083", size = 126689, upload-time = "2022-01-10T10:55:00.793Z" }, +] + +[[package]] +name = "pydantic" +version = "2.11.7" +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/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, + { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, + { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, + { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, + { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, + { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, + { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, + { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, + { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, + { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, + { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, + { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, + { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, + { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, + { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, + { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, + { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, +] + +[[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 = "python-dotenv" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, +] + +[[package]] +name = "python-engineio" +version = "4.12.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "simple-websocket" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ba/0b/67295279b66835f9fa7a491650efcd78b20321c127036eef62c11a31e028/python_engineio-4.12.2.tar.gz", hash = "sha256:e7e712ffe1be1f6a05ee5f951e72d434854a32fcfc7f6e4d9d3cae24ec70defa", size = 91677, upload-time = "2025-06-04T19:22:18.789Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/fa/df59acedf7bbb937f69174d00f921a7b93aa5a5f5c17d05296c814fff6fc/python_engineio-4.12.2-py3-none-any.whl", hash = "sha256:8218ab66950e179dfec4b4bbb30aecf3f5d86f5e58e6fc1aa7fde2c698b2804f", size = 59536, upload-time = "2025-06-04T19:22:16.916Z" }, +] + +[[package]] +name = "python-multipart" +version = "0.0.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158, upload-time = "2024-12-16T19:45:46.972Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload-time = "2024-12-16T19:45:44.423Z" }, +] + +[[package]] +name = "python-socketio" +version = "5.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bidict" }, + { name = "python-engineio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/21/1a/396d50ccf06ee539fa758ce5623b59a9cb27637fc4b2dc07ed08bf495e77/python_socketio-5.13.0.tar.gz", hash = "sha256:ac4e19a0302ae812e23b712ec8b6427ca0521f7c582d6abb096e36e24a263029", size = 121125, upload-time = "2025-04-12T15:46:59.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/32/b4fb8585d1be0f68bde7e110dffbcf354915f77ad8c778563f0ad9655c02/python_socketio-5.13.0-py3-none-any.whl", hash = "sha256:51f68d6499f2df8524668c24bcec13ba1414117cfb3a90115c559b601ab10caf", size = 77800, upload-time = "2025-04-12T15:46:58.412Z" }, +] + +[package.optional-dependencies] +asyncio-client = [ + { name = "aiohttp" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, +] + +[[package]] +name = "ruff" +version = "0.12.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/da/5bd7565be729e86e1442dad2c9a364ceeff82227c2dece7c29697a9795eb/ruff-0.12.8.tar.gz", hash = "sha256:4cb3a45525176e1009b2b64126acf5f9444ea59066262791febf55e40493a033", size = 5242373, upload-time = "2025-08-07T19:05:47.268Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/1e/c843bfa8ad1114fab3eb2b78235dda76acd66384c663a4e0415ecc13aa1e/ruff-0.12.8-py3-none-linux_armv6l.whl", hash = "sha256:63cb5a5e933fc913e5823a0dfdc3c99add73f52d139d6cd5cc8639d0e0465513", size = 11675315, upload-time = "2025-08-07T19:05:06.15Z" }, + { url = "https://files.pythonhosted.org/packages/24/ee/af6e5c2a8ca3a81676d5480a1025494fd104b8896266502bb4de2a0e8388/ruff-0.12.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a9bbe28f9f551accf84a24c366c1aa8774d6748438b47174f8e8565ab9dedbc", size = 12456653, upload-time = "2025-08-07T19:05:09.759Z" }, + { url = "https://files.pythonhosted.org/packages/99/9d/e91f84dfe3866fa648c10512904991ecc326fd0b66578b324ee6ecb8f725/ruff-0.12.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2fae54e752a3150f7ee0e09bce2e133caf10ce9d971510a9b925392dc98d2fec", size = 11659690, upload-time = "2025-08-07T19:05:12.551Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ac/a363d25ec53040408ebdd4efcee929d48547665858ede0505d1d8041b2e5/ruff-0.12.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0acbcf01206df963d9331b5838fb31f3b44fa979ee7fa368b9b9057d89f4a53", size = 11896923, upload-time = "2025-08-07T19:05:14.821Z" }, + { url = "https://files.pythonhosted.org/packages/58/9f/ea356cd87c395f6ade9bb81365bd909ff60860975ca1bc39f0e59de3da37/ruff-0.12.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae3e7504666ad4c62f9ac8eedb52a93f9ebdeb34742b8b71cd3cccd24912719f", size = 11477612, upload-time = "2025-08-07T19:05:16.712Z" }, + { url = "https://files.pythonhosted.org/packages/1a/46/92e8fa3c9dcfd49175225c09053916cb97bb7204f9f899c2f2baca69e450/ruff-0.12.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb82efb5d35d07497813a1c5647867390a7d83304562607f3579602fa3d7d46f", size = 13182745, upload-time = "2025-08-07T19:05:18.709Z" }, + { url = "https://files.pythonhosted.org/packages/5e/c4/f2176a310f26e6160deaf661ef60db6c3bb62b7a35e57ae28f27a09a7d63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dbea798fc0065ad0b84a2947b0aff4233f0cb30f226f00a2c5850ca4393de609", size = 14206885, upload-time = "2025-08-07T19:05:21.025Z" }, + { url = "https://files.pythonhosted.org/packages/87/9d/98e162f3eeeb6689acbedbae5050b4b3220754554526c50c292b611d3a63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49ebcaccc2bdad86fd51b7864e3d808aad404aab8df33d469b6e65584656263a", size = 13639381, upload-time = "2025-08-07T19:05:23.423Z" }, + { url = "https://files.pythonhosted.org/packages/81/4e/1b7478b072fcde5161b48f64774d6edd59d6d198e4ba8918d9f4702b8043/ruff-0.12.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ac9c570634b98c71c88cb17badd90f13fc076a472ba6ef1d113d8ed3df109fb", size = 12613271, upload-time = "2025-08-07T19:05:25.507Z" }, + { url = "https://files.pythonhosted.org/packages/e8/67/0c3c9179a3ad19791ef1b8f7138aa27d4578c78700551c60d9260b2c660d/ruff-0.12.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:560e0cd641e45591a3e42cb50ef61ce07162b9c233786663fdce2d8557d99818", size = 12847783, upload-time = "2025-08-07T19:05:28.14Z" }, + { url = "https://files.pythonhosted.org/packages/4e/2a/0b6ac3dd045acf8aa229b12c9c17bb35508191b71a14904baf99573a21bd/ruff-0.12.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:71c83121512e7743fba5a8848c261dcc454cafb3ef2934a43f1b7a4eb5a447ea", size = 11702672, upload-time = "2025-08-07T19:05:30.413Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ee/f9fdc9f341b0430110de8b39a6ee5fa68c5706dc7c0aa940817947d6937e/ruff-0.12.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:de4429ef2ba091ecddedd300f4c3f24bca875d3d8b23340728c3cb0da81072c3", size = 11440626, upload-time = "2025-08-07T19:05:32.492Z" }, + { url = "https://files.pythonhosted.org/packages/89/fb/b3aa2d482d05f44e4d197d1de5e3863feb13067b22c571b9561085c999dc/ruff-0.12.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a2cab5f60d5b65b50fba39a8950c8746df1627d54ba1197f970763917184b161", size = 12462162, upload-time = "2025-08-07T19:05:34.449Z" }, + { url = "https://files.pythonhosted.org/packages/18/9f/5c5d93e1d00d854d5013c96e1a92c33b703a0332707a7cdbd0a4880a84fb/ruff-0.12.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:45c32487e14f60b88aad6be9fd5da5093dbefb0e3e1224131cb1d441d7cb7d46", size = 12913212, upload-time = "2025-08-07T19:05:36.541Z" }, + { url = "https://files.pythonhosted.org/packages/71/13/ab9120add1c0e4604c71bfc2e4ef7d63bebece0cfe617013da289539cef8/ruff-0.12.8-py3-none-win32.whl", hash = "sha256:daf3475060a617fd5bc80638aeaf2f5937f10af3ec44464e280a9d2218e720d3", size = 11694382, upload-time = "2025-08-07T19:05:38.468Z" }, + { url = "https://files.pythonhosted.org/packages/f6/dc/a2873b7c5001c62f46266685863bee2888caf469d1edac84bf3242074be2/ruff-0.12.8-py3-none-win_amd64.whl", hash = "sha256:7209531f1a1fcfbe8e46bcd7ab30e2f43604d8ba1c49029bb420b103d0b5f76e", size = 12740482, upload-time = "2025-08-07T19:05:40.391Z" }, + { url = "https://files.pythonhosted.org/packages/cb/5c/799a1efb8b5abab56e8a9f2a0b72d12bd64bb55815e9476c7d0a2887d2f7/ruff-0.12.8-py3-none-win_arm64.whl", hash = "sha256:c90e1a334683ce41b0e7a04f41790c429bf5073b62c1ae701c9dc5b3d14f0749", size = 11884718, upload-time = "2025-08-07T19:05:42.866Z" }, +] + +[[package]] +name = "simple-websocket" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wsproto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b0/d4/bfa032f961103eba93de583b161f0e6a5b63cebb8f2c7d0c6e6efe1e3d2e/simple_websocket-1.1.0.tar.gz", hash = "sha256:7939234e7aa067c534abdab3a9ed933ec9ce4691b0713c78acb195560aa52ae4", size = 17300, upload-time = "2024-10-10T22:39:31.412Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl", hash = "sha256:4af6069630a38ed6c561010f0e11a5bc0d4ca569b36306eb257cd9a192497c8c", size = 13842, upload-time = "2024-10-10T22:39:29.645Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "starlette" +version = "0.47.2" +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/04/57/d062573f391d062710d4088fa1369428c38d51460ab6fedff920efef932e/starlette-0.47.2.tar.gz", hash = "sha256:6ae9aa5db235e4846decc1e7b79c4f346adf41e9777aebeb49dfd09bbd7023d8", size = 2583948, upload-time = "2025-07-20T17:31:58.522Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/1f/b876b1f83aef204198a42dc101613fefccb32258e5428b5f9259677864b4/starlette-0.47.2-py3-none-any.whl", hash = "sha256:c5847e96134e5c5371ee9fac6fdf1a67336d5815e09eb2a01fdb57a351ef915b", size = 72984, upload-time = "2025-07-20T17:31:56.738Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.35.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, +] + +[package.optional-dependencies] +standard = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "httptools" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, + { name = "watchfiles" }, + { name = "websockets" }, +] + +[[package]] +name = "uvloop" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741, upload-time = "2024-10-14T23:38:35.489Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", size = 1471284, upload-time = "2024-10-14T23:37:47.833Z" }, + { url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2", size = 821349, upload-time = "2024-10-14T23:37:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", size = 4580089, upload-time = "2024-10-14T23:37:51.703Z" }, + { url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", size = 4693770, upload-time = "2024-10-14T23:37:54.122Z" }, + { url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", size = 4451321, upload-time = "2024-10-14T23:37:55.766Z" }, + { url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022, upload-time = "2024-10-14T23:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123, upload-time = "2024-10-14T23:38:00.688Z" }, + { url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325, upload-time = "2024-10-14T23:38:02.309Z" }, + { url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806, upload-time = "2024-10-14T23:38:04.711Z" }, + { url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", size = 4701068, upload-time = "2024-10-14T23:38:06.385Z" }, + { url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", size = 4454428, upload-time = "2024-10-14T23:38:08.416Z" }, + { url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", size = 4660018, upload-time = "2024-10-14T23:38:10.888Z" }, +] + +[[package]] +name = "vbuild" +version = "0.8.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pscript" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/be/f0c6204a36440bbcc086bfa25964d009b7391c5a3c74d6e73188efd47adb/vbuild-0.8.2.tar.gz", hash = "sha256:270cd9078349d907dfae6c0e6364a5a5e74cb86183bb5093613f12a18b435fa9", size = 8937, upload-time = "2023-08-03T09:26:36.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/3d/7b22abbdb059d551507275a2815bc2b1974e3b9f6a13781c1eac9e858965/vbuild-0.8.2-py2.py3-none-any.whl", hash = "sha256:d76bcc976a1c53b6a5776ac947606f9e7786c25df33a587ebe33ed09dd8a1076", size = 9371, upload-time = "2023-08-03T09:26:35.023Z" }, +] + +[[package]] +name = "virtualenv" +version = "20.33.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/60/4f20960df6c7b363a18a55ab034c8f2bcd5d9770d1f94f9370ec104c1855/virtualenv-20.33.1.tar.gz", hash = "sha256:1b44478d9e261b3fb8baa5e74a0ca3bc0e05f21aa36167bf9cbf850e542765b8", size = 6082160, upload-time = "2025-08-05T16:10:55.605Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/ff/ded57ac5ff40a09e6e198550bab075d780941e0b0f83cbeabd087c59383a/virtualenv-20.33.1-py3-none-any.whl", hash = "sha256:07c19bc66c11acab6a5958b815cbcee30891cd1c2ccf53785a28651a0d8d8a67", size = 6060362, upload-time = "2025-08-05T16:10:52.81Z" }, +] + +[[package]] +name = "watchfiles" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2a/9a/d451fcc97d029f5812e898fd30a53fd8c15c7bbd058fd75cfc6beb9bd761/watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575", size = 94406, upload-time = "2025-06-15T19:06:59.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/b8/858957045a38a4079203a33aaa7d23ea9269ca7761c8a074af3524fbb240/watchfiles-1.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9dc001c3e10de4725c749d4c2f2bdc6ae24de5a88a339c4bce32300a31ede179", size = 402339, upload-time = "2025-06-15T19:05:24.516Z" }, + { url = "https://files.pythonhosted.org/packages/80/28/98b222cca751ba68e88521fabd79a4fab64005fc5976ea49b53fa205d1fa/watchfiles-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9ba68ec283153dead62cbe81872d28e053745f12335d037de9cbd14bd1877f5", size = 394409, upload-time = "2025-06-15T19:05:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/50/dee79968566c03190677c26f7f47960aff738d32087087bdf63a5473e7df/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130fc497b8ee68dce163e4254d9b0356411d1490e868bd8790028bc46c5cc297", size = 450939, upload-time = "2025-06-15T19:05:26.494Z" }, + { url = "https://files.pythonhosted.org/packages/40/45/a7b56fb129700f3cfe2594a01aa38d033b92a33dddce86c8dfdfc1247b72/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50a51a90610d0845a5931a780d8e51d7bd7f309ebc25132ba975aca016b576a0", size = 457270, upload-time = "2025-06-15T19:05:27.466Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c8/fa5ef9476b1d02dc6b5e258f515fcaaecf559037edf8b6feffcbc097c4b8/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc44678a72ac0910bac46fa6a0de6af9ba1355669b3dfaf1ce5f05ca7a74364e", size = 483370, upload-time = "2025-06-15T19:05:28.548Z" }, + { url = "https://files.pythonhosted.org/packages/98/68/42cfcdd6533ec94f0a7aab83f759ec11280f70b11bfba0b0f885e298f9bd/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a543492513a93b001975ae283a51f4b67973662a375a403ae82f420d2c7205ee", size = 598654, upload-time = "2025-06-15T19:05:29.997Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/b2a1544224118cc28df7e59008a929e711f9c68ce7d554e171b2dc531352/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ac164e20d17cc285f2b94dc31c384bc3aa3dd5e7490473b3db043dd70fbccfd", size = 478667, upload-time = "2025-06-15T19:05:31.172Z" }, + { url = "https://files.pythonhosted.org/packages/8c/77/e3362fe308358dc9f8588102481e599c83e1b91c2ae843780a7ded939a35/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7590d5a455321e53857892ab8879dce62d1f4b04748769f5adf2e707afb9d4f", size = 452213, upload-time = "2025-06-15T19:05:32.299Z" }, + { url = "https://files.pythonhosted.org/packages/6e/17/c8f1a36540c9a1558d4faf08e909399e8133599fa359bf52ec8fcee5be6f/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:37d3d3f7defb13f62ece99e9be912afe9dd8a0077b7c45ee5a57c74811d581a4", size = 626718, upload-time = "2025-06-15T19:05:33.415Z" }, + { url = "https://files.pythonhosted.org/packages/26/45/fb599be38b4bd38032643783d7496a26a6f9ae05dea1a42e58229a20ac13/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7080c4bb3efd70a07b1cc2df99a7aa51d98685be56be6038c3169199d0a1c69f", size = 623098, upload-time = "2025-06-15T19:05:34.534Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/fdf40e038475498e160cd167333c946e45d8563ae4dd65caf757e9ffe6b4/watchfiles-1.1.0-cp312-cp312-win32.whl", hash = "sha256:cbcf8630ef4afb05dc30107bfa17f16c0896bb30ee48fc24bf64c1f970f3b1fd", size = 279209, upload-time = "2025-06-15T19:05:35.577Z" }, + { url = "https://files.pythonhosted.org/packages/3f/d3/3ae9d5124ec75143bdf088d436cba39812122edc47709cd2caafeac3266f/watchfiles-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:cbd949bdd87567b0ad183d7676feb98136cde5bb9025403794a4c0db28ed3a47", size = 292786, upload-time = "2025-06-15T19:05:36.559Z" }, + { url = "https://files.pythonhosted.org/packages/26/2f/7dd4fc8b5f2b34b545e19629b4a018bfb1de23b3a496766a2c1165ca890d/watchfiles-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:0a7d40b77f07be87c6faa93d0951a0fcd8cbca1ddff60a1b65d741bac6f3a9f6", size = 284343, upload-time = "2025-06-15T19:05:37.5Z" }, + { url = "https://files.pythonhosted.org/packages/d3/42/fae874df96595556a9089ade83be34a2e04f0f11eb53a8dbf8a8a5e562b4/watchfiles-1.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5007f860c7f1f8df471e4e04aaa8c43673429047d63205d1630880f7637bca30", size = 402004, upload-time = "2025-06-15T19:05:38.499Z" }, + { url = "https://files.pythonhosted.org/packages/fa/55/a77e533e59c3003d9803c09c44c3651224067cbe7fb5d574ddbaa31e11ca/watchfiles-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:20ecc8abbd957046f1fe9562757903f5eaf57c3bce70929fda6c7711bb58074a", size = 393671, upload-time = "2025-06-15T19:05:39.52Z" }, + { url = "https://files.pythonhosted.org/packages/05/68/b0afb3f79c8e832e6571022611adbdc36e35a44e14f129ba09709aa4bb7a/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2f0498b7d2a3c072766dba3274fe22a183dbea1f99d188f1c6c72209a1063dc", size = 449772, upload-time = "2025-06-15T19:05:40.897Z" }, + { url = "https://files.pythonhosted.org/packages/ff/05/46dd1f6879bc40e1e74c6c39a1b9ab9e790bf1f5a2fe6c08b463d9a807f4/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:239736577e848678e13b201bba14e89718f5c2133dfd6b1f7846fa1b58a8532b", size = 456789, upload-time = "2025-06-15T19:05:42.045Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ca/0eeb2c06227ca7f12e50a47a3679df0cd1ba487ea19cf844a905920f8e95/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff4b8d89f444f7e49136dc695599a591ff769300734446c0a86cba2eb2f9895", size = 482551, upload-time = "2025-06-15T19:05:43.781Z" }, + { url = "https://files.pythonhosted.org/packages/31/47/2cecbd8694095647406645f822781008cc524320466ea393f55fe70eed3b/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12b0a02a91762c08f7264e2e79542f76870c3040bbc847fb67410ab81474932a", size = 597420, upload-time = "2025-06-15T19:05:45.244Z" }, + { url = "https://files.pythonhosted.org/packages/d9/7e/82abc4240e0806846548559d70f0b1a6dfdca75c1b4f9fa62b504ae9b083/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29e7bc2eee15cbb339c68445959108803dc14ee0c7b4eea556400131a8de462b", size = 477950, upload-time = "2025-06-15T19:05:46.332Z" }, + { url = "https://files.pythonhosted.org/packages/25/0d/4d564798a49bf5482a4fa9416dea6b6c0733a3b5700cb8a5a503c4b15853/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9481174d3ed982e269c090f780122fb59cee6c3796f74efe74e70f7780ed94c", size = 451706, upload-time = "2025-06-15T19:05:47.459Z" }, + { url = "https://files.pythonhosted.org/packages/81/b5/5516cf46b033192d544102ea07c65b6f770f10ed1d0a6d388f5d3874f6e4/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:80f811146831c8c86ab17b640801c25dc0a88c630e855e2bef3568f30434d52b", size = 625814, upload-time = "2025-06-15T19:05:48.654Z" }, + { url = "https://files.pythonhosted.org/packages/0c/dd/7c1331f902f30669ac3e754680b6edb9a0dd06dea5438e61128111fadd2c/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:60022527e71d1d1fda67a33150ee42869042bce3d0fcc9cc49be009a9cded3fb", size = 622820, upload-time = "2025-06-15T19:05:50.088Z" }, + { url = "https://files.pythonhosted.org/packages/1b/14/36d7a8e27cd128d7b1009e7715a7c02f6c131be9d4ce1e5c3b73d0e342d8/watchfiles-1.1.0-cp313-cp313-win32.whl", hash = "sha256:32d6d4e583593cb8576e129879ea0991660b935177c0f93c6681359b3654bfa9", size = 279194, upload-time = "2025-06-15T19:05:51.186Z" }, + { url = "https://files.pythonhosted.org/packages/25/41/2dd88054b849aa546dbeef5696019c58f8e0774f4d1c42123273304cdb2e/watchfiles-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:f21af781a4a6fbad54f03c598ab620e3a77032c5878f3d780448421a6e1818c7", size = 292349, upload-time = "2025-06-15T19:05:52.201Z" }, + { url = "https://files.pythonhosted.org/packages/c8/cf/421d659de88285eb13941cf11a81f875c176f76a6d99342599be88e08d03/watchfiles-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:5366164391873ed76bfdf618818c82084c9db7fac82b64a20c44d335eec9ced5", size = 283836, upload-time = "2025-06-15T19:05:53.265Z" }, + { url = "https://files.pythonhosted.org/packages/45/10/6faf6858d527e3599cc50ec9fcae73590fbddc1420bd4fdccfebffeedbc6/watchfiles-1.1.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:17ab167cca6339c2b830b744eaf10803d2a5b6683be4d79d8475d88b4a8a4be1", size = 400343, upload-time = "2025-06-15T19:05:54.252Z" }, + { url = "https://files.pythonhosted.org/packages/03/20/5cb7d3966f5e8c718006d0e97dfe379a82f16fecd3caa7810f634412047a/watchfiles-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:328dbc9bff7205c215a7807da7c18dce37da7da718e798356212d22696404339", size = 392916, upload-time = "2025-06-15T19:05:55.264Z" }, + { url = "https://files.pythonhosted.org/packages/8c/07/d8f1176328fa9e9581b6f120b017e286d2a2d22ae3f554efd9515c8e1b49/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7208ab6e009c627b7557ce55c465c98967e8caa8b11833531fdf95799372633", size = 449582, upload-time = "2025-06-15T19:05:56.317Z" }, + { url = "https://files.pythonhosted.org/packages/66/e8/80a14a453cf6038e81d072a86c05276692a1826471fef91df7537dba8b46/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8f6f72974a19efead54195bc9bed4d850fc047bb7aa971268fd9a8387c89011", size = 456752, upload-time = "2025-06-15T19:05:57.359Z" }, + { url = "https://files.pythonhosted.org/packages/5a/25/0853b3fe0e3c2f5af9ea60eb2e781eade939760239a72c2d38fc4cc335f6/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d181ef50923c29cf0450c3cd47e2f0557b62218c50b2ab8ce2ecaa02bd97e670", size = 481436, upload-time = "2025-06-15T19:05:58.447Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9e/4af0056c258b861fbb29dcb36258de1e2b857be4a9509e6298abcf31e5c9/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adb4167043d3a78280d5d05ce0ba22055c266cf8655ce942f2fb881262ff3cdf", size = 596016, upload-time = "2025-06-15T19:05:59.59Z" }, + { url = "https://files.pythonhosted.org/packages/c5/fa/95d604b58aa375e781daf350897aaaa089cff59d84147e9ccff2447c8294/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5701dc474b041e2934a26d31d39f90fac8a3dee2322b39f7729867f932b1d4", size = 476727, upload-time = "2025-06-15T19:06:01.086Z" }, + { url = "https://files.pythonhosted.org/packages/65/95/fe479b2664f19be4cf5ceeb21be05afd491d95f142e72d26a42f41b7c4f8/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b067915e3c3936966a8607f6fe5487df0c9c4afb85226613b520890049deea20", size = 451864, upload-time = "2025-06-15T19:06:02.144Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8a/3c4af14b93a15ce55901cd7a92e1a4701910f1768c78fb30f61d2b79785b/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:9c733cda03b6d636b4219625a4acb5c6ffb10803338e437fb614fef9516825ef", size = 625626, upload-time = "2025-06-15T19:06:03.578Z" }, + { url = "https://files.pythonhosted.org/packages/da/f5/cf6aa047d4d9e128f4b7cde615236a915673775ef171ff85971d698f3c2c/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:cc08ef8b90d78bfac66f0def80240b0197008e4852c9f285907377b2947ffdcb", size = 622744, upload-time = "2025-06-15T19:06:05.066Z" }, + { url = "https://files.pythonhosted.org/packages/2c/00/70f75c47f05dea6fd30df90f047765f6fc2d6eb8b5a3921379b0b04defa2/watchfiles-1.1.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9974d2f7dc561cce3bb88dfa8eb309dab64c729de85fba32e98d75cf24b66297", size = 402114, upload-time = "2025-06-15T19:06:06.186Z" }, + { url = "https://files.pythonhosted.org/packages/53/03/acd69c48db4a1ed1de26b349d94077cca2238ff98fd64393f3e97484cae6/watchfiles-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c68e9f1fcb4d43798ad8814c4c1b61547b014b667216cb754e606bfade587018", size = 393879, upload-time = "2025-06-15T19:06:07.369Z" }, + { url = "https://files.pythonhosted.org/packages/2f/c8/a9a2a6f9c8baa4eceae5887fecd421e1b7ce86802bcfc8b6a942e2add834/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95ab1594377effac17110e1352989bdd7bdfca9ff0e5eeccd8c69c5389b826d0", size = 450026, upload-time = "2025-06-15T19:06:08.476Z" }, + { url = "https://files.pythonhosted.org/packages/fe/51/d572260d98388e6e2b967425c985e07d47ee6f62e6455cefb46a6e06eda5/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba9b62da882c1be1280a7584ec4515d0a6006a94d6e5819730ec2eab60ffe12", size = 457917, upload-time = "2025-06-15T19:06:09.988Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2d/4258e52917bf9f12909b6ec314ff9636276f3542f9d3807d143f27309104/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3434e401f3ce0ed6b42569128b3d1e3af773d7ec18751b918b89cd49c14eaafb", size = 483602, upload-time = "2025-06-15T19:06:11.088Z" }, + { url = "https://files.pythonhosted.org/packages/84/99/bee17a5f341a4345fe7b7972a475809af9e528deba056f8963d61ea49f75/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa257a4d0d21fcbca5b5fcba9dca5a78011cb93c0323fb8855c6d2dfbc76eb77", size = 596758, upload-time = "2025-06-15T19:06:12.197Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/e4bec1d59b25b89d2b0716b41b461ed655a9a53c60dc78ad5771fda5b3e6/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd1b3879a578a8ec2076c7961076df540b9af317123f84569f5a9ddee64ce92", size = 477601, upload-time = "2025-06-15T19:06:13.391Z" }, + { url = "https://files.pythonhosted.org/packages/1f/fa/a514292956f4a9ce3c567ec0c13cce427c158e9f272062685a8a727d08fc/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc7a30eeb0e20ecc5f4bd113cd69dcdb745a07c68c0370cea919f373f65d9e", size = 451936, upload-time = "2025-06-15T19:06:14.656Z" }, + { url = "https://files.pythonhosted.org/packages/32/5d/c3bf927ec3bbeb4566984eba8dd7a8eb69569400f5509904545576741f88/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:891c69e027748b4a73847335d208e374ce54ca3c335907d381fde4e41661b13b", size = 626243, upload-time = "2025-06-15T19:06:16.232Z" }, + { url = "https://files.pythonhosted.org/packages/e6/65/6e12c042f1a68c556802a84d54bb06d35577c81e29fba14019562479159c/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:12fe8eaffaf0faa7906895b4f8bb88264035b3f0243275e0bf24af0436b27259", size = 623073, upload-time = "2025-06-15T19:06:17.457Z" }, + { url = "https://files.pythonhosted.org/packages/89/ab/7f79d9bf57329e7cbb0a6fd4c7bd7d0cee1e4a8ef0041459f5409da3506c/watchfiles-1.1.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:bfe3c517c283e484843cb2e357dd57ba009cff351edf45fb455b5fbd1f45b15f", size = 400872, upload-time = "2025-06-15T19:06:18.57Z" }, + { url = "https://files.pythonhosted.org/packages/df/d5/3f7bf9912798e9e6c516094db6b8932df53b223660c781ee37607030b6d3/watchfiles-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a9ccbf1f129480ed3044f540c0fdbc4ee556f7175e5ab40fe077ff6baf286d4e", size = 392877, upload-time = "2025-06-15T19:06:19.55Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c5/54ec7601a2798604e01c75294770dbee8150e81c6e471445d7601610b495/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba0e3255b0396cac3cc7bbace76404dd72b5438bf0d8e7cefa2f79a7f3649caa", size = 449645, upload-time = "2025-06-15T19:06:20.66Z" }, + { url = "https://files.pythonhosted.org/packages/0a/04/c2f44afc3b2fce21ca0b7802cbd37ed90a29874f96069ed30a36dfe57c2b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4281cd9fce9fc0a9dbf0fc1217f39bf9cf2b4d315d9626ef1d4e87b84699e7e8", size = 457424, upload-time = "2025-06-15T19:06:21.712Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b0/eec32cb6c14d248095261a04f290636da3df3119d4040ef91a4a50b29fa5/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d2404af8db1329f9a3c9b79ff63e0ae7131986446901582067d9304ae8aaf7f", size = 481584, upload-time = "2025-06-15T19:06:22.777Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/ca4bb71c68a937d7145aa25709e4f5d68eb7698a25ce266e84b55d591bbd/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e78b6ed8165996013165eeabd875c5dfc19d41b54f94b40e9fff0eb3193e5e8e", size = 596675, upload-time = "2025-06-15T19:06:24.226Z" }, + { url = "https://files.pythonhosted.org/packages/a1/dd/b0e4b7fb5acf783816bc950180a6cd7c6c1d2cf7e9372c0ea634e722712b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:249590eb75ccc117f488e2fabd1bfa33c580e24b96f00658ad88e38844a040bb", size = 477363, upload-time = "2025-06-15T19:06:25.42Z" }, + { url = "https://files.pythonhosted.org/packages/69/c4/088825b75489cb5b6a761a4542645718893d395d8c530b38734f19da44d2/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05686b5487cfa2e2c28ff1aa370ea3e6c5accfe6435944ddea1e10d93872147", size = 452240, upload-time = "2025-06-15T19:06:26.552Z" }, + { url = "https://files.pythonhosted.org/packages/10/8c/22b074814970eeef43b7c44df98c3e9667c1f7bf5b83e0ff0201b0bd43f9/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d0e10e6f8f6dc5762adee7dece33b722282e1f59aa6a55da5d493a97282fedd8", size = 625607, upload-time = "2025-06-15T19:06:27.606Z" }, + { url = "https://files.pythonhosted.org/packages/32/fa/a4f5c2046385492b2273213ef815bf71a0d4c1943b784fb904e184e30201/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:af06c863f152005c7592df1d6a7009c836a247c9d8adb78fef8575a5a98699db", size = 623315, upload-time = "2025-06-15T19:06:29.076Z" }, +] + +[[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/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/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +] + +[[package]] +name = "wsproto" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425, upload-time = "2022-08-23T19:58:21.447Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226, upload-time = "2022-08-23T19:58:19.96Z" }, +] + +[[package]] +name = "yarl" +version = "1.20.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/fb/efaa23fa4e45537b827620f04cf8f3cd658b76642205162e072703a5b963/yarl-1.20.1.tar.gz", hash = "sha256:d017a4997ee50c91fd5466cef416231bb82177b93b029906cefc542ce14c35ac", size = 186428, upload-time = "2025-06-10T00:46:09.923Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/9a/cb7fad7d73c69f296eda6815e4a2c7ed53fc70c2f136479a91c8e5fbdb6d/yarl-1.20.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdcc4cd244e58593a4379fe60fdee5ac0331f8eb70320a24d591a3be197b94a9", size = 133667, upload-time = "2025-06-10T00:43:44.369Z" }, + { url = "https://files.pythonhosted.org/packages/67/38/688577a1cb1e656e3971fb66a3492501c5a5df56d99722e57c98249e5b8a/yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a", size = 91025, upload-time = "2025-06-10T00:43:46.295Z" }, + { url = "https://files.pythonhosted.org/packages/50/ec/72991ae51febeb11a42813fc259f0d4c8e0507f2b74b5514618d8b640365/yarl-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1112ae8154186dfe2de4732197f59c05a83dc814849a5ced892b708033f40dc2", size = 89709, upload-time = "2025-06-10T00:43:48.22Z" }, + { url = "https://files.pythonhosted.org/packages/99/da/4d798025490e89426e9f976702e5f9482005c548c579bdae792a4c37769e/yarl-1.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90bbd29c4fe234233f7fa2b9b121fb63c321830e5d05b45153a2ca68f7d310ee", size = 352287, upload-time = "2025-06-10T00:43:49.924Z" }, + { url = "https://files.pythonhosted.org/packages/1a/26/54a15c6a567aac1c61b18aa0f4b8aa2e285a52d547d1be8bf48abe2b3991/yarl-1.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:680e19c7ce3710ac4cd964e90dad99bf9b5029372ba0c7cbfcd55e54d90ea819", size = 345429, upload-time = "2025-06-10T00:43:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/d6/95/9dcf2386cb875b234353b93ec43e40219e14900e046bf6ac118f94b1e353/yarl-1.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a979218c1fdb4246a05efc2cc23859d47c89af463a90b99b7c56094daf25a16", size = 365429, upload-time = "2025-06-10T00:43:53.494Z" }, + { url = "https://files.pythonhosted.org/packages/91/b2/33a8750f6a4bc224242a635f5f2cff6d6ad5ba651f6edcccf721992c21a0/yarl-1.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255b468adf57b4a7b65d8aad5b5138dce6a0752c139965711bdcb81bc370e1b6", size = 363862, upload-time = "2025-06-10T00:43:55.766Z" }, + { url = "https://files.pythonhosted.org/packages/98/28/3ab7acc5b51f4434b181b0cee8f1f4b77a65919700a355fb3617f9488874/yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd", size = 355616, upload-time = "2025-06-10T00:43:58.056Z" }, + { url = "https://files.pythonhosted.org/packages/36/a3/f666894aa947a371724ec7cd2e5daa78ee8a777b21509b4252dd7bd15e29/yarl-1.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8570d998db4ddbfb9a590b185a0a33dbf8aafb831d07a5257b4ec9948df9cb0a", size = 339954, upload-time = "2025-06-10T00:43:59.773Z" }, + { url = "https://files.pythonhosted.org/packages/f1/81/5f466427e09773c04219d3450d7a1256138a010b6c9f0af2d48565e9ad13/yarl-1.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:97c75596019baae7c71ccf1d8cc4738bc08134060d0adfcbe5642f778d1dca38", size = 365575, upload-time = "2025-06-10T00:44:02.051Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e3/e4b0ad8403e97e6c9972dd587388940a032f030ebec196ab81a3b8e94d31/yarl-1.20.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c48912653e63aef91ff988c5432832692ac5a1d8f0fb8a33091520b5bbe19ef", size = 365061, upload-time = "2025-06-10T00:44:04.196Z" }, + { url = "https://files.pythonhosted.org/packages/ac/99/b8a142e79eb86c926f9f06452eb13ecb1bb5713bd01dc0038faf5452e544/yarl-1.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4c3ae28f3ae1563c50f3d37f064ddb1511ecc1d5584e88c6b7c63cf7702a6d5f", size = 364142, upload-time = "2025-06-10T00:44:06.527Z" }, + { url = "https://files.pythonhosted.org/packages/34/f2/08ed34a4a506d82a1a3e5bab99ccd930a040f9b6449e9fd050320e45845c/yarl-1.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e9642f27036283550f5f57dc6156c51084b458570b9d0d96100c8bebb186a8", size = 381894, upload-time = "2025-06-10T00:44:08.379Z" }, + { url = "https://files.pythonhosted.org/packages/92/f8/9a3fbf0968eac704f681726eff595dce9b49c8a25cd92bf83df209668285/yarl-1.20.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2c26b0c49220d5799f7b22c6838409ee9bc58ee5c95361a4d7831f03cc225b5a", size = 383378, upload-time = "2025-06-10T00:44:10.51Z" }, + { url = "https://files.pythonhosted.org/packages/af/85/9363f77bdfa1e4d690957cd39d192c4cacd1c58965df0470a4905253b54f/yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004", size = 374069, upload-time = "2025-06-10T00:44:12.834Z" }, + { url = "https://files.pythonhosted.org/packages/35/99/9918c8739ba271dcd935400cff8b32e3cd319eaf02fcd023d5dcd487a7c8/yarl-1.20.1-cp312-cp312-win32.whl", hash = "sha256:daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5", size = 81249, upload-time = "2025-06-10T00:44:14.731Z" }, + { url = "https://files.pythonhosted.org/packages/eb/83/5d9092950565481b413b31a23e75dd3418ff0a277d6e0abf3729d4d1ce25/yarl-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698", size = 86710, upload-time = "2025-06-10T00:44:16.716Z" }, + { url = "https://files.pythonhosted.org/packages/8a/e1/2411b6d7f769a07687acee88a062af5833cf1966b7266f3d8dfb3d3dc7d3/yarl-1.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0b5ff0fbb7c9f1b1b5ab53330acbfc5247893069e7716840c8e7d5bb7355038a", size = 131811, upload-time = "2025-06-10T00:44:18.933Z" }, + { url = "https://files.pythonhosted.org/packages/b2/27/584394e1cb76fb771371770eccad35de400e7b434ce3142c2dd27392c968/yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3", size = 90078, upload-time = "2025-06-10T00:44:20.635Z" }, + { url = "https://files.pythonhosted.org/packages/bf/9a/3246ae92d4049099f52d9b0fe3486e3b500e29b7ea872d0f152966fc209d/yarl-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f60e4ad5db23f0b96e49c018596707c3ae89f5d0bd97f0ad3684bcbad899f1e7", size = 88748, upload-time = "2025-06-10T00:44:22.34Z" }, + { url = "https://files.pythonhosted.org/packages/a3/25/35afe384e31115a1a801fbcf84012d7a066d89035befae7c5d4284df1e03/yarl-1.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49bdd1b8e00ce57e68ba51916e4bb04461746e794e7c4d4bbc42ba2f18297691", size = 349595, upload-time = "2025-06-10T00:44:24.314Z" }, + { url = "https://files.pythonhosted.org/packages/28/2d/8aca6cb2cabc8f12efcb82749b9cefecbccfc7b0384e56cd71058ccee433/yarl-1.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:66252d780b45189975abfed839616e8fd2dbacbdc262105ad7742c6ae58f3e31", size = 342616, upload-time = "2025-06-10T00:44:26.167Z" }, + { url = "https://files.pythonhosted.org/packages/0b/e9/1312633d16b31acf0098d30440ca855e3492d66623dafb8e25b03d00c3da/yarl-1.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59174e7332f5d153d8f7452a102b103e2e74035ad085f404df2e40e663a22b28", size = 361324, upload-time = "2025-06-10T00:44:27.915Z" }, + { url = "https://files.pythonhosted.org/packages/bc/a0/688cc99463f12f7669eec7c8acc71ef56a1521b99eab7cd3abb75af887b0/yarl-1.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3968ec7d92a0c0f9ac34d5ecfd03869ec0cab0697c91a45db3fbbd95fe1b653", size = 359676, upload-time = "2025-06-10T00:44:30.041Z" }, + { url = "https://files.pythonhosted.org/packages/af/44/46407d7f7a56e9a85a4c207724c9f2c545c060380718eea9088f222ba697/yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5", size = 352614, upload-time = "2025-06-10T00:44:32.171Z" }, + { url = "https://files.pythonhosted.org/packages/b1/91/31163295e82b8d5485d31d9cf7754d973d41915cadce070491778d9c9825/yarl-1.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a62c839c3a8eac2410e951301309426f368388ff2f33799052787035793b02", size = 336766, upload-time = "2025-06-10T00:44:34.494Z" }, + { url = "https://files.pythonhosted.org/packages/b4/8e/c41a5bc482121f51c083c4c2bcd16b9e01e1cf8729e380273a952513a21f/yarl-1.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:041eaa14f73ff5a8986b4388ac6bb43a77f2ea09bf1913df7a35d4646db69e53", size = 364615, upload-time = "2025-06-10T00:44:36.856Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5b/61a3b054238d33d70ea06ebba7e58597891b71c699e247df35cc984ab393/yarl-1.20.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:377fae2fef158e8fd9d60b4c8751387b8d1fb121d3d0b8e9b0be07d1b41e83dc", size = 360982, upload-time = "2025-06-10T00:44:39.141Z" }, + { url = "https://files.pythonhosted.org/packages/df/a3/6a72fb83f8d478cb201d14927bc8040af901811a88e0ff2da7842dd0ed19/yarl-1.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1c92f4390e407513f619d49319023664643d3339bd5e5a56a3bebe01bc67ec04", size = 369792, upload-time = "2025-06-10T00:44:40.934Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/4cc3c36dfc7c077f8dedb561eb21f69e1e9f2456b91b593882b0b18c19dc/yarl-1.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d25ddcf954df1754ab0f86bb696af765c5bfaba39b74095f27eececa049ef9a4", size = 382049, upload-time = "2025-06-10T00:44:42.854Z" }, + { url = "https://files.pythonhosted.org/packages/19/3a/e54e2c4752160115183a66dc9ee75a153f81f3ab2ba4bf79c3c53b33de34/yarl-1.20.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:909313577e9619dcff8c31a0ea2aa0a2a828341d92673015456b3ae492e7317b", size = 384774, upload-time = "2025-06-10T00:44:45.275Z" }, + { url = "https://files.pythonhosted.org/packages/9c/20/200ae86dabfca89060ec6447649f219b4cbd94531e425e50d57e5f5ac330/yarl-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:793fd0580cb9664548c6b83c63b43c477212c0260891ddf86809e1c06c8b08f1", size = 374252, upload-time = "2025-06-10T00:44:47.31Z" }, + { url = "https://files.pythonhosted.org/packages/83/75/11ee332f2f516b3d094e89448da73d557687f7d137d5a0f48c40ff211487/yarl-1.20.1-cp313-cp313-win32.whl", hash = "sha256:468f6e40285de5a5b3c44981ca3a319a4b208ccc07d526b20b12aeedcfa654b7", size = 81198, upload-time = "2025-06-10T00:44:49.164Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/39b1ecbf51620b40ab402b0fc817f0ff750f6d92712b44689c2c215be89d/yarl-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:495b4ef2fea40596bfc0affe3837411d6aa3371abcf31aac0ccc4bdd64d4ef5c", size = 86346, upload-time = "2025-06-10T00:44:51.182Z" }, + { url = "https://files.pythonhosted.org/packages/43/c7/669c52519dca4c95153c8ad96dd123c79f354a376346b198f438e56ffeb4/yarl-1.20.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f60233b98423aab21d249a30eb27c389c14929f47be8430efa7dbd91493a729d", size = 138826, upload-time = "2025-06-10T00:44:52.883Z" }, + { url = "https://files.pythonhosted.org/packages/6a/42/fc0053719b44f6ad04a75d7f05e0e9674d45ef62f2d9ad2c1163e5c05827/yarl-1.20.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6f3eff4cc3f03d650d8755c6eefc844edde99d641d0dcf4da3ab27141a5f8ddf", size = 93217, upload-time = "2025-06-10T00:44:54.658Z" }, + { url = "https://files.pythonhosted.org/packages/4f/7f/fa59c4c27e2a076bba0d959386e26eba77eb52ea4a0aac48e3515c186b4c/yarl-1.20.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:69ff8439d8ba832d6bed88af2c2b3445977eba9a4588b787b32945871c2444e3", size = 92700, upload-time = "2025-06-10T00:44:56.784Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d4/062b2f48e7c93481e88eff97a6312dca15ea200e959f23e96d8ab898c5b8/yarl-1.20.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf34efa60eb81dd2645a2e13e00bb98b76c35ab5061a3989c7a70f78c85006d", size = 347644, upload-time = "2025-06-10T00:44:59.071Z" }, + { url = "https://files.pythonhosted.org/packages/89/47/78b7f40d13c8f62b499cc702fdf69e090455518ae544c00a3bf4afc9fc77/yarl-1.20.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8e0fe9364ad0fddab2688ce72cb7a8e61ea42eff3c7caeeb83874a5d479c896c", size = 323452, upload-time = "2025-06-10T00:45:01.605Z" }, + { url = "https://files.pythonhosted.org/packages/eb/2b/490d3b2dc66f52987d4ee0d3090a147ea67732ce6b4d61e362c1846d0d32/yarl-1.20.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f64fbf81878ba914562c672024089e3401974a39767747691c65080a67b18c1", size = 346378, upload-time = "2025-06-10T00:45:03.946Z" }, + { url = "https://files.pythonhosted.org/packages/66/ad/775da9c8a94ce925d1537f939a4f17d782efef1f973039d821cbe4bcc211/yarl-1.20.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6342d643bf9a1de97e512e45e4b9560a043347e779a173250824f8b254bd5ce", size = 353261, upload-time = "2025-06-10T00:45:05.992Z" }, + { url = "https://files.pythonhosted.org/packages/4b/23/0ed0922b47a4f5c6eb9065d5ff1e459747226ddce5c6a4c111e728c9f701/yarl-1.20.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56dac5f452ed25eef0f6e3c6a066c6ab68971d96a9fb441791cad0efba6140d3", size = 335987, upload-time = "2025-06-10T00:45:08.227Z" }, + { url = "https://files.pythonhosted.org/packages/3e/49/bc728a7fe7d0e9336e2b78f0958a2d6b288ba89f25a1762407a222bf53c3/yarl-1.20.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7d7f497126d65e2cad8dc5f97d34c27b19199b6414a40cb36b52f41b79014be", size = 329361, upload-time = "2025-06-10T00:45:10.11Z" }, + { url = "https://files.pythonhosted.org/packages/93/8f/b811b9d1f617c83c907e7082a76e2b92b655400e61730cd61a1f67178393/yarl-1.20.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:67e708dfb8e78d8a19169818eeb5c7a80717562de9051bf2413aca8e3696bf16", size = 346460, upload-time = "2025-06-10T00:45:12.055Z" }, + { url = "https://files.pythonhosted.org/packages/70/fd/af94f04f275f95da2c3b8b5e1d49e3e79f1ed8b6ceb0f1664cbd902773ff/yarl-1.20.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:595c07bc79af2494365cc96ddeb772f76272364ef7c80fb892ef9d0649586513", size = 334486, upload-time = "2025-06-10T00:45:13.995Z" }, + { url = "https://files.pythonhosted.org/packages/84/65/04c62e82704e7dd0a9b3f61dbaa8447f8507655fd16c51da0637b39b2910/yarl-1.20.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7bdd2f80f4a7df852ab9ab49484a4dee8030023aa536df41f2d922fd57bf023f", size = 342219, upload-time = "2025-06-10T00:45:16.479Z" }, + { url = "https://files.pythonhosted.org/packages/91/95/459ca62eb958381b342d94ab9a4b6aec1ddec1f7057c487e926f03c06d30/yarl-1.20.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c03bfebc4ae8d862f853a9757199677ab74ec25424d0ebd68a0027e9c639a390", size = 350693, upload-time = "2025-06-10T00:45:18.399Z" }, + { url = "https://files.pythonhosted.org/packages/a6/00/d393e82dd955ad20617abc546a8f1aee40534d599ff555ea053d0ec9bf03/yarl-1.20.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:344d1103e9c1523f32a5ed704d576172d2cabed3122ea90b1d4e11fe17c66458", size = 355803, upload-time = "2025-06-10T00:45:20.677Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ed/c5fb04869b99b717985e244fd93029c7a8e8febdfcffa06093e32d7d44e7/yarl-1.20.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88cab98aa4e13e1ade8c141daeedd300a4603b7132819c484841bb7af3edce9e", size = 341709, upload-time = "2025-06-10T00:45:23.221Z" }, + { url = "https://files.pythonhosted.org/packages/24/fd/725b8e73ac2a50e78a4534ac43c6addf5c1c2d65380dd48a9169cc6739a9/yarl-1.20.1-cp313-cp313t-win32.whl", hash = "sha256:b121ff6a7cbd4abc28985b6028235491941b9fe8fe226e6fdc539c977ea1739d", size = 86591, upload-time = "2025-06-10T00:45:25.793Z" }, + { url = "https://files.pythonhosted.org/packages/94/c3/b2e9f38bc3e11191981d57ea08cab2166e74ea770024a646617c9cddd9f6/yarl-1.20.1-cp313-cp313t-win_amd64.whl", hash = "sha256:541d050a355bbbc27e55d906bc91cb6fe42f96c01413dd0f4ed5a5240513874f", size = 93003, upload-time = "2025-06-10T00:45:27.752Z" }, + { url = "https://files.pythonhosted.org/packages/b4/2d/2345fce04cfd4bee161bf1e7d9cdc702e3e16109021035dbb24db654a622/yarl-1.20.1-py3-none-any.whl", hash = "sha256:83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77", size = 46542, upload-time = "2025-06-10T00:46:07.521Z" }, +] From d9de2d06058cfada8049a59642026d927c2c1301 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sun, 10 Aug 2025 15:27:25 +0100 Subject: [PATCH 006/198] Add colour select input --- src/editor/main.py | 23 ++++++++++++++++++++++- src/editor/scripts/editor.py | 16 +++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 1ad18b0f..e4a361f8 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -1,18 +1,39 @@ from nicegui import app, ui +from nicegui.events import ValueChangeEventArguments app.add_static_files("/scripts", "scripts") +def handle_colour_change(_: ValueChangeEventArguments) -> None: + """Handle colour change. + + Args: + _ (ValueChangeEventArguments): Change event + + """ + ui.run_javascript(""" + var event = new Event('change'); + document.querySelector(".colour-picker div div div input").dispatchEvent(event); + """) + + ui.add_head_html(""" """) +picker = ui.color_input( + label="Color", + value="#000000", + on_change=handle_colour_change, +).classes("colour-picker") + + ui.add_body_html("""
- + """) ui.run() diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 9824f7d2..1226adff 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -1,4 +1,4 @@ -from js import Math, MouseEvent, document, window +from js import Event, Math, MouseEvent, document, window from pyscript import when canvas = document.getElementById("image-canvas") @@ -112,3 +112,17 @@ def canvas_click(event: MouseEvent) -> None: ctx.beginPath() ctx.ellipse(x, y, ctx.lineWidth / 6, ctx.lineWidth / 6, 0, 0, 2 * Math.PI) ctx.stroke() + + +@when( + "change", + ".colour-picker div div div input", +) +def colour_change(event: Event) -> None: + """Handle colour change. + + Args: + event (Event): Change event + + """ + ctx.strokeStyle = event.target.value From a0de0a7aad57c7082e6e626556dc54e284ea73bc Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sun, 10 Aug 2025 16:07:26 +0100 Subject: [PATCH 007/198] Add line width input. --- src/editor/main.py | 32 ++++++++++++++++---------------- src/editor/scripts/editor.py | 30 +++++++++++++++++++----------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index e4a361f8..8dad7a54 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -1,33 +1,33 @@ from nicegui import app, ui -from nicegui.events import ValueChangeEventArguments app.add_static_files("/scripts", "scripts") -def handle_colour_change(_: ValueChangeEventArguments) -> None: - """Handle colour change. - - Args: - _ (ValueChangeEventArguments): Change event - - """ - ui.run_javascript(""" - var event = new Event('change'); - document.querySelector(".colour-picker div div div input").dispatchEvent(event); - """) - - ui.add_head_html(""" """) -picker = ui.color_input( +ui.color_input( label="Color", value="#000000", - on_change=handle_colour_change, + on_change=lambda _: ui.run_javascript(""" + var event = new Event('change'); + document.querySelector(".colour-picker div div div input").dispatchEvent(event); + """), ).classes("colour-picker") +ui.label("Line width") +ui.slider( + min=1, + max=20, + value=5, + on_change=lambda _: ui.run_javascript(""" + var event = new Event('change'); + document.querySelector(".width-input").dispatchEvent(event); + """), +).classes("width-input") + ui.add_body_html("""
diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 1226adff..5cf438eb 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -20,7 +20,7 @@ ctx.lineCap = "round" ctx.lineJoin = "round" -drawing = False +ctx.drawing = False rect = canvas.getBoundingClientRect() @@ -47,8 +47,7 @@ def start_path(event: MouseEvent) -> None: event (MouseEvent): The mouse event """ - global drawing - drawing = True + ctx.drawing = True x, y = get_canvas_coords(event) ctx.beginPath() ctx.moveTo(x, y) @@ -62,7 +61,7 @@ def mouse_tracker(event: MouseEvent) -> None: event (MouseEvent): The mouse event """ - if not drawing: + if not ctx.drawing: return x, y = get_canvas_coords(event) ctx.lineTo(x, y) @@ -77,10 +76,9 @@ def stop_path(_: MouseEvent) -> None: event (MouseEvent): The mouse event """ - global drawing - if not drawing: + if not ctx.drawing: return - drawing = False + ctx.drawing = False @when("mouseout", "#image-canvas") @@ -91,13 +89,12 @@ def leaves_canvas(event: MouseEvent) -> None: event (MouseEvent): The mouse event """ - global drawing - if not drawing: + if not ctx.drawing: return x, y = get_canvas_coords(event) ctx.lineTo(x, y) ctx.stroke() # Draws the line to the point on the edge where the mouse leaves the canvas - drawing = False + ctx.drawing = False @when("click", "#image-canvas") @@ -110,7 +107,7 @@ def canvas_click(event: MouseEvent) -> None: """ x, y = get_canvas_coords(event) ctx.beginPath() - ctx.ellipse(x, y, ctx.lineWidth / 6, ctx.lineWidth / 6, 0, 0, 2 * Math.PI) + ctx.ellipse(x, y, ctx.lineWidth / 6, ctx.lineWidth / 6, 0, 0, 2 * Math.PI) # Put a dot here ctx.stroke() @@ -126,3 +123,14 @@ def colour_change(event: Event) -> None: """ ctx.strokeStyle = event.target.value + + +@when("change", ".width-input") +def width_change(event: Event) -> None: + """Handle colour change. + + Args: + event (Event): Change event + + """ + ctx.lineWidth = int(event.target.getAttribute("aria-valuenow")) From 525644e7bdd24115ec2363eefb87418cd6d1bcf2 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sun, 10 Aug 2025 17:10:02 +0100 Subject: [PATCH 008/198] Add pen and erase toggle. Does not affect canvas yet. --- src/editor/main.py | 20 +++++++++++++++----- src/editor/scripts/editor.py | 16 ++++++++++++++-- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 8dad7a54..3e09a744 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -8,11 +8,24 @@ """) +ui.element("canvas").props("id='image-canvas' style='border: 1px solid black;'") + +ui.toggle( + {"pen": "🖊️", "eraser": "🧽"}, + value="pen", + on_change=lambda e: ui.run_javascript(f""" + const event = new Event('change'); + const actionSelect = document.querySelector("#action-select"); + actionSelect.setAttribute("value", "{e.value}"); + actionSelect.dispatchEvent(event); + """), +).props("id='action-select'") + ui.color_input( label="Color", value="#000000", on_change=lambda _: ui.run_javascript(""" - var event = new Event('change'); + const event = new Event('change'); document.querySelector(".colour-picker div div div input").dispatchEvent(event); """), ).classes("colour-picker") @@ -23,16 +36,13 @@ max=20, value=5, on_change=lambda _: ui.run_javascript(""" - var event = new Event('change'); + const event = new Event('change'); document.querySelector(".width-input").dispatchEvent(event); """), ).classes("width-input") ui.add_body_html(""" -
- -
""") diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 5cf438eb..2fee4e62 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -21,6 +21,7 @@ ctx.lineJoin = "round" ctx.drawing = False +ctx.action = "draw" rect = canvas.getBoundingClientRect() @@ -34,8 +35,8 @@ def get_canvas_coords(event: MouseEvent) -> tuple[float, float]: tuple[float, float]: The x and y coordinates """ - x = (event.clientX - rect.left) * SCALE - y = (event.clientY - rect.top) * SCALE + x = (event.pageX - rect.left) * SCALE + y = (event.pageY - rect.top) * SCALE return (x, y) @@ -134,3 +135,14 @@ def width_change(event: Event) -> None: """ ctx.lineWidth = int(event.target.getAttribute("aria-valuenow")) + + +@when("change", "#action-select") +def action_change(event: Event) -> None: + """Handle action change. + + Args: + event (Event): Change event + + """ + ctx.action = event.target.getAttribute("value") From e096088747cfbc00942ead965603eb8f179d0cf8 Mon Sep 17 00:00:00 2001 From: PiLogic Date: Sun, 10 Aug 2025 18:09:13 +0100 Subject: [PATCH 009/198] Added eraser feature --- src/editor/scripts/editor.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 2fee4e62..7c9de758 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -21,7 +21,7 @@ ctx.lineJoin = "round" ctx.drawing = False -ctx.action = "draw" +ctx.action = "pen" rect = canvas.getBoundingClientRect() @@ -106,12 +106,14 @@ def canvas_click(event: MouseEvent) -> None: event (MouseEvent): The mouse event """ + x, y = get_canvas_coords(event) ctx.beginPath() ctx.ellipse(x, y, ctx.lineWidth / 6, ctx.lineWidth / 6, 0, 0, 2 * Math.PI) # Put a dot here - ctx.stroke() - - + if ctx.action == 'pen': + ctx.stroke() + elif ctx.action == 'eraser': + ctx.fill() @when( "change", ".colour-picker div div div input", @@ -145,4 +147,9 @@ def action_change(event: Event) -> None: event (Event): Change event """ - ctx.action = event.target.getAttribute("value") + ctx.action = event.target.getAttribute("value") + if ctx.action == 'pen': + ctx.globalCompositeOperation = "source-over" + else: + ctx.globalCompositeOperation = "destination-out" + From 7fd73e8c247656999df5895d1f3f3be192a8a066 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sun, 10 Aug 2025 18:36:43 +0100 Subject: [PATCH 010/198] Add layout. Add dark mode. Fix clicking. Add resize window event handler to resize canvas. --- src/editor/main.py | 69 +++++++++++++++++++----------------- src/editor/scripts/editor.py | 66 +++++++++++++++++++++++++++------- 2 files changed, 90 insertions(+), 45 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 3e09a744..12ac7e33 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -8,39 +8,42 @@ """) -ui.element("canvas").props("id='image-canvas' style='border: 1px solid black;'") - -ui.toggle( - {"pen": "🖊️", "eraser": "🧽"}, - value="pen", - on_change=lambda e: ui.run_javascript(f""" - const event = new Event('change'); - const actionSelect = document.querySelector("#action-select"); - actionSelect.setAttribute("value", "{e.value}"); - actionSelect.dispatchEvent(event); - """), -).props("id='action-select'") - -ui.color_input( - label="Color", - value="#000000", - on_change=lambda _: ui.run_javascript(""" - const event = new Event('change'); - document.querySelector(".colour-picker div div div input").dispatchEvent(event); - """), -).classes("colour-picker") - -ui.label("Line width") -ui.slider( - min=1, - max=20, - value=5, - on_change=lambda _: ui.run_javascript(""" - const event = new Event('change'); - document.querySelector(".width-input").dispatchEvent(event); - """), -).classes("width-input") - +with ui.row(): + with ui.column(): + dark = ui.dark_mode() + ui.switch("Dark mode").bind_value(dark) + ui.toggle( + {"pen": "🖊️", "eraser": "🧽"}, + value="pen", + on_change=lambda e: ui.run_javascript(f""" + const event = new Event('change'); + const actionSelect = document.querySelector("#action-select"); + actionSelect.setAttribute("value", "{e.value}"); + actionSelect.dispatchEvent(event); + """), + ).props("id='action-select'") + + ui.color_input( + label="Color", + value="#000000", + on_change=lambda _: ui.run_javascript(""" + const event = new Event('change'); + document.querySelector(".colour-picker div div div input").dispatchEvent(event); + """), + ).classes("colour-picker") + + ui.label("Line width") + ui.slider( + min=1, + max=50, + value=5, + on_change=lambda _: ui.run_javascript(""" + const event = new Event('change'); + document.querySelector(".width-input").dispatchEvent(event); + """), + ).classes("width-input") + + ui.element("canvas").props("id='image-canvas'").style("border: 1px solid black; background-color: white;") ui.add_body_html(""" diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 2fee4e62..05f7fb1c 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -1,28 +1,33 @@ -from js import Event, Math, MouseEvent, document, window +from js import Event, Math, MouseEvent, Object, document, window +from pyodide.ffi import create_proxy from pyscript import when canvas = document.getElementById("image-canvas") -ctx = canvas.getContext("2d") -display_height = window.innerHeight * 0.8 -display_width = display_height * (2**0.5) +settings = Object() +settings.willReadFrequently = True -SCALE = 2 +ctx = canvas.getContext("2d", settings) -canvas.style.height = f"{display_height}px" # 80vh -canvas.style.width = f"{display_width}px" # Same ratio as an A4 sheet of paper +display_height = window.innerHeight * 0.95 # 95vh +display_width = display_height * (2**0.5) # Same ratio as an A4 sheet of paper + +SCALE = 2 # Better resolution + +canvas.style.height = f"{display_height}px" +canvas.style.width = f"{display_width}px" canvas.height = display_height * SCALE canvas.width = display_width * SCALE ctx.strokeStyle = "black" -ctx.lineWidth = 10 +ctx.lineWidth = 5 ctx.lineCap = "round" ctx.lineJoin = "round" ctx.drawing = False ctx.action = "draw" -rect = canvas.getBoundingClientRect() +ctx.rect = canvas.getBoundingClientRect() def get_canvas_coords(event: MouseEvent) -> tuple[float, float]: @@ -35,8 +40,8 @@ def get_canvas_coords(event: MouseEvent) -> tuple[float, float]: tuple[float, float]: The x and y coordinates """ - x = (event.pageX - rect.left) * SCALE - y = (event.pageY - rect.top) * SCALE + x = (event.pageX - ctx.rect.left) * SCALE + y = (event.pageY - ctx.rect.top) * SCALE return (x, y) @@ -106,9 +111,11 @@ def canvas_click(event: MouseEvent) -> None: event (MouseEvent): The mouse event """ + if ctx.drawing: + return x, y = get_canvas_coords(event) ctx.beginPath() - ctx.ellipse(x, y, ctx.lineWidth / 6, ctx.lineWidth / 6, 0, 0, 2 * Math.PI) # Put a dot here + ctx.ellipse(x, y, ctx.lineWidth / 100, ctx.lineWidth / 100, 0, 0, 2 * Math.PI) # Put a dot here ctx.stroke() @@ -146,3 +153,38 @@ def action_change(event: Event) -> None: """ ctx.action = event.target.getAttribute("value") + + +@create_proxy +def resize(_: Event) -> None: + """Resize canvas according to window. + + Args: + _ (Event): Resize event + + """ + data = ctx.getImageData(0, 0, canvas.width, canvas.height) + line_width = ctx.lineWidth + stroke_style = ctx.strokeStyle + + display_height = window.innerHeight * 0.95 + + display_width = display_height * (2**0.5) + + canvas.style.height = f"{display_height}px" + canvas.style.width = f"{display_width}px" + + canvas.height = display_height * SCALE + canvas.width = display_width * SCALE + + ctx.rect = canvas.getBoundingClientRect() + ctx.putImageData(data, 0, 0) + + ctx.lineWidth = line_width + ctx.strokeStyle = stroke_style + + ctx.lineCap = "round" + ctx.lineJoin = "round" + + +window.addEventListener("resize", resize) From cfbc4fd2d37b99559aaacfee7c4ad9c0c9502b08 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sun, 10 Aug 2025 18:45:01 +0100 Subject: [PATCH 011/198] Add loading screen --- src/editor/main.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/editor/main.py b/src/editor/main.py index 12ac7e33..edc87559 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -6,6 +6,20 @@ ui.add_head_html(""" + + +""") + +ui.add_body_html(""" + +

Loading...

+
""") with ui.row(): From d524e5ca3a5c6cf5cabd8204883a56da07f16232 Mon Sep 17 00:00:00 2001 From: PiLogic Date: Sun, 10 Aug 2025 18:47:48 +0100 Subject: [PATCH 012/198] Added reset feature --- src/editor/main.py | 37 ++++++++++++++++++++++++++---------- src/editor/scripts/editor.py | 5 ++++- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 3e09a744..a8008300 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -3,23 +3,40 @@ app.add_static_files("/scripts", "scripts") + ui.add_head_html(""" """) +def resetConfirmation(): + with ui.dialog() as dialog, ui.card(): + ui.label('Are you sure you want to reset?') + with ui.row(): + ui.button('Cancel', on_click=lambda:dialog.close()) + ui.button('Reset', on_click=lambda:(reset(), dialog.close())) + dialog.open() + +def reset(): + ui.run_javascript(""" + const event = new Event('reset'); + document.body.dispatchEvent(event); + """) + ui.element("canvas").props("id='image-canvas' style='border: 1px solid black;'") +with ui.row(): + ui.toggle( + {"pen": "🖊️", "eraser": "🧽"}, + value="pen", + on_change=lambda e: ui.run_javascript(f""" + const event = new Event('change'); + const actionSelect = document.querySelector("#action-select"); + actionSelect.setAttribute("value", "{e.value}"); + actionSelect.dispatchEvent(event); + """), + ).props("id='action-select'") -ui.toggle( - {"pen": "🖊️", "eraser": "🧽"}, - value="pen", - on_change=lambda e: ui.run_javascript(f""" - const event = new Event('change'); - const actionSelect = document.querySelector("#action-select"); - actionSelect.setAttribute("value", "{e.value}"); - actionSelect.dispatchEvent(event); - """), -).props("id='action-select'") + ui.button('Reset', on_click = lambda _: resetConfirmation()) ui.color_input( label="Color", diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 7c9de758..3928e3b1 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -24,7 +24,6 @@ ctx.action = "pen" rect = canvas.getBoundingClientRect() - def get_canvas_coords(event: MouseEvent) -> tuple[float, float]: """Give the canvas coordinates. @@ -153,3 +152,7 @@ def action_change(event: Event) -> None: else: ctx.globalCompositeOperation = "destination-out" +@when("reset","body") +def resetBoard(event: Event) -> None: + ctx.reset() + From 33a958fc44b4e2582078936564bdbf3eb4d518d0 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sun, 10 Aug 2025 19:23:07 +0100 Subject: [PATCH 013/198] Reformat files --- src/editor/main.py | 19 +++++++++++-------- src/editor/scripts/editor.py | 12 ++++++++++-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 033e1706..3e4a40a6 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -3,7 +3,6 @@ app.add_static_files("/scripts", "scripts") - ui.add_head_html(""" @@ -23,20 +22,25 @@ """) -def resetConfirmation(): + +def reset_confirmation() -> None: + """Prompt user to reset canvas.""" with ui.dialog() as dialog, ui.card(): - ui.label('Are you sure you want to reset?') + ui.label("Are you sure you want to reset?") with ui.row(): - ui.button('Cancel', on_click=lambda:dialog.close()) - ui.button('Reset', on_click=lambda:(reset(), dialog.close())) + ui.button("Cancel", on_click=lambda: dialog.close()) + ui.button("Reset", on_click=lambda: (reset(), dialog.close())) dialog.open() -def reset(): + +def reset() -> None: + """Reset canvas.""" ui.run_javascript(""" const event = new Event('reset'); document.body.dispatchEvent(event); """) + with ui.row(): with ui.column(): dark = ui.dark_mode() @@ -52,7 +56,7 @@ def reset(): actionSelect.dispatchEvent(event); """), ).props("id='action-select'") - ui.button('Reset', on_click = lambda _: resetConfirmation()) + ui.button("Reset", on_click=lambda _: reset_confirmation()) ui.color_input( label="Color", @@ -63,7 +67,6 @@ def reset(): """), ).classes("colour-picker") - ui.label("Line width") ui.slider( min=1, diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 221d40c5..1688d986 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -29,6 +29,7 @@ ctx.action = "pen" ctx.rect = canvas.getBoundingClientRect() + def get_canvas_coords(event: MouseEvent) -> tuple[float, float]: """Give the canvas coordinates. @@ -158,8 +159,15 @@ def action_change(event: Event) -> None: else: ctx.globalCompositeOperation = "destination-out" -@when("reset","body") -def resetBoard(event: Event) -> None: + +@when("reset", "body") +def reset_board(_: Event) -> None: + """Reset the canvas. + + Args: + _ (Event): Reset event + + """ ctx.reset() From 14c453a258e4afe6e08653aa7699bab527728c58 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sun, 10 Aug 2025 19:51:49 +0100 Subject: [PATCH 014/198] Fix reset clearing line settings. Prevent non-left mouse click from drawing. Made script runnable from outside /editor --- src/editor/main.py | 4 +++- src/editor/scripts/editor.py | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/editor/main.py b/src/editor/main.py index 3e4a40a6..ab8a395d 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -1,6 +1,8 @@ +import pathlib + from nicegui import app, ui -app.add_static_files("/scripts", "scripts") +app.add_static_files("/scripts", pathlib.Path(__file__).parent / "scripts") ui.add_head_html(""" diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 1688d986..64613620 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -53,6 +53,8 @@ def start_path(event: MouseEvent) -> None: event (MouseEvent): The mouse event """ + if event.button != 0: + return ctx.drawing = True x, y = get_canvas_coords(event) ctx.beginPath() @@ -111,6 +113,8 @@ def canvas_click(event: MouseEvent) -> None: event (MouseEvent): The mouse event """ + if event.button != 0: + return x, y = get_canvas_coords(event) ctx.beginPath() ctx.ellipse(x, y, ctx.lineWidth / 100, ctx.lineWidth / 100, 0, 0, 2 * Math.PI) # Put a dot here @@ -168,7 +172,13 @@ def reset_board(_: Event) -> None: _ (Event): Reset event """ + line_width = ctx.lineWidth + stroke_style = ctx.strokeStyle ctx.reset() + ctx.lineWidth = line_width + ctx.strokeStyle = stroke_style + ctx.lineCap = "round" + ctx.lineJoin = "round" @create_proxy From 16ddf56be12a82bb9c7b97e521a744663dcbb351 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sun, 10 Aug 2025 21:56:42 +0100 Subject: [PATCH 015/198] Fix reset and resize changing the action back to draw mode even if left on erase mode prior to the event --- src/editor/scripts/editor.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 64613620..8a0affe7 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -174,11 +174,13 @@ def reset_board(_: Event) -> None: """ line_width = ctx.lineWidth stroke_style = ctx.strokeStyle + global_composite_operation = ctx.globalCompositeOperation ctx.reset() ctx.lineWidth = line_width ctx.strokeStyle = stroke_style ctx.lineCap = "round" ctx.lineJoin = "round" + ctx.globalCompositeOperation = global_composite_operation @create_proxy @@ -192,7 +194,7 @@ def resize(_: Event) -> None: data = ctx.getImageData(0, 0, canvas.width, canvas.height) line_width = ctx.lineWidth stroke_style = ctx.strokeStyle - + global_composite_operation = ctx.globalCompositeOperation display_height = window.innerHeight * 0.95 display_width = display_height * (2**0.5) @@ -211,6 +213,7 @@ def resize(_: Event) -> None: ctx.lineCap = "round" ctx.lineJoin = "round" + ctx.globalCompositeOperation = global_composite_operation window.addEventListener("resize", resize) From e01a322abc8b1ccb96eeb694d34347621404351e Mon Sep 17 00:00:00 2001 From: PiLogic Date: Mon, 11 Aug 2025 10:58:35 +0100 Subject: [PATCH 016/198] Turned colour selector into slot machine style --- src/editor/main.py | 38 +++++++++++++++++++++++++++--------- src/editor/scripts/editor.py | 8 ++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index ab8a395d..cac53b34 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -1,4 +1,6 @@ import pathlib +import random +import asyncio from nicegui import app, ui @@ -24,7 +26,6 @@ """) - def reset_confirmation() -> None: """Prompt user to reset canvas.""" with ui.dialog() as dialog, ui.card(): @@ -42,6 +43,24 @@ def reset() -> None: document.body.dispatchEvent(event); """) +Hex = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'] + +async def spin() -> None: + """Change RGB values""" + hex_value = '' + for x in range(10): + for y in range(3): + text = random.choice(Hex) + random.choice(Hex) + colourValues[y].text = text + if x == 9: + hex_value += text + await asyncio.sleep(0.1) + ui.run_javascript(f""" + window.pen = window.pen || {{}}; + window.pen.colour = "#{hex_value}"; + const event = new Event('colourChange'); + document.body.dispatchEvent(event); + """) with ui.row(): with ui.column(): @@ -60,14 +79,15 @@ def reset() -> None: ).props("id='action-select'") ui.button("Reset", on_click=lambda _: reset_confirmation()) - ui.color_input( - label="Color", - value="#000000", - on_change=lambda _: ui.run_javascript(""" - const event = new Event('change'); - document.querySelector(".colour-picker div div div input").dispatchEvent(event); - """), - ).classes("colour-picker") + + with ui.row(): + colourValues = [] + for colour in ['R','G','B']: + with ui.column().style('align-items: center;'): + ui.label(colour) + colour_label = ui.label('00') + colourValues.append(colour_label) + ui.button('Spin',on_click = spin) ui.label("Line width") ui.slider( diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 8a0affe7..abdebdea 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -1,7 +1,6 @@ from js import Event, Math, MouseEvent, Object, document, window from pyodide.ffi import create_proxy from pyscript import when - canvas = document.getElementById("image-canvas") settings = Object() @@ -124,10 +123,7 @@ def canvas_click(event: MouseEvent) -> None: ctx.fill() -@when( - "change", - ".colour-picker div div div input", -) +@when("colourChange","body") def colour_change(event: Event) -> None: """Handle colour change. @@ -135,7 +131,7 @@ def colour_change(event: Event) -> None: event (Event): Change event """ - ctx.strokeStyle = event.target.value + ctx.strokeStyle = window.pen.colour @when("change", ".width-input") From c53cc676477601a861bec803684bda4c4b49a7fd Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Mon, 11 Aug 2025 12:03:45 +0100 Subject: [PATCH 017/198] Fix formatting --- src/editor/main.py | 31 +++++++++++++++++-------------- src/editor/scripts/editor.py | 7 ++++--- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index cac53b34..7579ce31 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -1,6 +1,6 @@ +import asyncio import pathlib import random -import asyncio from nicegui import app, ui @@ -26,6 +26,7 @@ """) + def reset_confirmation() -> None: """Prompt user to reset canvas.""" with ui.dialog() as dialog, ui.card(): @@ -43,16 +44,18 @@ def reset() -> None: document.body.dispatchEvent(event); """) -Hex = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'] + +Hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"] + async def spin() -> None: - """Change RGB values""" - hex_value = '' + """Change RGB values.""" + hex_value = "" for x in range(10): for y in range(3): - text = random.choice(Hex) + random.choice(Hex) - colourValues[y].text = text - if x == 9: + text = random.choice(Hex) + random.choice(Hex) # noqa: S311 + colour_values[y].text = text + if x == 9: # noqa: PLR2004 hex_value += text await asyncio.sleep(0.1) ui.run_javascript(f""" @@ -62,6 +65,7 @@ async def spin() -> None: document.body.dispatchEvent(event); """) + with ui.row(): with ui.column(): dark = ui.dark_mode() @@ -79,15 +83,14 @@ async def spin() -> None: ).props("id='action-select'") ui.button("Reset", on_click=lambda _: reset_confirmation()) - with ui.row(): - colourValues = [] - for colour in ['R','G','B']: - with ui.column().style('align-items: center;'): + colour_values = [] + for colour in ["R", "G", "B"]: + with ui.column().style("align-items: center;"): ui.label(colour) - colour_label = ui.label('00') - colourValues.append(colour_label) - ui.button('Spin',on_click = spin) + colour_label = ui.label("00") + colour_values.append(colour_label) + ui.button("Spin", on_click=spin) ui.label("Line width") ui.slider( diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index abdebdea..75ace176 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -1,6 +1,7 @@ from js import Event, Math, MouseEvent, Object, document, window from pyodide.ffi import create_proxy from pyscript import when + canvas = document.getElementById("image-canvas") settings = Object() @@ -123,12 +124,12 @@ def canvas_click(event: MouseEvent) -> None: ctx.fill() -@when("colourChange","body") -def colour_change(event: Event) -> None: +@when("colourChange", "body") +def colour_change(_: Event) -> None: """Handle colour change. Args: - event (Event): Change event + _ (Event): Change event """ ctx.strokeStyle = window.pen.colour From 4019d1fdb02ea573806464602c51af0b75dcd3b8 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Mon, 11 Aug 2025 12:23:29 +0100 Subject: [PATCH 018/198] Reorganise UI layout. Fix formatting. --- src/editor/main.py | 30 ++++++++++++++++-------------- src/editor/scripts/__init__.py | 1 + src/editor/scripts/editor.py | 7 ++++--- 3 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 src/editor/scripts/__init__.py diff --git a/src/editor/main.py b/src/editor/main.py index 7579ce31..c7f69b37 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -31,9 +31,9 @@ def reset_confirmation() -> None: """Prompt user to reset canvas.""" with ui.dialog() as dialog, ui.card(): ui.label("Are you sure you want to reset?") - with ui.row(): + with ui.row().style("display: flex; justify-content: space-between; width: 100%;"): ui.button("Cancel", on_click=lambda: dialog.close()) - ui.button("Reset", on_click=lambda: (reset(), dialog.close())) + ui.button("Reset", on_click=lambda: (reset(), dialog.close())).props("color='red'") dialog.open() @@ -66,23 +66,27 @@ async def spin() -> None: """) -with ui.row(): - with ui.column(): +with ui.row().style("display: flex; width: 100%; justify-content: space-between;"): + # Left side contains page controls + with ui.column().style("flex-grow: 1; flex-basis: 0;"): dark = ui.dark_mode() ui.switch("Dark mode").bind_value(dark) - with ui.row(): - ui.toggle( - {"pen": "🖊️", "eraser": "🧽"}, - value="pen", - on_change=lambda e: ui.run_javascript(f""" + ui.button("Reset", on_click=lambda _: reset_confirmation()).props("color='red'") + + ui.element("canvas").props("id='image-canvas'").style("border: 1px solid black; background-color: white;") + + # Right side contains canvas controls + with ui.column().style("flex-grow: 1; flex-basis: 0;"): + ui.toggle( + {"pen": "🖊️", "eraser": "🧽"}, + value="pen", + on_change=lambda e: ui.run_javascript(f""" const event = new Event('change'); const actionSelect = document.querySelector("#action-select"); actionSelect.setAttribute("value", "{e.value}"); actionSelect.dispatchEvent(event); """), - ).props("id='action-select'") - ui.button("Reset", on_click=lambda _: reset_confirmation()) - + ).props("id='action-select'") with ui.row(): colour_values = [] for colour in ["R", "G", "B"]: @@ -91,7 +95,6 @@ async def spin() -> None: colour_label = ui.label("00") colour_values.append(colour_label) ui.button("Spin", on_click=spin) - ui.label("Line width") ui.slider( min=1, @@ -103,7 +106,6 @@ async def spin() -> None: """), ).classes("width-input") - ui.element("canvas").props("id='image-canvas'").style("border: 1px solid black; background-color: white;") ui.add_body_html(""" diff --git a/src/editor/scripts/__init__.py b/src/editor/scripts/__init__.py new file mode 100644 index 00000000..68de05da --- /dev/null +++ b/src/editor/scripts/__init__.py @@ -0,0 +1 @@ +# Added so Ruff stops complaining diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 75ace176..b75e5989 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -1,6 +1,7 @@ -from js import Event, Math, MouseEvent, Object, document, window -from pyodide.ffi import create_proxy -from pyscript import when +# Following imports have the ignore flag as they are not pip installed +from js import Event, Math, MouseEvent, Object, document, window # pyright: ignore[reportMissingImports] +from pyodide.ffi import create_proxy # pyright: ignore[reportMissingImports] +from pyscript import when # pyright: ignore[reportMissingImports] canvas = document.getElementById("image-canvas") From 02ead65ba57932941ebc0046f0efb5ac56e2e349 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Mon, 11 Aug 2025 14:05:17 +0100 Subject: [PATCH 019/198] Revert "Reorganise UI layout. Fix formatting." This reverts commit 4019d1fdb02ea573806464602c51af0b75dcd3b8. --- src/editor/main.py | 30 ++++++++++++++---------------- src/editor/scripts/__init__.py | 1 - src/editor/scripts/editor.py | 7 +++---- 3 files changed, 17 insertions(+), 21 deletions(-) delete mode 100644 src/editor/scripts/__init__.py diff --git a/src/editor/main.py b/src/editor/main.py index c7f69b37..7579ce31 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -31,9 +31,9 @@ def reset_confirmation() -> None: """Prompt user to reset canvas.""" with ui.dialog() as dialog, ui.card(): ui.label("Are you sure you want to reset?") - with ui.row().style("display: flex; justify-content: space-between; width: 100%;"): + with ui.row(): ui.button("Cancel", on_click=lambda: dialog.close()) - ui.button("Reset", on_click=lambda: (reset(), dialog.close())).props("color='red'") + ui.button("Reset", on_click=lambda: (reset(), dialog.close())) dialog.open() @@ -66,27 +66,23 @@ async def spin() -> None: """) -with ui.row().style("display: flex; width: 100%; justify-content: space-between;"): - # Left side contains page controls - with ui.column().style("flex-grow: 1; flex-basis: 0;"): +with ui.row(): + with ui.column(): dark = ui.dark_mode() ui.switch("Dark mode").bind_value(dark) - ui.button("Reset", on_click=lambda _: reset_confirmation()).props("color='red'") - - ui.element("canvas").props("id='image-canvas'").style("border: 1px solid black; background-color: white;") - - # Right side contains canvas controls - with ui.column().style("flex-grow: 1; flex-basis: 0;"): - ui.toggle( - {"pen": "🖊️", "eraser": "🧽"}, - value="pen", - on_change=lambda e: ui.run_javascript(f""" + with ui.row(): + ui.toggle( + {"pen": "🖊️", "eraser": "🧽"}, + value="pen", + on_change=lambda e: ui.run_javascript(f""" const event = new Event('change'); const actionSelect = document.querySelector("#action-select"); actionSelect.setAttribute("value", "{e.value}"); actionSelect.dispatchEvent(event); """), - ).props("id='action-select'") + ).props("id='action-select'") + ui.button("Reset", on_click=lambda _: reset_confirmation()) + with ui.row(): colour_values = [] for colour in ["R", "G", "B"]: @@ -95,6 +91,7 @@ async def spin() -> None: colour_label = ui.label("00") colour_values.append(colour_label) ui.button("Spin", on_click=spin) + ui.label("Line width") ui.slider( min=1, @@ -106,6 +103,7 @@ async def spin() -> None: """), ).classes("width-input") + ui.element("canvas").props("id='image-canvas'").style("border: 1px solid black; background-color: white;") ui.add_body_html(""" diff --git a/src/editor/scripts/__init__.py b/src/editor/scripts/__init__.py deleted file mode 100644 index 68de05da..00000000 --- a/src/editor/scripts/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Added so Ruff stops complaining diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index b75e5989..75ace176 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -1,7 +1,6 @@ -# Following imports have the ignore flag as they are not pip installed -from js import Event, Math, MouseEvent, Object, document, window # pyright: ignore[reportMissingImports] -from pyodide.ffi import create_proxy # pyright: ignore[reportMissingImports] -from pyscript import when # pyright: ignore[reportMissingImports] +from js import Event, Math, MouseEvent, Object, document, window +from pyodide.ffi import create_proxy +from pyscript import when canvas = document.getElementById("image-canvas") From f305f23c2f607e0e2aa5966fe52409d4f8ce666b Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Mon, 11 Aug 2025 14:27:58 +0100 Subject: [PATCH 020/198] Fix UI layout I think I messed something up so I redid the changes --- src/editor/main.py | 38 +++++++++++++++++++--------------- src/editor/scripts/__init__.py | 0 src/editor/scripts/editor.py | 7 ++++--- 3 files changed, 25 insertions(+), 20 deletions(-) create mode 100644 src/editor/scripts/__init__.py diff --git a/src/editor/main.py b/src/editor/main.py index 7579ce31..14b10ba2 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -31,9 +31,9 @@ def reset_confirmation() -> None: """Prompt user to reset canvas.""" with ui.dialog() as dialog, ui.card(): ui.label("Are you sure you want to reset?") - with ui.row(): + with ui.row().style("display: flex; justify-content: space-between; width: 100%;"): ui.button("Cancel", on_click=lambda: dialog.close()) - ui.button("Reset", on_click=lambda: (reset(), dialog.close())) + ui.button("Reset", on_click=lambda: (reset(), dialog.close())).props("color='red'") dialog.open() @@ -66,22 +66,27 @@ async def spin() -> None: """) -with ui.row(): - with ui.column(): +with ui.row().style("display: flex; width: 100%;"): + # Page controls + with ui.column().style("flex-grow: 1; flex-basis: 0;"): dark = ui.dark_mode() ui.switch("Dark mode").bind_value(dark) - with ui.row(): - ui.toggle( - {"pen": "🖊️", "eraser": "🧽"}, - value="pen", - on_change=lambda e: ui.run_javascript(f""" - const event = new Event('change'); - const actionSelect = document.querySelector("#action-select"); - actionSelect.setAttribute("value", "{e.value}"); - actionSelect.dispatchEvent(event); - """), - ).props("id='action-select'") - ui.button("Reset", on_click=lambda _: reset_confirmation()) + ui.button("Reset", on_click=lambda _: reset_confirmation()).props("color='red'") + + ui.element("canvas").props("id='image-canvas'").style("border: 1px solid black; background-color: white;") + + # Canvas controls + with ui.column().style("flex-grow: 1; flex-basis: 0;"): + ui.toggle( + {"pen": "🖊️", "eraser": "🧽"}, + value="pen", + on_change=lambda e: ui.run_javascript(f""" + const event = new Event('change'); + const actionSelect = document.querySelector("#action-select"); + actionSelect.setAttribute("value", "{e.value}"); + actionSelect.dispatchEvent(event); + """), + ).props("id='action-select'") with ui.row(): colour_values = [] @@ -103,7 +108,6 @@ async def spin() -> None: """), ).classes("width-input") - ui.element("canvas").props("id='image-canvas'").style("border: 1px solid black; background-color: white;") ui.add_body_html(""" diff --git a/src/editor/scripts/__init__.py b/src/editor/scripts/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 75ace176..b75e5989 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -1,6 +1,7 @@ -from js import Event, Math, MouseEvent, Object, document, window -from pyodide.ffi import create_proxy -from pyscript import when +# Following imports have the ignore flag as they are not pip installed +from js import Event, Math, MouseEvent, Object, document, window # pyright: ignore[reportMissingImports] +from pyodide.ffi import create_proxy # pyright: ignore[reportMissingImports] +from pyscript import when # pyright: ignore[reportMissingImports] canvas = document.getElementById("image-canvas") From 4cd84da670c62e408e3f5a437ae5c4fdb0d0ca65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Mon, 11 Aug 2025 16:14:15 +0200 Subject: [PATCH 021/198] Gallery: Refactored and simplified --- src/gallery/main.py | 164 +++++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 86 deletions(-) diff --git a/src/gallery/main.py b/src/gallery/main.py index e225acdc..d7d1d78c 100644 --- a/src/gallery/main.py +++ b/src/gallery/main.py @@ -1,71 +1,97 @@ ## PLACEHOLDER, TAKEN FROM: ## https://pyscript.com/@examples/webgl-icosahedron/latest +## DOCS +## https://threejs.org/docs/ + from pyodide.ffi import to_js from pyscript import when, window, document from js import Math, THREE, performance, Object import asyncio -mouse = THREE.Vector2.new() -renderer = THREE.WebGLRenderer.new({"antialias": True}) -renderer.setSize(1000, 1000) -renderer.shadowMap.enabled = False -renderer.shadowMap.type = THREE.PCFSoftShadowMap -renderer.shadowMap.needsUpdate = True +RENDERER = THREE.WebGLRenderer.new({"antialias": False}) +document.body.appendChild(RENDERER.domElement) +RENDERER.setSize(1000, 1000) +RENDERER.shadowMap.enabled = False +RENDERER.shadowMap.type = THREE.PCFSoftShadowMap +RENDERER.shadowMap.needsUpdate = True +RENDERER.setSize(window.innerWidth, window.innerHeight) -document.body.appendChild(renderer.domElement) +CAMERA = THREE.PerspectiveCamera.new(35, window.innerWidth / window.innerHeight, 1, 500) +cameraRange = 3 +CAMERA.position.set(0, 0, cameraRange) +setcolor = "#000000" +SCENE = THREE.Scene.new() +SCENE.background = THREE.Color.new(setcolor) +SCENE.fog = THREE.Fog.new(setcolor, 2.5, 3.5) -@when("mousemove", "body") -def onMouseMove(event): - event.preventDefault() - mouse.x = (event.clientX / window.innerWidth) * 2 - 1 - mouse.y = -(event.clientY / window.innerHeight) * 2 + 1 +CAMERA.lookAt(SCENE.position) +SCENE_GROUP = THREE.Object3D.new() +SCENE.add(SCENE_GROUP) -camera = THREE.PerspectiveCamera.new(35, window.innerWidth / window.innerHeight, 1, 500) -scene = THREE.Scene.new() -cameraRange = 3 +PARTICULAR_GROUP = THREE.Object3D.new() +SCENE_GROUP.add(PARTICULAR_GROUP) -camera.aspect = window.innerWidth / window.innerHeight -camera.updateProjectionMatrix() -renderer.setSize(window.innerWidth, window.innerHeight) +MODULAR_GROUP = THREE.Object3D.new() +SCENE.add(MODULAR_GROUP) -setcolor = "#000000" -scene.background = THREE.Color.new(setcolor) -scene.fog = THREE.Fog.new(setcolor, 2.5, 3.5) +MOUSE = THREE.Vector2.new() -sceneGroup = THREE.Object3D.new() -particularGroup = THREE.Object3D.new() +@when("mousemove", "body") +def onMouseMove(event): + event.preventDefault() + MOUSE.x = (event.clientX / window.innerWidth) * 2 - 1 + MOUSE.y = -(event.clientY / window.innerHeight) * 2 + 1 def mathRandom(num=1): setNumber = -Math.random() * num + Math.random() * num return setNumber +def genearate_lights()->None: + ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.1) + SCENE.add(ambientLight) -particularGroup = THREE.Object3D.new() -modularGroup = THREE.Object3D.new() + light = THREE.SpotLight.new(0xFFFFFF, 3) + light.position.set(5, 5, 2) + light.castShadow = True + light.shadow.mapSize.width = 10000 + light.shadow.mapSize.height = light.shadow.mapSize.width + light.penumbra = 0.5 + SCENE.add(light) -perms = { - "flatShading": True, - "color": "#111111", - "transparent": False, - "opacity": 1, - "wireframe": False, -} -perms = Object.fromEntries(to_js(perms)) + lightBack = THREE.PointLight.new(0x0FFFFF, 1) + lightBack.position.set(0, -3, -1) + SCENE.add(lightBack) -particle_perms = {"color": "#FFFFFF", "side": THREE.DoubleSide} -particle_perms = Object.fromEntries(to_js(particle_perms)) + rectSize = 2 + intensity = 14 + rectLight = THREE.RectAreaLight.new(0x0FFFFF, intensity, rectSize, rectSize) + rectLight.position.set(0, 0, 1) + rectLight.lookAt(0, 0, 0) + SCENE.add(rectLight) def create_cubes(mathRandom, modularGroup): i = 0 while i < 30: geometry = THREE.IcosahedronGeometry.new() + perms = Object.fromEntries( + to_js( + { + "flatShading": True, + "color": "#111111", + "transparent": False, + "opacity": 1, + "wireframe": False, + } + ) + ) + material = THREE.MeshStandardMaterial.new(perms) cube = THREE.Mesh.new(geometry, material) cube.speedRotation = Math.random() * 0.1 @@ -84,10 +110,10 @@ def create_cubes(mathRandom, modularGroup): i += 1 -create_cubes(mathRandom, modularGroup) - - def generateParticle(mathRandom, particularGroup, num, amp=2): + particle_perms = {"color": "#FFFFFF", "side": THREE.DoubleSide} + particle_perms = Object.fromEntries(to_js(particle_perms)) + gmaterial = THREE.MeshPhysicalMaterial.new(particle_perms) gparticular = THREE.CircleGeometry.new(0.2, 5) i = 0 @@ -102,59 +128,20 @@ def generateParticle(mathRandom, particularGroup, num, amp=2): i += 1 -generateParticle(mathRandom, particularGroup, 200, 2) - -sceneGroup.add(particularGroup) -scene.add(modularGroup) -scene.add(sceneGroup) - -camera.position.set(0, 0, cameraRange) -cameraValue = False - -ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.1) - -light = THREE.SpotLight.new(0xFFFFFF, 3) -light.position.set(5, 5, 2) -light.castShadow = True -light.shadow.mapSize.width = 10000 -light.shadow.mapSize.height = light.shadow.mapSize.width -light.penumbra = 0.5 - -lightBack = THREE.PointLight.new(0x0FFFFF, 1) -lightBack.position.set(0, -3, -1) - -scene.add(sceneGroup) -scene.add(light) -scene.add(lightBack) - -rectSize = 2 -intensity = 14 -rectLight = THREE.RectAreaLight.new(0x0FFFFF, intensity, rectSize, rectSize) -rectLight.position.set(0, 0, 1) -rectLight.lookAt(0, 0, 0) -scene.add(rectLight) - -raycaster = THREE.Raycaster.new() -uSpeed = 0.1 - -time = 0.0003 -camera.lookAt(scene.position) - - async def main(): while True: time = performance.now() * 0.0003 i = 0 - while i < particularGroup.children.length: - newObject = particularGroup.children[i] + while i < PARTICULAR_GROUP.children.length: + newObject = PARTICULAR_GROUP.children[i] newObject.rotation.x += newObject.speedValue / 10 newObject.rotation.y += newObject.speedValue / 10 newObject.rotation.z += newObject.speedValue / 10 i += 1 i = 0 - while i < modularGroup.children.length: - newCubes = modularGroup.children[i] + while i < MODULAR_GROUP.children.length: + newCubes = MODULAR_GROUP.children[i] newCubes.rotation.x += 0.008 newCubes.rotation.y += 0.005 newCubes.rotation.z += 0.003 @@ -170,13 +157,18 @@ async def main(): ) i += 1 - particularGroup.rotation.y += 0.005 + PARTICULAR_GROUP.rotation.y += 0.005 - modularGroup.rotation.y -= ((mouse.x * 4) + modularGroup.rotation.y) * uSpeed - modularGroup.rotation.x -= ((-mouse.y * 4) + modularGroup.rotation.x) * uSpeed + uSpeed = 0.1 + MODULAR_GROUP.rotation.y -= ((MOUSE.x * 4) + MODULAR_GROUP.rotation.y) * uSpeed + MODULAR_GROUP.rotation.x -= ((-MOUSE.y * 4) + MODULAR_GROUP.rotation.x) * uSpeed - renderer.render(scene, camera) + RENDERER.render(SCENE, CAMERA) await asyncio.sleep(0.02) -asyncio.ensure_future(main()) +if __name__ == "__main__": + generate_lights() + create_cubes(mathRandom, MODULAR_GROUP) + generateParticle(mathRandom, PARTICULAR_GROUP, 200, 2) + asyncio.ensure_future(main()) From 6a0d8ad83c65dc320793c437e8f19100131f9dd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Mon, 11 Aug 2025 16:14:15 +0200 Subject: [PATCH 022/198] Gallery: Refactored and simplified --- src/gallery/main.py | 164 +++++++++++++++++++++----------------------- 1 file changed, 78 insertions(+), 86 deletions(-) diff --git a/src/gallery/main.py b/src/gallery/main.py index e225acdc..4c94bc08 100644 --- a/src/gallery/main.py +++ b/src/gallery/main.py @@ -1,71 +1,97 @@ ## PLACEHOLDER, TAKEN FROM: ## https://pyscript.com/@examples/webgl-icosahedron/latest +## DOCS +## https://threejs.org/docs/ + from pyodide.ffi import to_js from pyscript import when, window, document from js import Math, THREE, performance, Object import asyncio -mouse = THREE.Vector2.new() -renderer = THREE.WebGLRenderer.new({"antialias": True}) -renderer.setSize(1000, 1000) -renderer.shadowMap.enabled = False -renderer.shadowMap.type = THREE.PCFSoftShadowMap -renderer.shadowMap.needsUpdate = True +RENDERER = THREE.WebGLRenderer.new({"antialias": False}) +document.body.appendChild(RENDERER.domElement) +RENDERER.setSize(1000, 1000) +RENDERER.shadowMap.enabled = False +RENDERER.shadowMap.type = THREE.PCFSoftShadowMap +RENDERER.shadowMap.needsUpdate = True +RENDERER.setSize(window.innerWidth, window.innerHeight) -document.body.appendChild(renderer.domElement) +CAMERA = THREE.PerspectiveCamera.new(35, window.innerWidth / window.innerHeight, 1, 500) +cameraRange = 3 +CAMERA.position.set(0, 0, cameraRange) +setcolor = "#000000" +SCENE = THREE.Scene.new() +SCENE.background = THREE.Color.new(setcolor) +SCENE.fog = THREE.Fog.new(setcolor, 2.5, 3.5) -@when("mousemove", "body") -def onMouseMove(event): - event.preventDefault() - mouse.x = (event.clientX / window.innerWidth) * 2 - 1 - mouse.y = -(event.clientY / window.innerHeight) * 2 + 1 +CAMERA.lookAt(SCENE.position) +SCENE_GROUP = THREE.Object3D.new() +SCENE.add(SCENE_GROUP) -camera = THREE.PerspectiveCamera.new(35, window.innerWidth / window.innerHeight, 1, 500) -scene = THREE.Scene.new() -cameraRange = 3 +PARTICULAR_GROUP = THREE.Object3D.new() +SCENE_GROUP.add(PARTICULAR_GROUP) -camera.aspect = window.innerWidth / window.innerHeight -camera.updateProjectionMatrix() -renderer.setSize(window.innerWidth, window.innerHeight) +MODULAR_GROUP = THREE.Object3D.new() +SCENE.add(MODULAR_GROUP) -setcolor = "#000000" -scene.background = THREE.Color.new(setcolor) -scene.fog = THREE.Fog.new(setcolor, 2.5, 3.5) +MOUSE = THREE.Vector2.new() -sceneGroup = THREE.Object3D.new() -particularGroup = THREE.Object3D.new() +@when("mousemove", "body") +def onMouseMove(event): + event.preventDefault() + MOUSE.x = (event.clientX / window.innerWidth) * 2 - 1 + MOUSE.y = -(event.clientY / window.innerHeight) * 2 + 1 def mathRandom(num=1): setNumber = -Math.random() * num + Math.random() * num return setNumber +def generate_lights()->None: + ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.1) + SCENE.add(ambientLight) -particularGroup = THREE.Object3D.new() -modularGroup = THREE.Object3D.new() + light = THREE.SpotLight.new(0xFFFFFF, 3) + light.position.set(5, 5, 2) + light.castShadow = True + light.shadow.mapSize.width = 10000 + light.shadow.mapSize.height = light.shadow.mapSize.width + light.penumbra = 0.5 + SCENE.add(light) -perms = { - "flatShading": True, - "color": "#111111", - "transparent": False, - "opacity": 1, - "wireframe": False, -} -perms = Object.fromEntries(to_js(perms)) + lightBack = THREE.PointLight.new(0x0FFFFF, 1) + lightBack.position.set(0, -3, -1) + SCENE.add(lightBack) -particle_perms = {"color": "#FFFFFF", "side": THREE.DoubleSide} -particle_perms = Object.fromEntries(to_js(particle_perms)) + rectSize = 2 + intensity = 14 + rectLight = THREE.RectAreaLight.new(0x0FFFFF, intensity, rectSize, rectSize) + rectLight.position.set(0, 0, 1) + rectLight.lookAt(0, 0, 0) + SCENE.add(rectLight) def create_cubes(mathRandom, modularGroup): i = 0 while i < 30: geometry = THREE.IcosahedronGeometry.new() + perms = Object.fromEntries( + to_js( + { + "flatShading": True, + "color": "#111111", + "transparent": False, + "opacity": 1, + "wireframe": False, + } + ) + ) + material = THREE.MeshStandardMaterial.new(perms) cube = THREE.Mesh.new(geometry, material) cube.speedRotation = Math.random() * 0.1 @@ -84,10 +110,10 @@ def create_cubes(mathRandom, modularGroup): i += 1 -create_cubes(mathRandom, modularGroup) - - def generateParticle(mathRandom, particularGroup, num, amp=2): + particle_perms = {"color": "#FFFFFF", "side": THREE.DoubleSide} + particle_perms = Object.fromEntries(to_js(particle_perms)) + gmaterial = THREE.MeshPhysicalMaterial.new(particle_perms) gparticular = THREE.CircleGeometry.new(0.2, 5) i = 0 @@ -102,59 +128,20 @@ def generateParticle(mathRandom, particularGroup, num, amp=2): i += 1 -generateParticle(mathRandom, particularGroup, 200, 2) - -sceneGroup.add(particularGroup) -scene.add(modularGroup) -scene.add(sceneGroup) - -camera.position.set(0, 0, cameraRange) -cameraValue = False - -ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.1) - -light = THREE.SpotLight.new(0xFFFFFF, 3) -light.position.set(5, 5, 2) -light.castShadow = True -light.shadow.mapSize.width = 10000 -light.shadow.mapSize.height = light.shadow.mapSize.width -light.penumbra = 0.5 - -lightBack = THREE.PointLight.new(0x0FFFFF, 1) -lightBack.position.set(0, -3, -1) - -scene.add(sceneGroup) -scene.add(light) -scene.add(lightBack) - -rectSize = 2 -intensity = 14 -rectLight = THREE.RectAreaLight.new(0x0FFFFF, intensity, rectSize, rectSize) -rectLight.position.set(0, 0, 1) -rectLight.lookAt(0, 0, 0) -scene.add(rectLight) - -raycaster = THREE.Raycaster.new() -uSpeed = 0.1 - -time = 0.0003 -camera.lookAt(scene.position) - - async def main(): while True: time = performance.now() * 0.0003 i = 0 - while i < particularGroup.children.length: - newObject = particularGroup.children[i] + while i < PARTICULAR_GROUP.children.length: + newObject = PARTICULAR_GROUP.children[i] newObject.rotation.x += newObject.speedValue / 10 newObject.rotation.y += newObject.speedValue / 10 newObject.rotation.z += newObject.speedValue / 10 i += 1 i = 0 - while i < modularGroup.children.length: - newCubes = modularGroup.children[i] + while i < MODULAR_GROUP.children.length: + newCubes = MODULAR_GROUP.children[i] newCubes.rotation.x += 0.008 newCubes.rotation.y += 0.005 newCubes.rotation.z += 0.003 @@ -170,13 +157,18 @@ async def main(): ) i += 1 - particularGroup.rotation.y += 0.005 + PARTICULAR_GROUP.rotation.y += 0.005 - modularGroup.rotation.y -= ((mouse.x * 4) + modularGroup.rotation.y) * uSpeed - modularGroup.rotation.x -= ((-mouse.y * 4) + modularGroup.rotation.x) * uSpeed + uSpeed = 0.1 + MODULAR_GROUP.rotation.y -= ((MOUSE.x * 4) + MODULAR_GROUP.rotation.y) * uSpeed + MODULAR_GROUP.rotation.x -= ((-MOUSE.y * 4) + MODULAR_GROUP.rotation.x) * uSpeed - renderer.render(scene, camera) + RENDERER.render(SCENE, CAMERA) await asyncio.sleep(0.02) -asyncio.ensure_future(main()) +if __name__ == "__main__": + generate_lights() + create_cubes(mathRandom, MODULAR_GROUP) + generateParticle(mathRandom, PARTICULAR_GROUP, 200, 2) + asyncio.ensure_future(main()) From e979ed387bfeb4924d734a6f66891fcdec08e818 Mon Sep 17 00:00:00 2001 From: PiLogic Date: Mon, 11 Aug 2025 16:51:33 +0100 Subject: [PATCH 023/198] Added pixel art feature --- src/editor/main.py | 27 +++++++---- src/editor/scripts/editor.py | 93 +++++++++++++++++++++++++++--------- 2 files changed, 87 insertions(+), 33 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 14b10ba2..86a330bb 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -6,7 +6,6 @@ app.add_static_files("/scripts", pathlib.Path(__file__).parent / "scripts") - ui.add_head_html(""" @@ -26,14 +25,23 @@ """) +def do_reset(mode_value): + if mode_value: + ui.run_javascript(f""" + const event = new Event('change'); + const typeSelect = document.querySelector("#type-select"); + typeSelect.setAttribute("value", "{mode_value}"); + typeSelect.dispatchEvent(event); + """) + reset() -def reset_confirmation() -> None: +def reset_confirmation(mode_value = False) -> None: """Prompt user to reset canvas.""" with ui.dialog() as dialog, ui.card(): ui.label("Are you sure you want to reset?") with ui.row().style("display: flex; justify-content: space-between; width: 100%;"): ui.button("Cancel", on_click=lambda: dialog.close()) - ui.button("Reset", on_click=lambda: (reset(), dialog.close())).props("color='red'") + ui.button("Reset", on_click=lambda: (do_reset(mode_value), dialog.close())).props("color='red'") dialog.open() @@ -72,7 +80,11 @@ async def spin() -> None: dark = ui.dark_mode() ui.switch("Dark mode").bind_value(dark) ui.button("Reset", on_click=lambda _: reset_confirmation()).props("color='red'") - + ui.toggle( + {"smooth": "✍️", "pixel": "👾"}, + value="smooth", + on_change=lambda e: reset_confirmation(mode_value = e.value), + ).props("id='type-select'") ui.element("canvas").props("id='image-canvas'").style("border: 1px solid black; background-color: white;") # Canvas controls @@ -80,12 +92,7 @@ async def spin() -> None: ui.toggle( {"pen": "🖊️", "eraser": "🧽"}, value="pen", - on_change=lambda e: ui.run_javascript(f""" - const event = new Event('change'); - const actionSelect = document.querySelector("#action-select"); - actionSelect.setAttribute("value", "{e.value}"); - actionSelect.dispatchEvent(event); - """), + on_change=lambda e: reset_confirmation() ).props("id='action-select'") with ui.row(): diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index b75e5989..4b98dd12 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -5,21 +5,25 @@ canvas = document.getElementById("image-canvas") +canvas.style.imageRendering = "pixelated" +canvas.style.imageRendering = "crisp-edges" + settings = Object() settings.willReadFrequently = True ctx = canvas.getContext("2d", settings) +ctx.imageSmoothingEnabled = False display_height = window.innerHeight * 0.95 # 95vh display_width = display_height * (2**0.5) # Same ratio as an A4 sheet of paper -SCALE = 2 # Better resolution +ctx.scale = 2 # Better resolution canvas.style.height = f"{display_height}px" canvas.style.width = f"{display_width}px" -canvas.height = display_height * SCALE -canvas.width = display_width * SCALE +canvas.height = display_height * ctx.scale +canvas.width = display_width * ctx.scale ctx.strokeStyle = "black" ctx.lineWidth = 5 @@ -28,8 +32,14 @@ ctx.drawing = False ctx.action = "pen" +ctx.type = "smooth" ctx.rect = canvas.getBoundingClientRect() +PIXEL_SIZE = 8 + +def draw_pixel(x, y): + ctx.fillStyle = ctx.strokeStyle + ctx.fillRect(x - PIXEL_SIZE//2, y - PIXEL_SIZE//2, PIXEL_SIZE, PIXEL_SIZE) def get_canvas_coords(event: MouseEvent) -> tuple[float, float]: """Give the canvas coordinates. @@ -41,8 +51,11 @@ def get_canvas_coords(event: MouseEvent) -> tuple[float, float]: tuple[float, float]: The x and y coordinates """ - x = (event.pageX - ctx.rect.left) * SCALE - y = (event.pageY - ctx.rect.top) * SCALE + x = ((event.pageX - ctx.rect.left) * ctx.scale) + y = ((event.pageY - ctx.rect.top) * ctx.scale) + if ctx.type == "pixel": + x = (int(x)+5)//10*10 + y = (int(y)+5)//10*10 return (x, y) @@ -57,9 +70,11 @@ def start_path(event: MouseEvent) -> None: if event.button != 0: return ctx.drawing = True - x, y = get_canvas_coords(event) - ctx.beginPath() - ctx.moveTo(x, y) + if ctx.type == "smooth": + x, y = get_canvas_coords(event) + ctx.beginPath() + ctx.moveTo(x, y) + @when("mousemove", "#image-canvas") @@ -73,8 +88,14 @@ def mouse_tracker(event: MouseEvent) -> None: if not ctx.drawing: return x, y = get_canvas_coords(event) - ctx.lineTo(x, y) - ctx.stroke() + if ctx.type == "smooth": + ctx.lineTo(x, y) + ctx.stroke() + elif ctx.type == "pixel": + if ctx.action == "pen": + draw_pixel(x,y) + elif ctx.action == "eraser": + ctx.clearRect(x - PIXEL_SIZE//2, y - PIXEL_SIZE//2, PIXEL_SIZE,PIXEL_SIZE) @when("mouseup", "#image-canvas") @@ -100,13 +121,15 @@ def leaves_canvas(event: MouseEvent) -> None: """ if not ctx.drawing: return - x, y = get_canvas_coords(event) - ctx.lineTo(x, y) - ctx.stroke() # Draws the line to the point on the edge where the mouse leaves the canvas + if ctx.type == "smooth": + x, y = get_canvas_coords(event) + ctx.lineTo(x,y) + ctx.stroke() + ctx.drawing = False -@when("click", "#image-canvas") +@when("mousedown", "#image-canvas") def canvas_click(event: MouseEvent) -> None: """Handle mouse clicking canvas. @@ -117,13 +140,18 @@ def canvas_click(event: MouseEvent) -> None: if event.button != 0: return x, y = get_canvas_coords(event) - ctx.beginPath() - ctx.ellipse(x, y, ctx.lineWidth / 100, ctx.lineWidth / 100, 0, 0, 2 * Math.PI) # Put a dot here - if ctx.action == "pen": - ctx.stroke() - elif ctx.action == "eraser": - ctx.fill() - + if ctx.type == "smooth": + ctx.beginPath() + ctx.ellipse(x, y, ctx.lineWidth / 100, ctx.lineWidth / 100, 0, 0, 2 * Math.PI) # Put a dot here + if ctx.action == "pen": + ctx.stroke() + elif ctx.action == "eraser": + ctx.fill() + elif ctx.type == "pixel": + if ctx.action == "pen": + draw_pixel(x,y) + elif ctx.action == "eraser": + ctx.clearRect(x - PIXEL_SIZE//2, y - PIXEL_SIZE//2, PIXEL_SIZE,PIXEL_SIZE) @when("colourChange", "body") def colour_change(_: Event) -> None: @@ -161,6 +189,24 @@ def action_change(event: Event) -> None: else: ctx.globalCompositeOperation = "destination-out" +@when("change", "#type-select") +def type_change(event: Event) -> None: + """Handle type change. + + Args: + event (Event): Change event + + """ + ctx.type = event.target.getAttribute("value") + if ctx.type == "smooth": + ctx.imageSmoothingEnabled = True + ctx.scale = 2 + elif ctx.type == "pixel": + ctx.imageSmoothingEnabled = False + ctx.scale = 0.5 + resize(Event) + + @when("reset", "body") def reset_board(_: Event) -> None: @@ -189,6 +235,7 @@ def resize(_: Event) -> None: _ (Event): Resize event """ + window.console.log(ctx.scale) data = ctx.getImageData(0, 0, canvas.width, canvas.height) line_width = ctx.lineWidth stroke_style = ctx.strokeStyle @@ -200,8 +247,8 @@ def resize(_: Event) -> None: canvas.style.height = f"{display_height}px" canvas.style.width = f"{display_width}px" - canvas.height = display_height * SCALE - canvas.width = display_width * SCALE + canvas.height = display_height * ctx.scale + canvas.width = display_width * ctx.scale ctx.rect = canvas.getBoundingClientRect() ctx.putImageData(data, 0, 0) From 8942ff6eb6f23e9bc434f7b765e86081ac884f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Mon, 11 Aug 2025 18:05:04 +0200 Subject: [PATCH 024/198] GTLF loader added, with debug tools --- src/gallery/index.html | 17 +++++++++++-- src/gallery/main.py | 54 +++++++++++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/gallery/index.html b/src/gallery/index.html index d5cfbe22..fc432a21 100644 --- a/src/gallery/index.html +++ b/src/gallery/index.html @@ -11,9 +11,24 @@ + + + diff --git a/src/gallery/main.py b/src/gallery/main.py index 9bf5225f..2e21fac2 100644 --- a/src/gallery/main.py +++ b/src/gallery/main.py @@ -4,11 +4,15 @@ ## DOCS ## https://threejs.org/docs/ -from pyodide.ffi import create_proxy, to_js +from pyodide.ffi import create_proxy from pyscript import when, window, document -from js import Math, THREE, performance, Object, GLTFLoader +from js import Math, THREE, GLTFLoader, PointerLockControls + +from collections import defaultdict +from enum import Enum import asyncio + RENDERER = THREE.WebGLRenderer.new({"antialias": False}) document.body.appendChild(RENDERER.domElement) RENDERER.setSize(1000, 1000) @@ -17,16 +21,16 @@ RENDERER.shadowMap.needsUpdate = True RENDERER.setSize(window.innerWidth, window.innerHeight) -CAMERA = THREE.PerspectiveCamera.new(35, window.innerWidth / window.innerHeight, 1, 500) -cameraRange = 3 -CAMERA.position.set(0, 0, cameraRange) +CAMERA = THREE.PerspectiveCamera.new(53, window.innerWidth / window.innerHeight, 0.01, 500) +CAMERA.position.set(3, 1, 3.5) +CAMERA.rotation.set(0, 0.4, 0) setcolor = "#000000" SCENE = THREE.Scene.new() SCENE.background = THREE.Color.new(setcolor) # SCENE.fog = THREE.Fog.new(setcolor, 2.5, 3.5) -CAMERA.lookAt(SCENE.position) +# CAMERA.lookAt(SCENE.position) MODULAR_GROUP = THREE.Object3D.new() SCENE.add(MODULAR_GROUP) @@ -34,6 +38,106 @@ MOUSE = THREE.Vector2.new() +CONTROLS = PointerLockControls.new(CAMERA, document.body) +document.getElementById("instructions").addEventListener("click", create_proxy(CONTROLS.lock)) +CONTROLS.addEventListener( + "lock", + create_proxy( + lambda x: setattr( + document.getElementById("instructions").style, + "display", + "none", + ), + ), +) +CONTROLS.addEventListener( + "unlock", + create_proxy( + lambda x: setattr( + document.getElementById("instructions").style, + "display", + "", + ), + ), +) + + +INPUTS = Enum("INPUTS", ["FORW", "LEFT", "RIGHT", "BACK", "UP", "DOWN", "RUN"]) +KEY_MAPPINGS: dict[INPUTS, set[str]] = { + INPUTS.FORW: {"KeyW", "KeyK", "ArrowUp"}, + INPUTS.LEFT: {"KeyH", "KeyA", "ArrowLeft"}, + INPUTS.RIGHT: {"KeyL", "KeyD", "ArrowRight"}, + INPUTS.BACK: {"KeyJ", "KeyS", "ArrowDown"}, + # + INPUTS.UP: {"Space"}, + INPUTS.DOWN: {"ShiftLeft", "ShiftRight"}, + # + INPUTS.RUN: {"KeyZ"}, +} +KEY_STATES: dict[str, bool] = defaultdict(bool) +document.addEventListener("keydown", create_proxy(lambda x: KEY_STATES.__setitem__(x.code, True))) +document.addEventListener("keyup", create_proxy(lambda x: KEY_STATES.__setitem__(x.code, False))) + +RUN_STATE = False + + +def toggle_run(event): + global RUN_STATE + if event.code in KEY_MAPPINGS[INPUTS.RUN]: + RUN_STATE = not RUN_STATE + + +document.addEventListener("keydown", create_proxy(toggle_run)) + +VELOCITY = THREE.Vector3.new() + + +def move_character(delta_time: float): + pressed_keys = {k for k, v in KEY_MAPPINGS.items() if any(KEY_STATES[i] for i in v)} + damping = 7 + if RUN_STATE: + acceleration = 25 + max_speed = 50 + + CAMERA.fov = min(CAMERA.fov + 60 * delta_time, 60) + else: + acceleration = 10 + max_speed = 20 + + CAMERA.fov = max(CAMERA.fov - 60 * delta_time, 53) + CAMERA.updateProjectionMatrix() + + move = THREE.Vector3.new() + if INPUTS.FORW in pressed_keys: + move.z -= 1 + if INPUTS.BACK in pressed_keys: + move.z += 1 + + if INPUTS.LEFT in pressed_keys: + move.x -= 1 + if INPUTS.RIGHT in pressed_keys: + move.x += 1 + + if INPUTS.UP in pressed_keys: + move.y += 1 + if INPUTS.DOWN in pressed_keys: + move.y -= 1 + + if move.length() > 0: + q = CAMERA.quaternion + yaw = Math.atan2(2 * (q.w * q.y + q.x * q.z), 1 - 2 * (q.y * q.y + q.z * q.z)) + yaw_q = THREE.Quaternion.new() + yaw_q.setFromAxisAngle(THREE.Vector3.new(0, 1, 0), yaw) + + move.applyQuaternion(yaw_q).normalize() + VELOCITY.addScaledVector(move, acceleration * delta_time) + + if VELOCITY.length() > max_speed: + VELOCITY.setLength(max_speed) + + VELOCITY.multiplyScalar(1 - min(damping * delta_time, 1)) + CAMERA.position.addScaledVector(VELOCITY, delta_time) + @when("mousemove", "body") def onMouseMove(event): @@ -93,9 +197,9 @@ def inner_loader(gltf): obj.rotation.y = 0 obj.rotation.z = 0 - obj.scale.x = 0.25 - obj.scale.y = 0.25 - obj.scale.z = 0.25 + obj.scale.x = 1 + obj.scale.y = 1 + obj.scale.z = 1 # Backface culling for v in obj.children[0].children: @@ -120,11 +224,9 @@ def inner_error(error): async def main(): + clock = THREE.Clock.new() while True: - uSpeed = 0.1 - MODULAR_GROUP.rotation.y -= ((MOUSE.x * 4) + MODULAR_GROUP.rotation.y) * uSpeed - MODULAR_GROUP.rotation.x -= ((-MOUSE.y * 4) + MODULAR_GROUP.rotation.x) * uSpeed - + move_character(clock.getDelta()) RENDERER.render(SCENE, CAMERA) await asyncio.sleep(0.02) From 6d5b1fcb6d1e4ffc16c8416822da125f35d8df9c Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Tue, 12 Aug 2025 23:12:03 +0100 Subject: [PATCH 048/198] Add show action preview --- src/editor/main.py | 5 ----- src/editor/scripts/canvas_ctx.py | 13 ++++++++++-- src/editor/scripts/editor.py | 36 +++++++++++++++++++++++++++----- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 6993f49f..9abb66ae 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -146,11 +146,6 @@ def upload_image(e: UploadEventArguments) -> None: const fileUpload = document.querySelector("#file-upload"); fileUpload.src = "data:{e.type};base64,{content}" fileUpload.dispatchEvent(event); - - // The following event is fired in case the image upload is above the canvas. - // This would change the getBoundingClientRect() of the canvas. - event = new Event('resize'); - window.dispatchEvent(event); """) # e.sender is the file upload element which has a .reset() method e.sender.reset() # type: ignore # noqa: PGH003 diff --git a/src/editor/scripts/canvas_ctx.py b/src/editor/scripts/canvas_ctx.py index 8d263cb4..4fe2f025 100644 --- a/src/editor/scripts/canvas_ctx.py +++ b/src/editor/scripts/canvas_ctx.py @@ -171,9 +171,18 @@ def get_canvas_coords(self, event: MouseEvent) -> tuple[float, float]: ########################################################################### # Builtin Methods ########################################################################### - def arc(self) -> None: + def arc( # noqa: PLR0913 + self, + x: float, + y: float, + radius: float, + startAngle: float, + endAngle: float, + *, + counterclockwise: bool = False, + ) -> None: """Add arc.""" - self.ctx.arc() + self.ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise) def arcTo(self) -> None: """Add arcTo.""" diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 524a0079..571f8cac 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -85,6 +85,30 @@ def draw_pixel(x: float, y: float) -> None: ctx.fillRect(x - PIXEL_SIZE // 2, y - PIXEL_SIZE // 2, PIXEL_SIZE, PIXEL_SIZE) +def show_action_icon(x: float, y: float) -> None: + """Show icon to let user know what the action would look like. + + Args: + x (float): X coordinate + y (float): Y coordinate + """ + if ctx.type == "smooth": + buffer_ctx.beginPath() + buffer_ctx.arc(x, y, ctx.lineWidth / 2, 0, 2 * Math.PI) # Put a dot here + if ctx.action == "pen": + buffer_ctx.fill() + elif ctx.action == "eraser": + prev_width = buffer_ctx.lineWidth + prev_fill = buffer_ctx.fillStyle + buffer_ctx.lineWidth = ctx.scaled_by + buffer_ctx.fillStyle = "white" + buffer_ctx.fill() + buffer_ctx.arc(x, y, ctx.lineWidth / 2, 0, 2 * Math.PI) + buffer_ctx.stroke() + buffer_ctx.lineWidth = prev_width + buffer_ctx.fillStyle = prev_fill + + def get_smudge_data(x: float, y: float) -> ImageData: """Get the smudge data around the xy for smudgeing.""" smudge_size = ctx.lineWidth @@ -176,10 +200,12 @@ def mouse_tracker(event: MouseEvent) -> None: event (MouseEvent): The mouse event """ x, y = get_canvas_coords(event) + + buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) if ctx.moving_image: - buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) buffer_ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) return + show_action_icon(x, y) if not ctx.drawing: return @@ -254,16 +280,14 @@ def canvas_click(event: MouseEvent) -> None: if ctx.moving_image: ctx.moving_image = False - ctx.globalCompositeOperation = ctx.prev_operation buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) + ctx.globalCompositeOperation = ctx.prev_operation elif ctx.type == "smooth": ctx.beginPath() ctx.ellipse(x, y, ctx.lineWidth / 100, ctx.lineWidth / 100, 0, 0, 2 * Math.PI) # Put a dot here - if ctx.action == "pen": + if ctx.action in ("pen", "eraser"): ctx.stroke() - elif ctx.action == "eraser": - ctx.fill() elif ctx.type == "pixel": if ctx.action == "pen": draw_pixel(x, y) @@ -279,6 +303,7 @@ def colour_change(_: Event) -> None: _ (Event): Change event """ ctx.strokeStyle = window.pen.colour + buffer_ctx.strokeStyle = window.pen.colour @when("change", ".width-input") @@ -289,6 +314,7 @@ def width_change(event: Event) -> None: event (Event): Change event """ ctx.lineWidth = int(event.target.getAttribute("aria-valuenow")) + buffer_ctx.lineWidth = ctx.lineWidth @when("change", "#action-select") From 1f727563f0abbd104e7df6792aef349d4aadbec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Wed, 13 Aug 2025 03:33:56 +0200 Subject: [PATCH 049/198] Gallery: significantly improved mouse lock UX --- src/gallery/index.html | 20 +++++++++++++++----- src/gallery/main.py | 3 ++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/gallery/index.html b/src/gallery/index.html index 3176f64d..ebfc5f9e 100644 --- a/src/gallery/index.html +++ b/src/gallery/index.html @@ -39,17 +39,27 @@ #loading { outline: none; border: none; background: transparent } #instructions { position: absolute; - top: 50%; - width: 100%; + top: 14%; + left: 50%; + transform: translate(-50%, -50%); /* perfectly center horizontally & vertically */ + max-width: 80%; /* optional, keeps text from stretching too wide */ text-align: center; - color: white; - font-size: 24px; + color: black; + font-size: 28px; font-family: sans-serif; + font-weight: bold; + background-color: white; /* highlight effect */ + padding: 12px 20px; /* padding inside box */ + border-radius: 8px; /* rounded corners */ + box-shadow: 0 4px 8px rgba(0,0,0,0.2); /* subtle shadow for depth */ + display: none; } @@ -77,7 +87,7 @@

Loading...

-
Click to look around!
+
Click here to look around!
diff --git a/src/gallery/main.py b/src/gallery/main.py index 5fdacb18..e167fe63 100644 --- a/src/gallery/main.py +++ b/src/gallery/main.py @@ -39,6 +39,7 @@ def log(*msgs): SCENE.add(MODULAR_GROUP) +# Camera controls and mouse lock CONTROLS = PointerLockControls.new(CAMERA, document.body) document.getElementById("instructions").addEventListener("click", create_proxy(CONTROLS.lock)) CONTROLS.addEventListener( @@ -57,7 +58,7 @@ def log(*msgs): lambda x: setattr( document.getElementById("instructions").style, "display", - "", + "block", ), ), ) From 23c1e27878bdc0ac1d1aaad1a7a00896604c60ed Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:22:30 +0300 Subject: [PATCH 050/198] Get rid of samples from the template --- samples/Pipfile | 15 --------------- samples/pyproject.toml | 19 ------------------- 2 files changed, 34 deletions(-) delete mode 100644 samples/Pipfile delete mode 100644 samples/pyproject.toml diff --git a/samples/Pipfile b/samples/Pipfile deleted file mode 100644 index dedd0c50..00000000 --- a/samples/Pipfile +++ /dev/null @@ -1,15 +0,0 @@ -# Sample Pipfile. - -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] - -[dev-packages] -ruff = "~=0.12.2" -pre-commit = "~=4.2.0" - -[requires] -python_version = "3.12" diff --git a/samples/pyproject.toml b/samples/pyproject.toml deleted file mode 100644 index b486e506..00000000 --- a/samples/pyproject.toml +++ /dev/null @@ -1,19 +0,0 @@ -# Sample poetry configuration. - -[tool.poetry] -name = "Name" -version = "0.1.0" -description = "Description" -authors = ["Author 1 "] -license = "MIT" - -[tool.poetry.dependencies] -python = "3.12.*" - -[tool.poetry.dev-dependencies] -ruff = "~0.12.2" -pre-commit = "~4.2.0" - -[build-system] -requires = ["poetry-core>=1.0.0"] -build-backend = "poetry.core.masonry.api" From d0f5cb40dd48271b86eeedca0152eda7c30d2d94 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:25:22 +0300 Subject: [PATCH 051/198] Move src/editor under packages/editor and delete an unnecessary __init__.py file --- {src => packages}/editor/README.md | 0 {src => packages}/editor/main.py | 0 {src/editor => packages/editor/scripts}/__init__.py | 0 {src => packages}/editor/scripts/editor.py | 0 src/editor/scripts/__init__.py | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {src => packages}/editor/README.md (100%) rename {src => packages}/editor/main.py (100%) rename {src/editor => packages/editor/scripts}/__init__.py (100%) rename {src => packages}/editor/scripts/editor.py (100%) delete mode 100644 src/editor/scripts/__init__.py diff --git a/src/editor/README.md b/packages/editor/README.md similarity index 100% rename from src/editor/README.md rename to packages/editor/README.md diff --git a/src/editor/main.py b/packages/editor/main.py similarity index 100% rename from src/editor/main.py rename to packages/editor/main.py diff --git a/src/editor/__init__.py b/packages/editor/scripts/__init__.py similarity index 100% rename from src/editor/__init__.py rename to packages/editor/scripts/__init__.py diff --git a/src/editor/scripts/editor.py b/packages/editor/scripts/editor.py similarity index 100% rename from src/editor/scripts/editor.py rename to packages/editor/scripts/editor.py diff --git a/src/editor/scripts/__init__.py b/src/editor/scripts/__init__.py deleted file mode 100644 index e69de29b..00000000 From c6b471c09b2fc7c45d3cae64dca0137d65486df7 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:27:45 +0300 Subject: [PATCH 052/198] Make packages/editor a uv workspace member --- packages/editor/pyproject.toml | 7 +++++++ pyproject.toml | 3 +++ 2 files changed, 10 insertions(+) create mode 100644 packages/editor/pyproject.toml diff --git a/packages/editor/pyproject.toml b/packages/editor/pyproject.toml new file mode 100644 index 00000000..e5766e22 --- /dev/null +++ b/packages/editor/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "editor" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [] diff --git a/pyproject.toml b/pyproject.toml index 331ce5eb..20cb480d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,3 +63,6 @@ ignore = [ "TD003", "FIX", ] + +[tool.uv.workspace] +members = ["packages/editor"] From 96478ac006ee3e85226ec9a91b533bc230be523a Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:28:51 +0300 Subject: [PATCH 053/198] Move src/gallery under packages/gallery --- {src => packages}/gallery/README.md | 0 {src => packages}/gallery/assets/css/examples.css | 0 {src => packages}/gallery/assets/css/icosahedron.css | 0 {src => packages}/gallery/index.html | 0 {src => packages}/gallery/main.py | 0 {src => packages}/gallery/pyscript.toml | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {src => packages}/gallery/README.md (100%) rename {src => packages}/gallery/assets/css/examples.css (100%) rename {src => packages}/gallery/assets/css/icosahedron.css (100%) rename {src => packages}/gallery/index.html (100%) rename {src => packages}/gallery/main.py (100%) rename {src => packages}/gallery/pyscript.toml (100%) diff --git a/src/gallery/README.md b/packages/gallery/README.md similarity index 100% rename from src/gallery/README.md rename to packages/gallery/README.md diff --git a/src/gallery/assets/css/examples.css b/packages/gallery/assets/css/examples.css similarity index 100% rename from src/gallery/assets/css/examples.css rename to packages/gallery/assets/css/examples.css diff --git a/src/gallery/assets/css/icosahedron.css b/packages/gallery/assets/css/icosahedron.css similarity index 100% rename from src/gallery/assets/css/icosahedron.css rename to packages/gallery/assets/css/icosahedron.css diff --git a/src/gallery/index.html b/packages/gallery/index.html similarity index 100% rename from src/gallery/index.html rename to packages/gallery/index.html diff --git a/src/gallery/main.py b/packages/gallery/main.py similarity index 100% rename from src/gallery/main.py rename to packages/gallery/main.py diff --git a/src/gallery/pyscript.toml b/packages/gallery/pyscript.toml similarity index 100% rename from src/gallery/pyscript.toml rename to packages/gallery/pyscript.toml From d62693f5eecffa4fc4b6d7840c970cc432a472be Mon Sep 17 00:00:00 2001 From: Aadil Goyal Date: Wed, 13 Aug 2025 21:52:22 +0530 Subject: [PATCH 054/198] Implemented keyboard shortcuts I have implemented keyboard shortcuts like p for pen, e for eraser, c for new colour etc Also to add more shortcuts, we just need to just add a few classes to it. --- src/editor/main.py | 9 ++++-- src/editor/scripts/shortcuts.py | 56 +++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 src/editor/scripts/shortcuts.py diff --git a/src/editor/main.py b/src/editor/main.py index 6edb7a38..8188d02c 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -203,7 +203,7 @@ def switch_action(e: ValueChangeEventArguments) -> None: value="pen", on_change=switch_action, ).props( - "id='action-select'", + "id='action-select' class='keyboard-shortcuts' shortcut_data='toggle,p:🖊️,e:🧽,s:💨'", ) ui.separator().classes("w-full") with ui.row(): @@ -213,7 +213,9 @@ def switch_action(e: ValueChangeEventArguments) -> None: ui.label(colour) colour_label = ui.label("00") colour_values.append(colour_label) - ui.button("Spin", on_click=spin) + ui.button("Spin", on_click=spin).props( + "class='keyboard-shortcuts' shortcut_data='btn,c'" + ) ui.separator().classes("w-full") width_input = ui.number(label="Line Width", min=1, max=50, step=1) width_slider = ui.slider( @@ -231,9 +233,10 @@ def switch_action(e: ValueChangeEventArguments) -> None: [[fetch]] from = "/scripts/" - files = ["canvas_ctx.py", "editor.py"] + files = ["canvas_ctx.py", "editor.py", "shortcuts.py"] + """) ui.run() diff --git a/src/editor/scripts/shortcuts.py b/src/editor/scripts/shortcuts.py new file mode 100644 index 00000000..a9161988 --- /dev/null +++ b/src/editor/scripts/shortcuts.py @@ -0,0 +1,56 @@ +# from js import console +from pyscript import when, document + +shortcuts_dict = dict() + +# I have commented the stuff related to logs as it was only for debug +# def log(*msgs): +# [console.log(msg) for msg in msgs] + +# log('LOG WORKING') + + +def handle_toggle(elem, data: list[str]) -> None: + btn_dict = {btn.innerText: btn for btn in elem.children} + + for d in data: + key, value = d.split(":") + action = btn_dict[value].click + shortcuts_dict[key] = action + + +def handle_btn(elem, data: list[str]) -> None: + action = elem.click + key = data[0] + + shortcuts_dict[key] = action + + +for elem in document.getElementsByClassName("keyboard-shortcuts"): + data = elem.getAttribute("shortcut_data").split(",") + if not data: + # log("No shortcut data found") + continue + if data[0] == 'toggle': + handle_toggle(elem, data[1:]) + continue + if data[0] == 'btn': + handle_btn(elem, data[1:]) + continue + + # log("Invalid shortcut data format") + + +@when("keydown", "body") +def handle_keydown(event): + if event.repeat: # runs only once when same key is pressed more than once or held down + return + # log('some key pressed') + action = shortcuts_dict.get(event.key, None) + if action: + # log('action found for key:', event.key) + action() + # else: + # log('no action found for key:', event.key) + + From 38567676bb89e05dd37e5e128152746e86d1dc86 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Wed, 13 Aug 2025 17:58:36 +0100 Subject: [PATCH 055/198] Fix formtting --- src/editor/main.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 9abb66ae..49e3bd8a 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -144,7 +144,7 @@ def upload_image(e: UploadEventArguments) -> None: ui.run_javascript(f""" let event = new Event("change"); const fileUpload = document.querySelector("#file-upload"); - fileUpload.src = "data:{e.type};base64,{content}" + fileUpload.src = "data:{e.type};base64,{content}"; fileUpload.dispatchEvent(event); """) # e.sender is the file upload element which has a .reset() method @@ -153,16 +153,15 @@ def upload_image(e: UploadEventArguments) -> None: def switch_action(e: ValueChangeEventArguments) -> None: """Fire switch action event.""" - print(type_toggle.value, e.value) if type_toggle.value == "pixel" and e.value == "smudge": action_toggle.value = "pen" ui.notify("You cannot select the smudge action while in pixel mode.", type="negative") return ui.run_javascript(f""" - const event = new Event('change'); - const actionSelect = document.querySelector("#action-select"); - actionSelect.setAttribute("value", "{e.value}"); - actionSelect.dispatchEvent(event); + const event = new Event('change'); + const actionSelect = document.querySelector("#action-select"); + actionSelect.setAttribute("value", "{e.value}"); + actionSelect.dispatchEvent(event); """) From 2390da9f488c1ae9e598ac7864efcf6eab06d31d Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Wed, 13 Aug 2025 18:03:15 +0100 Subject: [PATCH 056/198] Fix action icon staying when in pixel mode --- src/editor/scripts/editor.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 571f8cac..dc1185c5 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -348,6 +348,8 @@ def type_change(event: Event) -> None: elif ctx.type == "pixel": ctx.imageSmoothingEnabled = False ctx.scaled_by = 0.5 + buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + resize(event) From e1f540f965f9af994d6d81316d1387fbcb886bb5 Mon Sep 17 00:00:00 2001 From: Aadil Goyal Date: Thu, 14 Aug 2025 00:05:02 +0530 Subject: [PATCH 057/198] Updated the image rendering functions Added a image I made from the drawing tool and it works!!! Removed the onLoad thing because we render after every 0.02s so it will get rendered after it loads automatically, no need to wait Also tried to add a border to the photoframe, didnt work :( Finally cleaned the html file --- src/gallery/assets/css/style.css | 28 ++++++ .../assets/images/tree-test-image.avif | Bin 0 -> 272431 bytes src/gallery/index.html | 47 ++------- src/gallery/main.py | 90 ++++++++++++++---- 4 files changed, 105 insertions(+), 60 deletions(-) create mode 100644 src/gallery/assets/css/style.css create mode 100644 src/gallery/assets/images/tree-test-image.avif diff --git a/src/gallery/assets/css/style.css b/src/gallery/assets/css/style.css new file mode 100644 index 00000000..35079ad5 --- /dev/null +++ b/src/gallery/assets/css/style.css @@ -0,0 +1,28 @@ + +#loading { + outline: none; border: none; background: transparent +} + + +#instructions { + position: absolute; + top: 14%; + left: 50%; + transform: translate(-50%, -50%); /* perfectly center horizontally & vertically */ + max-width: 80%; /* optional, keeps text from stretching too wide */ + text-align: center; + color: black; + font-size: 28px; + font-family: sans-serif; + font-weight: bold; + background-color: white; /* highlight effect */ + padding: 12px 20px; /* padding inside box */ + border-radius: 8px; /* rounded corners */ + box-shadow: 0 4px 8px rgba(0,0,0,0.2); /* subtle shadow for depth */ + display: none; +} + + +body { + margin: 0; +} diff --git a/src/gallery/assets/images/tree-test-image.avif b/src/gallery/assets/images/tree-test-image.avif new file mode 100644 index 0000000000000000000000000000000000000000..f10ca8d777d1c3b42dd7f1e8c282c747160491f5 GIT binary patch literal 272431 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

03^L9* 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

rijN) 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 G - - - + - + - Raycaster Icosahedron - - + Image Gallery + @@ -76,17 +56,6 @@

Loading...

-
-
-
-
-
-
-
-
-
-
-
Click here to look around!
diff --git a/src/gallery/main.py b/src/gallery/main.py index e167fe63..ec676b39 100644 --- a/src/gallery/main.py +++ b/src/gallery/main.py @@ -6,7 +6,7 @@ from pyodide.ffi import to_js, create_proxy from pyscript import when, window, document -from js import Math, THREE, Object, console, GLTFLoader, PointerLockControls +from js import Math, THREE, LineSegments2, LineMaterial, Object, console, GLTFLoader, PointerLockControls from collections import defaultdict from enum import Enum @@ -18,6 +18,11 @@ def log(*msgs): console.log(msg) +def convert_dict_to_js_object(my_dict: dict): + """Convert a Python dict to a JavaScript object.""" + return Object.fromEntries(to_js(my_dict)) + + RENDERER = THREE.WebGLRenderer.new({"antialias": False}) RENDERER.shadowMap.enabled = False RENDERER.shadowMap.type = THREE.PCFSoftShadowMap @@ -174,34 +179,77 @@ def generate_lights() -> None: SCENE.add(ambientLight) -def load_image(): +def load_image(image_loc: str): textureLoader = THREE.TextureLoader.new() - texture = textureLoader.load( - "assets/images/test-image-nobg.png", - create_proxy(lambda e: create_plane(texture)), - create_proxy(log), - create_proxy(log), - ) + texture = textureLoader.load(image_loc) + # texture = textureLoader.load( + # image_loc, + # create_proxy(lambda e: create_photoframe(texture)), + # create_proxy(log), + # create_proxy(log), + # ) + return texture def create_plane(texture): - perms = Object.fromEntries( - to_js( - { - "map": texture, - # the color makes it look wierd so commented it - # "color": "#A6D32B", - } - ) + perms = convert_dict_to_js_object( + { + "map": texture, + "transparent": True, # removes the black bg + + # the color makes it look wierd so commented it + # "color": "#A6D32B", + } ) geometry = THREE.PlaneGeometry.new(1, 1, 1) material = THREE.MeshBasicMaterial.new(perms) plane = THREE.Mesh.new(geometry, material) - plane.position.x = 0.55 - plane.position.y = 1.6 - plane.position.z = 1.36 - SCENE.add(plane) + + plane.scale.x = 1.414 # as HiPeople said the aspect ratio is 1 : sqrt2 + + return plane + +# doesnt work, idk why +""" +def create_borders(plane): + width = 0.02 # Width of the border + + # Create a border around the plane + borderGeometry = THREE.EdgesGeometry.new(plane.geometry) + borderMaterial = LineMaterial.new( + convert_dict_to_js_object({ + "color": "#FF0000", + "linewidth": 10 + }) + ) + border = LineSegments2.new(borderGeometry, borderMaterial) + + # Set the position and scale of the border + border.position.copy(plane.position) + border.scale.x = plane.scale.x * (1 + width) + border.scale.y = plane.scale.y * (1 + width) + border.scale.z = plane.scale.z * (1 + width) + + return border + """ + +def create_photoframe(image_loc): + texture = load_image(image_loc) + plane = create_plane(texture) + # border = create_borders(plane) + + photo = THREE.Object3D.new() + photo.add(plane) + # photo.add(border) + + photo.position.x = 0 + photo.position.y = 1.6 + photo.position.z = 1.36 + + SCENE.add(photo) + + return photo def tree_print(x, indent=0): @@ -263,5 +311,5 @@ async def main(): if __name__ == "__main__": generate_lights() load_gallery() - load_image() + create_photoframe("assets/images/tree-test-image.avif") # added a new image asyncio.ensure_future(main()) From 257d4810ef0b50c1d23a03ac8c2ee3db0698e1e6 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Thu, 14 Aug 2025 13:23:45 +0100 Subject: [PATCH 058/198] Add text feature. Fix formatting for shortcuts --- src/editor/main.py | 20 ++++++++++-- src/editor/scripts/canvas_ctx.py | 27 +++++++++++++--- src/editor/scripts/editor.py | 35 +++++++++++++++++++++ src/editor/scripts/shortcuts.py | 53 ++++++++++++++++++-------------- 4 files changed, 105 insertions(+), 30 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 75f490e8..d4725cc1 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -217,9 +217,7 @@ def switch_action(e: ValueChangeEventArguments) -> None: ui.label(colour) colour_label = ui.label("00") colour_values.append(colour_label) - ui.button("Spin", on_click=spin).props( - "class='keyboard-shortcuts' shortcut_data='btn,c'" - ) + ui.button("Spin", on_click=spin).props("class='keyboard-shortcuts' shortcut_data='btn,c'") ui.separator().classes("w-full") width_input = ui.number(label="Line Width", min=1, max=50, step=1) width_slider = ui.slider( @@ -232,6 +230,22 @@ def switch_action(e: ValueChangeEventArguments) -> None: """), ).classes("width-input") width_input.bind_value(width_slider) + ui.separator().classes("w-full") + text_input = ui.input( + label="Text", + placeholder="Start typing", + ).props("id='text-input'") + ui.button( + "Add to canvas", + on_click=lambda: ( + ui.run_javascript(""" + const event = new Event("addText"); + document.querySelector("#text-input").dispatchEvent(event); + """), + text_input.set_value(""), + ), + ) + ui.add_body_html(""" diff --git a/src/editor/scripts/canvas_ctx.py b/src/editor/scripts/canvas_ctx.py index 4fe2f025..5d0363c9 100644 --- a/src/editor/scripts/canvas_ctx.py +++ b/src/editor/scripts/canvas_ctx.py @@ -8,6 +8,23 @@ from pyodide.ffi import JsProxy # pyright: ignore[reportMissingImports] +class TextMetrics: + """Textmetrics typehints.""" + + actualBoundingBoxAscent: float + actualBoundingBoxDescent: float + actualBoundingBoxLeft: float + actualBoundingBoxRight: float + alphabeticBaseline: float + emHeightAscent: float + emHeightDescent: float + fontBoundingBoxAscent: float + fontBoundingBoxDescent: float + hangingBaseline: float + ideographicBaseline: float + width: float + + class CanvasSettings: """`CanvasSettings` for `CanvasContext`.""" @@ -30,6 +47,8 @@ class CanvasContext: smudge_data: ImageData prev_data: ImageData moving_image: bool + writing_text: bool + text_value: str prev_operation: Literal[ "source-over", "source-in", @@ -264,9 +283,9 @@ def fillRect(self, x: float, y: float, width: float, height: float) -> None: """Add fillRect.""" self.ctx.fillRect(x, y, width, height) - def fillText(self) -> None: + def fillText(self, text: str, x: float, y: float) -> None: """Add fillText.""" - self.ctx.fillText() + self.ctx.fillText(text, x, y) def getContextAttributes(self) -> None: """Add getContextAttributes.""" @@ -300,9 +319,9 @@ def lineTo(self, x: float, y: float) -> None: """Make a line to the x, y given.""" self.ctx.lineTo(x, y) - def measureText(self) -> None: + def measureText(self, text: str) -> TextMetrics: """Add measureText.""" - self.ctx.measureText() + return self.ctx.measureText(text) def moveTo(self, x: float, y: float) -> None: """Move to the x, y given.""" diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index dc1185c5..7ef86d82 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -52,6 +52,7 @@ ctx.lineWidth = 5 ctx.lineCap = "round" ctx.lineJoin = "round" +ctx.font = "50px serif" # Custom attributes attached so we don't need to use global vars ctx.drawing = False @@ -60,6 +61,7 @@ ctx.bounding_rect = canvas.getBoundingClientRect() ctx.current_img = Image.new() ctx.moving_image = False +ctx.writing_text = False ctx.prev_operation = "source-over" @@ -68,6 +70,7 @@ buffer_ctx.lineWidth = 5 buffer_ctx.lineCap = "round" buffer_ctx.lineJoin = "round" +buffer_ctx.font = "50px serif" PIXEL_SIZE = 8 @@ -205,6 +208,14 @@ def mouse_tracker(event: MouseEvent) -> None: if ctx.moving_image: buffer_ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) return + if ctx.writing_text: + text_dimensions = ctx.measureText(ctx.text_value) + buffer_ctx.fillText( + ctx.text_value, + x - text_dimensions.width / 2, + y + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, + ) + return show_action_icon(x, y) if not ctx.drawing: return @@ -283,6 +294,16 @@ def canvas_click(event: MouseEvent) -> None: buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) ctx.globalCompositeOperation = ctx.prev_operation + elif ctx.writing_text: + ctx.writing_text = False + buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + text_dimensions = ctx.measureText(ctx.text_value) + ctx.fillText( + ctx.text_value, + x - text_dimensions.width / 2, + y + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, + ) + ctx.globalCompositeOperation = ctx.prev_operation elif ctx.type == "smooth": ctx.beginPath() ctx.ellipse(x, y, ctx.lineWidth / 100, ctx.lineWidth / 100, 0, 0, 2 * Math.PI) # Put a dot here @@ -334,6 +355,20 @@ def action_change(event: Event) -> None: ctx.globalCompositeOperation = "source-over" +@when("addText", "#text-input") +def add_text(_: Event) -> None: + """Add text to canvas. + + Args: + _ (Event): Add text event + """ + ctx.text_value = document.getElementById("text-input").value + if ctx.text_value: + ctx.writing_text = True + ctx.prev_operation = ctx.globalCompositeOperation + ctx.globalCompositeOperation = "source-over" + + @when("change", "#type-select") def type_change(event: Event) -> None: """Handle type change. diff --git a/src/editor/scripts/shortcuts.py b/src/editor/scripts/shortcuts.py index a9161988..7c3c1751 100644 --- a/src/editor/scripts/shortcuts.py +++ b/src/editor/scripts/shortcuts.py @@ -1,16 +1,18 @@ -# from js import console -from pyscript import when, document +# Disable missing imports as Pyscript is loaded at runtime +from js import Element, KeyboardEvent # pyright: ignore[reportMissingImports] +from pyscript import document, when # pyright: ignore[reportMissingImports] -shortcuts_dict = dict() +shortcuts_dict = {} +text_input = document.getElementById("text-input") -# I have commented the stuff related to logs as it was only for debug -# def log(*msgs): -# [console.log(msg) for msg in msgs] -# log('LOG WORKING') +def handle_toggle(elem: Element, data: list[str]) -> None: + """Add elements to dictionary. - -def handle_toggle(elem, data: list[str]) -> None: + Args: + elem (Element): Toggle element + data (list[str]): Keybind data + """ btn_dict = {btn.innerText: btn for btn in elem.children} for d in data: @@ -19,7 +21,13 @@ def handle_toggle(elem, data: list[str]) -> None: shortcuts_dict[key] = action -def handle_btn(elem, data: list[str]) -> None: +def handle_btn(elem: Element, data: list[str]) -> None: + """Add elements to dictionary. + + Args: + elem (Element): Button element + data (list[str]): Keybind data + """ action = elem.click key = data[0] @@ -29,28 +37,27 @@ def handle_btn(elem, data: list[str]) -> None: for elem in document.getElementsByClassName("keyboard-shortcuts"): data = elem.getAttribute("shortcut_data").split(",") if not data: - # log("No shortcut data found") continue - if data[0] == 'toggle': + if data[0] == "toggle": handle_toggle(elem, data[1:]) continue - if data[0] == 'btn': + if data[0] == "btn": handle_btn(elem, data[1:]) continue - # log("Invalid shortcut data format") - @when("keydown", "body") -def handle_keydown(event): - if event.repeat: # runs only once when same key is pressed more than once or held down +def handle_keydown(event: KeyboardEvent) -> None: + """Switch action when keybind is pressed. + + Args: + event (KeyboardEvent): Keydown event + """ + # Disable keybinds when writing text + if event.target == text_input: + return + if event.repeat: # runs only once when same key is pressed more than once or held down return - # log('some key pressed') action = shortcuts_dict.get(event.key, None) if action: - # log('action found for key:', event.key) action() - # else: - # log('no action found for key:', event.key) - - From 7274f4f286b54123a1ca5a148e5cc79730a14a06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Thu, 14 Aug 2025 17:57:48 +0200 Subject: [PATCH 059/198] Added 3d-model-defined gallery painting slots --- .gitignore | 1 + src/gallery/assets/gallery.glb | Bin 8148 -> 19320 bytes src/gallery/main.py | 85 +++++++++++++++++++++++---------- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/.gitignore b/.gitignore index 376abf30..108386b2 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ build/ # For now we're keeping .blend files out of the repo *.blend +*.blend1 diff --git a/src/gallery/assets/gallery.glb b/src/gallery/assets/gallery.glb index 444887456f0df416f9342f4146ead31124cb9dad..5fdbd8f209df1a754aa4b8ee97a99de962c58c9e 100644 GIT binary patch literal 19320 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 b%)jOKzZuMbraJzjd66+?F05!f-~ayuyQERO delta 66 zcmV-I0KNbCmI2g14rgpsMgjl;0Ms7<0E`Qf4t|lRJF}SxSOT-M3m*Zqc@jPZqt+w? YlL|2#3pFt|G<{utARsIhvo0|*6u%!6ivR!s diff --git a/src/gallery/main.py b/src/gallery/main.py index ec676b39..f3883199 100644 --- a/src/gallery/main.py +++ b/src/gallery/main.py @@ -4,9 +4,19 @@ ## DOCS ## https:#threejs.org/docs/ -from pyodide.ffi import to_js, create_proxy -from pyscript import when, window, document -from js import Math, THREE, LineSegments2, LineMaterial, Object, console, GLTFLoader, PointerLockControls +from pyodide.ffi import to_js, create_proxy # pyright: ignore[reportMissingImports] +from pyscript import when, window, document # pyright: ignore[reportMissingImports] +from js import ( # pyright: ignore[reportMissingImports] + Math, + THREE, + LineSegments2, + LineMaterial, + Object, + console, + GLTFLoader, + PointerLockControls, +) + from collections import defaultdict from enum import Enum @@ -195,8 +205,7 @@ def create_plane(texture): perms = convert_dict_to_js_object( { "map": texture, - "transparent": True, # removes the black bg - + "transparent": True, # removes the black bg # the color makes it look wierd so commented it # "color": "#A6D32B", } @@ -206,10 +215,15 @@ def create_plane(texture): material = THREE.MeshBasicMaterial.new(perms) plane = THREE.Mesh.new(geometry, material) - plane.scale.x = 1.414 # as HiPeople said the aspect ratio is 1 : sqrt2 + plane.scale.x = 1.414 # as HiPeople said the aspect ratio is 1 : sqrt2 return plane + +V3 = tuple[float, float, float] +V2 = tuple[float, float] +PAINTING_SLOTS: dict[int, tuple[V3, V3, V2]] = {} + # doesnt work, idk why """ def create_borders(plane): @@ -234,7 +248,21 @@ def create_borders(plane): return border """ -def create_photoframe(image_loc): + +async def snap_to_slot(photo, slot: int): + while slot not in PAINTING_SLOTS: + await asyncio.sleep(0.05) + (x, y, z), (nx, ny, nz), (w, h) = PAINTING_SLOTS[slot] + photo.position.x = x + photo.position.y = y + photo.position.z = z + + q = THREE.Quaternion.new() + q.setFromUnitVectors(THREE.Vector3.new(-1, 0, 0), THREE.Vector3.new(nx, ny, nz)) + photo.quaternion.copy(q) + + +async def create_photoframe(image_loc, slot: int = 0): texture = load_image(image_loc) plane = create_plane(texture) # border = create_borders(plane) @@ -243,10 +271,7 @@ def create_photoframe(image_loc): photo.add(plane) # photo.add(border) - photo.position.x = 0 - photo.position.y = 1.6 - photo.position.z = 1.36 - + await snap_to_slot(photo, slot) SCENE.add(photo) return photo @@ -266,24 +291,32 @@ def inner_loader(gltf): obj = gltf.scene MODULAR_GROUP.add(obj) - obj.position.x = 0 - obj.position.y = 0 - obj.position.z = 0 - - obj.rotation.x = 0 - obj.rotation.y = 0 - obj.rotation.z = 0 - - obj.scale.x = 1 - obj.scale.y = 1 - obj.scale.z = 1 - # Backface culling + assert obj.children[0].name == "Cube" for v in obj.children[0].children: v.material.side = THREE.FrontSide + for v in obj.children[1:]: + id_ = int(v.name[-3:]) + position: V3 = v.position.x, v.position.y, v.position.z + + n_array = v.geometry.attributes.normal.array + # Y-up/Z-up shenanigans + normal: V3 = (n_array[0], n_array[2], n_array[1]) + + bb = v.geometry.boundingBox + size_xyz = [abs(getattr(bb.max, i) - getattr(bb.min, i)) for i in ("x", "y", "z")] + # Height is Z + size_wh: V2 = (max(size_xyz[0], size_xyz[1]), (size_xyz[2])) + + PAINTING_SLOTS[id_] = (position, normal, size_wh) + + v.visible = False + print(f"Loading done! Here's its component structure:") print(tree_print(obj)) + print(f"Painting slots:") + print(list(PAINTING_SLOTS.keys())) def inner_progress(xhr): print(str(xhr.loaded) + " loaded") @@ -311,5 +344,9 @@ async def main(): if __name__ == "__main__": generate_lights() load_gallery() - create_photoframe("assets/images/tree-test-image.avif") # added a new image + asyncio.ensure_future(create_photoframe("assets/images/tree-test-image.avif", 0)) + asyncio.ensure_future(create_photoframe("assets/images/test-image-nobg.png", 1)) + for i in range(2, 12): + asyncio.ensure_future(create_photoframe("assets/images/test-image.webp", i)) + asyncio.ensure_future(main()) From 76294c1df64889c76306624699b43d4b4c69f13e Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Thu, 14 Aug 2025 18:16:17 +0100 Subject: [PATCH 060/198] Resizing now keeps image to scale. However things like line width aren't scaled up --- src/editor/main.py | 10 ++-- src/editor/scripts/canvas_ctx.py | 4 +- src/editor/scripts/editor.py | 94 +++++++++++++++++++++++--------- 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index d4725cc1..1c1770c3 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -75,14 +75,14 @@ def handle_type_change(dialog: ui.dialog, *, mode_value: bool) -> None: width_input.enable() width_slider.enable() file_uploader.enable() + text_input.enable() + add_text_button.enable() elif type_toggle.value == "pixel": width_input.disable() width_slider.disable() file_uploader.disable() - ui.run_javascript(""" - const event = new Event('resize'); - window.dispatchEvent(event); - """) + text_input.disable() + add_text_button.disable() def change_type(*, mode_value: bool = False) -> None: @@ -235,7 +235,7 @@ def switch_action(e: ValueChangeEventArguments) -> None: label="Text", placeholder="Start typing", ).props("id='text-input'") - ui.button( + add_text_button = ui.button( "Add to canvas", on_click=lambda: ( ui.run_javascript(""" diff --git a/src/editor/scripts/canvas_ctx.py b/src/editor/scripts/canvas_ctx.py index 5d0363c9..1a9ba536 100644 --- a/src/editor/scripts/canvas_ctx.py +++ b/src/editor/scripts/canvas_ctx.py @@ -256,9 +256,11 @@ def drawImage( image: JsProxy, dx: float, dy: float, + dWidth: float | None = None, + dHeight: float | None = None, ) -> None: """Add drawImage.""" - self.ctx.drawImage(image, dx, dy) + self.ctx.drawImage(image, dx, dy, dWidth, dHeight) def ellipse( # noqa: PLR0913 We didn't decide how many args there are so... self, diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 7ef86d82..fdc249b7 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -7,6 +7,7 @@ Math, MouseEvent, Object, + createImageBitmap, document, window, ) @@ -88,13 +89,28 @@ def draw_pixel(x: float, y: float) -> None: ctx.fillRect(x - PIXEL_SIZE // 2, y - PIXEL_SIZE // 2, PIXEL_SIZE, PIXEL_SIZE) -def show_action_icon(x: float, y: float) -> None: +def show_action_icon(x: float, y: float) -> bool: """Show icon to let user know what the action would look like. Args: x (float): X coordinate y (float): Y coordinate + + Returns: + bool: If True is returned mousemove doesn't do anything else """ + buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + if ctx.moving_image: + buffer_ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) + return True + if ctx.writing_text: + text_dimensions = ctx.measureText(ctx.text_value) + buffer_ctx.fillText( + ctx.text_value, + x - text_dimensions.width / 2, + y + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, + ) + return True if ctx.type == "smooth": buffer_ctx.beginPath() buffer_ctx.arc(x, y, ctx.lineWidth / 2, 0, 2 * Math.PI) # Put a dot here @@ -110,6 +126,7 @@ def show_action_icon(x: float, y: float) -> None: buffer_ctx.stroke() buffer_ctx.lineWidth = prev_width buffer_ctx.fillStyle = prev_fill + return False def get_smudge_data(x: float, y: float) -> ImageData: @@ -204,19 +221,8 @@ def mouse_tracker(event: MouseEvent) -> None: """ x, y = get_canvas_coords(event) - buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) - if ctx.moving_image: - buffer_ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) - return - if ctx.writing_text: - text_dimensions = ctx.measureText(ctx.text_value) - buffer_ctx.fillText( - ctx.text_value, - x - text_dimensions.width / 2, - y + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, - ) + if show_action_icon(x, y): return - show_action_icon(x, y) if not ctx.drawing: return @@ -385,7 +391,7 @@ def type_change(event: Event) -> None: ctx.scaled_by = 0.5 buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) - resize(event) + resize(event, keep_content=False) @when("reset", "body") @@ -395,15 +401,7 @@ def reset_board(_: Event) -> None: Args: _ (Event): Reset event """ - line_width = ctx.lineWidth - stroke_style = ctx.strokeStyle - global_composite_operation = ctx.globalCompositeOperation - ctx.reset() - ctx.lineWidth = line_width - ctx.strokeStyle = stroke_style - ctx.lineCap = "round" - ctx.lineJoin = "round" - ctx.globalCompositeOperation = global_composite_operation + ctx.clearRect(0, 0, canvas.width, canvas.height) @when("click", "#download-button") @@ -435,11 +433,13 @@ def upload_image(e: Event) -> None: @create_proxy -def resize(_: Event) -> None: +def resize(_: Event, keep_content: dict | bool = True) -> None: # noqa: FBT001, FBT002 keep_content has to be a positional arg """Resize canvas according to window. Args: _ (Event): Resize event + keep_content (bool): Flag to keep the existing content. It's technically not a dict. It's an Object, + but I can't type hint with it. """ data = ctx.getImageData(0, 0, canvas.width, canvas.height) line_width = ctx.lineWidth @@ -454,18 +454,58 @@ def resize(_: Event) -> None: canvas.height = display_height * ctx.scaled_by canvas.width = display_width * ctx.scaled_by - ctx.bounding_rect = canvas.getBoundingClientRect() - ctx.putImageData(data, 0, 0) + + if isinstance(keep_content, bool): + if keep_content: + createImageBitmap(data).then( + lambda img_bitmap: ctx.drawImage(img_bitmap, 0, 0, canvas.width, canvas.height), + ) + # I don't know why but keep_content is an object sometimes + elif keep_content.keep_content: # pyright: ignore[reportAttributeAccessIssue] + createImageBitmap(data).then( + lambda img_bitmap: ctx.drawImage(img_bitmap, 0, 0, canvas.width, canvas.height), + ) ctx.lineWidth = line_width ctx.strokeStyle = stroke_style + ctx.imageSmoothingEnabled = False ctx.lineCap = "round" ctx.lineJoin = "round" + ctx.font = "50px serif" ctx.globalCompositeOperation = global_composite_operation + buffer.style.height = f"{display_height}px" + buffer.style.width = f"{display_width}px" + + buffer.height = display_height * ctx.scaled_by + buffer.width = display_width * ctx.scaled_by + + buffer_ctx.imageSmoothingEnabled = False + buffer_ctx.strokeStyle = "black" + buffer_ctx.lineWidth = 5 + buffer_ctx.lineCap = "round" + buffer_ctx.lineJoin = "round" + buffer_ctx.font = "50px serif" + + +@create_proxy +def handle_scroll(e: Event) -> None: + """Handle scrolling on the canvas. Used to increase/decrease the size of images/text etc. + + Args: + e (Event): Scroll event + """ + e.preventDefault() + print(e.deltaY) + window.addEventListener("resize", resize) -ctx.current_img.onload = resize +ctx.current_img.addEventListener("load", resize) + +# The wheel event is for most browsers. The mousewheel event is deprecated +# but the wheel event is not supported by Safari and Webviewer on iOS. +canvas.addEventListener("wheel", handle_scroll) +canvas.addEventListener("mousewheel", handle_scroll) From d892b6dbbfd2a65f613e7d2fab203febbb4cf222 Mon Sep 17 00:00:00 2001 From: PiLogic Date: Thu, 14 Aug 2025 18:51:38 +0100 Subject: [PATCH 061/198] Undo/redo feature --- src/editor/main.py | 3 +++ src/editor/scripts/editor.py | 41 +++++++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index d4725cc1..8ff5b231 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -196,6 +196,9 @@ def switch_action(e: ValueChangeEventArguments) -> None: # Canvas controls with ui.column().style("flex-grow: 1; flex-basis: 0;"): + with ui.row(): + ui.button("Undo").props("id='undo-button'") + ui.button("Redo").props("id='redo-button'") action_options = { "pen": "🖊️", "eraser": "🧽", diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 7ef86d82..8b3de8be 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -62,6 +62,7 @@ ctx.current_img = Image.new() ctx.moving_image = False ctx.writing_text = False +ctx.text_placed = True ctx.prev_operation = "source-over" @@ -72,10 +73,36 @@ buffer_ctx.lineJoin = "round" buffer_ctx.font = "50px serif" +ctx.history = [] +ctx.history_index = -1 +MAX_HISTORY = 50 PIXEL_SIZE = 8 SMUDGE_BLEND_FACTOR = 0.5 +def save_history(): + ctx.history = ctx.history[:ctx.history_index + 1] + if len(ctx.history) >= MAX_HISTORY: + ctx.history.pop(0) + ctx.history_index -= 1 + + ctx.history.append(ctx.getImageData(0,0,canvas.width,canvas.height)) + ctx.history_index += 1 + window.console.log("saved") + +@when("click","#undo-button") +def undo(_: Event) -> None: + if ctx.history_index <= 0: + return + ctx.history_index -= 1 + ctx.putImageData(ctx.history[ctx.history_index], 0, 0) + +@when("click","#redo-button") +def redo(_: Event) -> None: + if ctx.history_index >= len(ctx.history) - 1: + return + ctx.history_index += 1 + ctx.putImageData(ctx.history[ctx.history_index], 0, 0) def draw_pixel(x: float, y: float) -> None: """Draws the pixel on the canvas. @@ -208,13 +235,14 @@ def mouse_tracker(event: MouseEvent) -> None: if ctx.moving_image: buffer_ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) return - if ctx.writing_text: + if not(ctx.text_placed): text_dimensions = ctx.measureText(ctx.text_value) buffer_ctx.fillText( ctx.text_value, x - text_dimensions.width / 2, y + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, ) + if ctx.writing_text: return show_action_icon(x, y) if not ctx.drawing: @@ -243,8 +271,11 @@ def stop_path(_: MouseEvent) -> None: Args: event (MouseEvent): The mouse event """ + if ctx.text_placed: + ctx.writing_text = False if ctx.drawing: ctx.drawing = False + save_history() @when("mouseenter", "#image-canvas") @@ -276,6 +307,7 @@ def leaves_canvas(event: MouseEvent) -> None: ctx.drawing = False ctx.smudge_data = None + save_history() @when("mousedown", "#image-canvas") @@ -288,14 +320,12 @@ def canvas_click(event: MouseEvent) -> None: if event.button != 0: return x, y = get_canvas_coords(event) - if ctx.moving_image: - ctx.moving_image = False buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) ctx.globalCompositeOperation = ctx.prev_operation elif ctx.writing_text: - ctx.writing_text = False + ctx.text_placed = True buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) text_dimensions = ctx.measureText(ctx.text_value) ctx.fillText( @@ -315,7 +345,6 @@ def canvas_click(event: MouseEvent) -> None: elif ctx.action == "eraser": ctx.clearRect(x - PIXEL_SIZE // 2, y - PIXEL_SIZE // 2, PIXEL_SIZE, PIXEL_SIZE) - @when("colourChange", "body") def colour_change(_: Event) -> None: """Handle colour change. @@ -365,6 +394,7 @@ def add_text(_: Event) -> None: ctx.text_value = document.getElementById("text-input").value if ctx.text_value: ctx.writing_text = True + ctx.text_placed = False ctx.prev_operation = ctx.globalCompositeOperation ctx.globalCompositeOperation = "source-over" @@ -469,3 +499,4 @@ def resize(_: Event) -> None: window.addEventListener("resize", resize) ctx.current_img.onload = resize +save_history() \ No newline at end of file From 0fe960edc968697557a426c92d754f51768d84dc Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Thu, 14 Aug 2025 19:20:27 +0100 Subject: [PATCH 062/198] Bold, italics, and font family settings for text --- src/editor/main.py | 22 ++++++++++++++++++++++ src/editor/scripts/canvas_ctx.py | 1 + src/editor/scripts/editor.py | 18 +++++++++++++++--- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 1c1770c3..add28143 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -77,12 +77,18 @@ def handle_type_change(dialog: ui.dialog, *, mode_value: bool) -> None: file_uploader.enable() text_input.enable() add_text_button.enable() + bold_checkbox.enable() + italics_checkbox.enable() + font_family.enable() elif type_toggle.value == "pixel": width_input.disable() width_slider.disable() file_uploader.disable() text_input.disable() add_text_button.disable() + bold_checkbox.disable() + italics_checkbox.disable() + font_family.disable() def change_type(*, mode_value: bool = False) -> None: @@ -235,6 +241,22 @@ def switch_action(e: ValueChangeEventArguments) -> None: label="Text", placeholder="Start typing", ).props("id='text-input'") + bold_checkbox = ui.checkbox("Bold").props("id='bold-text'") + italics_checkbox = ui.checkbox("Italics").props("id='italics-text'") + font_family = ui.select( + [ + "Arial", + "Verdana", + "Tahoma", + "Trebuchet MS", + "Times New Roman", + "Georgia", + "Garamond", + "Courier New", + "Brush Script MT", + ], + value="Arial", + ).props("id='text-font-family'") add_text_button = ui.button( "Add to canvas", on_click=lambda: ( diff --git a/src/editor/scripts/canvas_ctx.py b/src/editor/scripts/canvas_ctx.py index 1a9ba536..8ff93c9a 100644 --- a/src/editor/scripts/canvas_ctx.py +++ b/src/editor/scripts/canvas_ctx.py @@ -77,6 +77,7 @@ class CanvasContext: "color", "luminosity", ] + text_settings: dict[str, str | bool | int] # Builtin attributes canvas: Any diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index fdc249b7..da82656c 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -16,6 +16,11 @@ canvas = document.getElementById("image-canvas") buffer = document.getElementById("buffer-canvas") +text_input = document.getElementById("text-input") + +bold_input = document.getElementById("bold-text") +italics_input = document.getElementById("italics-text") +font_family_input = document.getElementById("text-font-family").querySelector("input") settings = Object() settings.willReadFrequently = True @@ -53,7 +58,7 @@ ctx.lineWidth = 5 ctx.lineCap = "round" ctx.lineJoin = "round" -ctx.font = "50px serif" +ctx.font = "50px Brush Script MT" # Custom attributes attached so we don't need to use global vars ctx.drawing = False @@ -64,6 +69,7 @@ ctx.moving_image = False ctx.writing_text = False ctx.prev_operation = "source-over" +ctx.text_settings = {"bold": False, "italics": False, "size": 50, "font-family": "Arial"} buffer_ctx.imageSmoothingEnabled = False @@ -71,7 +77,7 @@ buffer_ctx.lineWidth = 5 buffer_ctx.lineCap = "round" buffer_ctx.lineJoin = "round" -buffer_ctx.font = "50px serif" +buffer_ctx.font = f"{ctx.text_settings['size']}px {ctx.text_settings['font-family']}" PIXEL_SIZE = 8 @@ -368,11 +374,17 @@ def add_text(_: Event) -> None: Args: _ (Event): Add text event """ - ctx.text_value = document.getElementById("text-input").value + ctx.text_value = text_input.value if ctx.text_value: ctx.writing_text = True ctx.prev_operation = ctx.globalCompositeOperation ctx.globalCompositeOperation = "source-over" + ctx.text_settings["bold"] = "bold" if bold_input.getAttribute("aria-checked") == "true" else "normal" + ctx.text_settings["italics"] = "italic" if italics_input.getAttribute("aria-checked") == "true" else "normal" + ctx.text_settings["font-family"] = font_family_input.value + # I know it's too long but it doesn't work otherwise + ctx.font = f"{ctx.text_settings['italics']} {ctx.text_settings['bold']} {ctx.text_settings['size']}px {ctx.text_settings['font-family']}" # noqa: E501 + buffer_ctx.font = f"{ctx.text_settings['italics']} {ctx.text_settings['bold']} {ctx.text_settings['size']}px {ctx.text_settings['font-family']}" # noqa: E501 @when("change", "#type-select") From 863f69228c7e31f1f9a1d18f0a731dd45fd6ed0c Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Thu, 14 Aug 2025 19:52:42 +0100 Subject: [PATCH 063/198] Fix undo/redo after resizing. Add images to history. --- src/editor/scripts/canvas_ctx.py | 3 ++ src/editor/scripts/editor.py | 54 +++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src/editor/scripts/canvas_ctx.py b/src/editor/scripts/canvas_ctx.py index 8ff93c9a..c26677d0 100644 --- a/src/editor/scripts/canvas_ctx.py +++ b/src/editor/scripts/canvas_ctx.py @@ -78,6 +78,9 @@ class CanvasContext: "luminosity", ] text_settings: dict[str, str | bool | int] + history: list[Any] + history_index: int + text_placed: bool # Builtin attributes canvas: Any diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 8a922c90..885355b0 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -87,29 +87,47 @@ PIXEL_SIZE = 8 SMUDGE_BLEND_FACTOR = 0.5 -def save_history(): - ctx.history = ctx.history[:ctx.history_index + 1] + +def save_history() -> None: + """Save the historical data.""" + ctx.history = ctx.history[: ctx.history_index + 1] if len(ctx.history) >= MAX_HISTORY: ctx.history.pop(0) ctx.history_index -= 1 - - ctx.history.append(ctx.getImageData(0,0,canvas.width,canvas.height)) + + ctx.history.append(ctx.getImageData(0, 0, canvas.width, canvas.height)) ctx.history_index += 1 - window.console.log("saved") -@when("click","#undo-button") + +@when("click", "#undo-button") def undo(_: Event) -> None: + """Undo history.""" if ctx.history_index <= 0: return ctx.history_index -= 1 - ctx.putImageData(ctx.history[ctx.history_index], 0, 0) -@when("click","#redo-button") + createImageBitmap(ctx.history[ctx.history_index]).then( + lambda img_bitmap: ( + ctx.clearRect(0, 0, canvas.width, canvas.height), + ctx.drawImage(img_bitmap, 0, 0, canvas.width, canvas.height), + ), + ) + + +@when("click", "#redo-button") def redo(_: Event) -> None: + """Redo history.""" if ctx.history_index >= len(ctx.history) - 1: return ctx.history_index += 1 - ctx.putImageData(ctx.history[ctx.history_index], 0, 0) + + createImageBitmap(ctx.history[ctx.history_index]).then( + lambda img_bitmap: ( + ctx.clearRect(0, 0, canvas.width, canvas.height), + ctx.drawImage(img_bitmap, 0, 0, canvas.width, canvas.height), + ), + ) + def draw_pixel(x: float, y: float) -> None: """Draws the pixel on the canvas. @@ -256,7 +274,7 @@ def mouse_tracker(event: MouseEvent) -> None: if show_action_icon(x, y): return - if not(ctx.text_placed): + if not (ctx.text_placed): text_dimensions = ctx.measureText(ctx.text_value) buffer_ctx.fillText( ctx.text_value, @@ -341,9 +359,11 @@ def canvas_click(event: MouseEvent) -> None: return x, y = get_canvas_coords(event) if ctx.moving_image: + ctx.moving_image = False buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) ctx.globalCompositeOperation = ctx.prev_operation + save_history() elif ctx.writing_text: ctx.text_placed = True buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) @@ -365,6 +385,7 @@ def canvas_click(event: MouseEvent) -> None: elif ctx.action == "eraser": ctx.clearRect(x - PIXEL_SIZE // 2, y - PIXEL_SIZE // 2, PIXEL_SIZE, PIXEL_SIZE) + @when("colourChange", "body") def colour_change(_: Event) -> None: """Handle colour change. @@ -373,7 +394,9 @@ def colour_change(_: Event) -> None: _ (Event): Change event """ ctx.strokeStyle = window.pen.colour + ctx.fillStyle = window.pen.colour buffer_ctx.strokeStyle = window.pen.colour + buffer_ctx.fillStyle = window.pen.colour @when("change", ".width-input") @@ -494,6 +517,7 @@ def resize(_: Event, keep_content: dict | bool = True) -> None: # noqa: FBT001, data = ctx.getImageData(0, 0, canvas.width, canvas.height) line_width = ctx.lineWidth stroke_style = ctx.strokeStyle + font = ctx.font global_composite_operation = ctx.globalCompositeOperation display_height = window.innerHeight * 0.95 @@ -523,7 +547,7 @@ def resize(_: Event, keep_content: dict | bool = True) -> None: # noqa: FBT001, ctx.imageSmoothingEnabled = False ctx.lineCap = "round" ctx.lineJoin = "round" - ctx.font = "50px serif" + ctx.font = font ctx.globalCompositeOperation = global_composite_operation buffer.style.height = f"{display_height}px" @@ -533,11 +557,11 @@ def resize(_: Event, keep_content: dict | bool = True) -> None: # noqa: FBT001, buffer.width = display_width * ctx.scaled_by buffer_ctx.imageSmoothingEnabled = False - buffer_ctx.strokeStyle = "black" - buffer_ctx.lineWidth = 5 + buffer_ctx.strokeStyle = stroke_style + buffer_ctx.lineWidth = line_width buffer_ctx.lineCap = "round" buffer_ctx.lineJoin = "round" - buffer_ctx.font = "50px serif" + buffer_ctx.font = font @create_proxy @@ -560,4 +584,4 @@ def handle_scroll(e: Event) -> None: canvas.addEventListener("wheel", handle_scroll) canvas.addEventListener("mousewheel", handle_scroll) -save_history() \ No newline at end of file +save_history() From da494aba3878a9b9db7552d864b4fea77735b4c9 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Thu, 14 Aug 2025 21:53:00 +0100 Subject: [PATCH 064/198] Fix some typehinting --- src/editor/main.py | 8 +++++--- src/editor/scripts/canvas_ctx.py | 27 ++++++++++++++++++++------- src/editor/scripts/editor.py | 4 +++- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/editor/main.py b/src/editor/main.py index 826f52ab..78f8cfce 100644 --- a/src/editor/main.py +++ b/src/editor/main.py @@ -6,6 +6,8 @@ from nicegui import app, ui from nicegui.events import UploadEventArguments, ValueChangeEventArguments +SPIN_COUNT = 10 + app.add_static_files("/scripts", pathlib.Path(__file__).parent / "scripts") ui.add_head_html(""" @@ -128,11 +130,11 @@ def reset() -> None: async def spin() -> None: """Change RGB values.""" hex_value = "" - for x in range(10): + for x in range(SPIN_COUNT): for y in range(3): - text = random.choice(Hex) + random.choice(Hex) # noqa: S311 + text = random.choice(Hex) + random.choice(Hex) # noqa: S311 This isn't for cryptography colour_values[y].text = text - if x == 9: # noqa: PLR2004 + if x == SPIN_COUNT - 1: hex_value += text await asyncio.sleep(0.1) ui.run_javascript(f""" diff --git a/src/editor/scripts/canvas_ctx.py b/src/editor/scripts/canvas_ctx.py index c26677d0..0313d257 100644 --- a/src/editor/scripts/canvas_ctx.py +++ b/src/editor/scripts/canvas_ctx.py @@ -8,8 +8,21 @@ from pyodide.ffi import JsProxy # pyright: ignore[reportMissingImports] +class DOMRect: + """Bounding box typehint.""" + + bottom: float + height: float + left: float + right: float + top: float + width: float + x: float + y: float + + class TextMetrics: - """Textmetrics typehints.""" + """TextMetrics typehint.""" actualBoundingBoxAscent: float actualBoundingBoxDescent: float @@ -174,7 +187,7 @@ def rect_bottom(self) -> float: ########################################################################### # Cutstom Methods ########################################################################### - def getBoundingClientRect(self) -> Any: # noqa: ANN401 + def getBoundingClientRect(self) -> DOMRect: """Get the canvas getBoundingClientRect.""" return self.canvas.getBoundingClientRect() @@ -194,7 +207,7 @@ def get_canvas_coords(self, event: MouseEvent) -> tuple[float, float]: ########################################################################### # Builtin Methods ########################################################################### - def arc( # noqa: PLR0913 + def arc( # noqa: PLR0913 This method has this many arguments. self, x: float, y: float, @@ -266,7 +279,7 @@ def drawImage( """Add drawImage.""" self.ctx.drawImage(image, dx, dy, dWidth, dHeight) - def ellipse( # noqa: PLR0913 We didn't decide how many args there are so... + def ellipse( # noqa: PLR0913 This method has this many arguments. self, x: float, y: float, @@ -297,9 +310,9 @@ def getContextAttributes(self) -> None: """Add getContextAttributes.""" self.ctx.getContextAttributes() - def getImageData(self, sx: float, sy: float, sw: float, sh: float) -> Any: # noqa: ANN401 + def getImageData(self, sx: float, sy: float, sw: float, sh: float) -> ImageData: """Get the image data from the canvas.""" - self.ctx.getImageData(sx, sy, sw, sh) + return self.ctx.getImageData(sx, sy, sw, sh) def getLineDash(self) -> None: """Add getLineDash.""" @@ -333,7 +346,7 @@ def moveTo(self, x: float, y: float) -> None: """Move to the x, y given.""" self.ctx.moveTo(x, y) - def putImageData( # noqa: PLR0913 + def putImageData( # noqa: PLR0913 This method has this many arguments. self, imageData: ImageData, dx: float, diff --git a/src/editor/scripts/editor.py b/src/editor/scripts/editor.py index 885355b0..79809dae 100644 --- a/src/editor/scripts/editor.py +++ b/src/editor/scripts/editor.py @@ -1,5 +1,7 @@ -# Following imports have the ignore flag as they are not pip installed +# This should be under the other imports but because it isn't imported in the traditional way, it's above them. from canvas_ctx import CanvasContext + +# Following imports have the ignore flag as they are not pip installed from js import ( # pyright: ignore[reportMissingImports] Event, Image, From eaee90e8ca2b13f9100b5773c8a69464e858dc7b Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:42:31 +0300 Subject: [PATCH 065/198] Make packages/gallery a uv workspace member --- packages/gallery/pyproject.toml | 7 +++++++ pyproject.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 packages/gallery/pyproject.toml diff --git a/packages/gallery/pyproject.toml b/packages/gallery/pyproject.toml new file mode 100644 index 00000000..cd7c12f5 --- /dev/null +++ b/packages/gallery/pyproject.toml @@ -0,0 +1,7 @@ +[project] +name = "gallery" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [] diff --git a/pyproject.toml b/pyproject.toml index 20cb480d..9ee6de9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,4 +65,4 @@ ignore = [ ] [tool.uv.workspace] -members = ["packages/editor"] +members = ["packages/editor", "packages/gallery"] From 58bd0f77c706a0ba053d2281ee62275300429b14 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:43:44 +0300 Subject: [PATCH 066/198] Move src/backend under packages/backend --- packages/backend/.env.template | 69 ++++++++++++++++++++++ {src => packages}/backend/README.md | 0 packages/backend/pyproject.toml | 13 +++++ packages/backend/server/__init__.py | 91 +++++++++++++++++++++++++++++ packages/backend/server/env.py | 10 ++++ packages/backend/server/sb.py | 52 +++++++++++++++++ packages/backend/server/utils.py | 10 ++++ 7 files changed, 245 insertions(+) create mode 100644 packages/backend/.env.template rename {src => packages}/backend/README.md (100%) create mode 100644 packages/backend/pyproject.toml create mode 100644 packages/backend/server/__init__.py create mode 100644 packages/backend/server/env.py create mode 100644 packages/backend/server/sb.py create mode 100644 packages/backend/server/utils.py diff --git a/packages/backend/.env.template b/packages/backend/.env.template new file mode 100644 index 00000000..21449bf1 --- /dev/null +++ b/packages/backend/.env.template @@ -0,0 +1,69 @@ +CLIENT_ID="YOUR_CLIENT_ID" +CLIENT_SECRET="YOUR_CLIENT_SECRET" + +############ +# Secrets +# YOU MUST CHANGE THESE BEFORE GOING INTO PRODUCTION +############ + +POSTGRES_PASSWORD=your-super-secret-and-long-postgres-password +JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long +ANON_KEY=your-anon-jwt-token +SERVICE_ROLE_KEY=your-service-jwt-token +DASHBOARD_USERNAME=supabase +DASHBOARD_PASSWORD=this_password_is_insecure_and_should_be_updated +SECRET_KEY_BASE=UpNVntn3cDxHJpq99YMc1T1AQgQpc8kfYTuRgBiYa15BLrx8etQoXz3gZv1/u2oq +VAULT_ENC_KEY=your-encryption-key-32-chars-min + +############ +# Database - You can change these to any PostgreSQL database that has logical replication enabled. +############ + +POSTGRES_HOST=db +POSTGRES_DB=postgres +POSTGRES_PORT=5432 +# default user is postgres + +############ +# Supavisor -- Database pooler +############ +# Port Supavisor listens on for transaction pooling connections +POOLER_PROXY_PORT_TRANSACTION=6543 +# Maximum number of PostgreSQL connections Supavisor opens per pool +POOLER_DEFAULT_POOL_SIZE=20 +# Maximum number of client connections Supavisor accepts per pool +POOLER_MAX_CLIENT_CONN=100 +# Unique tenant identifier +POOLER_TENANT_ID=your-tenant-id +# Pool size for internal metadata storage used by Supavisor +# This is separate from client connections and used only by Supavisor itself +POOLER_DB_POOL_SIZE=5 + +############ +# API Proxy - Configuration for the Kong Reverse proxy. +############ + +KONG_HTTP_PORT=8000 +KONG_HTTPS_PORT=8443 + +############ +# Auth - Configuration for the GoTrue authentication server. +############ + +## General +SITE_URL=http://localhost:3000 +ADDITIONAL_REDIRECT_URLS=http://localhost:9000/auth +JWT_EXPIRY=3600 +DISABLE_SIGNUP=false +API_EXTERNAL_URL=http://localhost:8000 + +############ +# Studio - Configuration for the Dashboard +############ + +STUDIO_DEFAULT_ORGANIZATION=Default Organization +STUDIO_DEFAULT_PROJECT=Default Project + +STUDIO_PORT=3000 +# replace if you intend to use Studio outside of localhost +SUPABASE_PUBLIC_URL=http://localhost:8000 diff --git a/src/backend/README.md b/packages/backend/README.md similarity index 100% rename from src/backend/README.md rename to packages/backend/README.md diff --git a/packages/backend/pyproject.toml b/packages/backend/pyproject.toml new file mode 100644 index 00000000..376d0497 --- /dev/null +++ b/packages/backend/pyproject.toml @@ -0,0 +1,13 @@ +[project] +name = "backend" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "fastapi>=0.116.1", + "httpx>=0.28.1", + "pyjwt>=2.10.1", + "supabase>=2.18.0", + "uvicorn>=0.35.0", +] diff --git a/packages/backend/server/__init__.py b/packages/backend/server/__init__.py new file mode 100644 index 00000000..52137fe6 --- /dev/null +++ b/packages/backend/server/__init__.py @@ -0,0 +1,91 @@ +import secrets +from typing import Annotated + +import httpx +import jwt +from fastapi import FastAPI, HTTPException, Query, Request, Response +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import RedirectResponse +from fastapi.routing import APIRouter +from gotrue import CodeExchangeParams, SignInWithOAuthCredentials, SignInWithOAuthCredentialsOptions + +from . import env, sb + +app = FastAPI() + +app.add_middleware( + CORSMiddleware, + allow_origins=["https://*.github.com", "http://localhost:9000"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + +@app.get("/auth") +async def auth( # noqa: D103 + code: Annotated[str, Query()], + request: Request, +) -> RedirectResponse: + client = await sb.create_internal_client() + code_verifier = request.cookies.get(sb.CODE_VERIFIER_COOKIE_KEY) + if code_verifier is None: + raise HTTPException(status_code=401, detail="Code verifier not found in cookies") + + gh_response = await client.auth.exchange_code_for_session( + CodeExchangeParams( + code_verifier=code_verifier, + auth_code=code, + redirect_to="", + ), + ) + + if gh_response.session is None: + raise HTTPException(status_code=401, detail="Failed to exchange code for session") + + response = RedirectResponse("https://github.com/Matiiss/pydis-cj12-heavenly-hostas") + + response.set_cookie( + key=sb.ACCESS_TOKEN_COOKIE_KEY, + value=gh_response.session.access_token, + httponly=True, + secure=True, + samesite="none", + ) + response.set_cookie( + key=sb.REFRESH_TOKEN_COOKIE_KEY, + value=gh_response.session.refresh_token, + httponly=True, + secure=True, + samesite="none", + ) + + return response + + +@app.get("/login") +async def login() -> RedirectResponse: # noqa: D103 + sb_client = await sb.create_external_client() + + gh_response = await sb_client.auth.sign_in_with_oauth( + SignInWithOAuthCredentials( + provider="github", + options=SignInWithOAuthCredentialsOptions(redirect_to="http://localhost:9000/auth"), + ), + ) + + response = RedirectResponse(gh_response.url) + response.set_cookie( + key=sb.CODE_VERIFIER_COOKIE_KEY, + value=await sb.get_code_verifier_from_client(sb_client), + httponly=True, + secure=True, + samesite="lax", + ) + return response + + +if __name__ == "__main__": + import uvicorn + + uvicorn.run("main:app", host="localhost", port=8000, workers=1) diff --git a/packages/backend/server/env.py b/packages/backend/server/env.py new file mode 100644 index 00000000..ad806a43 --- /dev/null +++ b/packages/backend/server/env.py @@ -0,0 +1,10 @@ +from . import utils + +CLIENT_ID = utils.assure_get_env("CLIENT_ID") +CLIENT_SECRET = utils.assure_get_env("CLIENT_SECRET") +# SUPABASE_URL = utils.assure_get_env("SUPABASE_PUBLIC_URL") +SUPABASE_INTERNAL_URL = "http://kong:8000" +SUPABASE_EXTERNAL_URL = "http://localhost:8000" +SUPABASE_KEY = utils.assure_get_env("ANON_KEY") + +JWT_SECRET = utils.assure_get_env("JWT_SECRET") diff --git a/packages/backend/server/sb.py b/packages/backend/server/sb.py new file mode 100644 index 00000000..c75d758d --- /dev/null +++ b/packages/backend/server/sb.py @@ -0,0 +1,52 @@ +from fastapi import HTTPException, Request +from gotrue.constants import STORAGE_KEY +from supabase import AsyncClient, AsyncClientOptions, create_async_client + +from . import env + +ACCESS_TOKEN_COOKIE_KEY = "sb_access_token" # noqa: S105 +REFRESH_TOKEN_COOKIE_KEY = "sb_refresh_token" # noqa: S105 +CODE_VERIFIER_COOKIE_KEY = "sb_code_verifier" + + +async def create_internal_client() -> AsyncClient: + """Create a Supabase client.""" + return await create_async_client( + supabase_url=env.SUPABASE_INTERNAL_URL, + supabase_key=env.SUPABASE_KEY, + options=AsyncClientOptions(flow_type="pkce"), + ) + + +async def create_external_client() -> AsyncClient: + """Create a Supabase client.""" + return await create_async_client( + supabase_url=env.SUPABASE_EXTERNAL_URL, + supabase_key=env.SUPABASE_KEY, + options=AsyncClientOptions(flow_type="pkce"), + ) + + +async def get_code_verifier_from_client(client: AsyncClient) -> str: + """Get the code verifier from the client.""" + storage = client.auth._storage # noqa: SLF001 + code_verifier = await storage.get_item(f"{STORAGE_KEY}-code-verifier") + + if code_verifier is None: + raise HTTPException(status_code=401, detail="Code verifier not found in storage") + + return code_verifier + + +async def get_session(request: Request) -> AsyncClient: + """Get a Supabase client session.""" + access_token = request.cookies.get(ACCESS_TOKEN_COOKIE_KEY) + refresh_token = request.cookies.get(REFRESH_TOKEN_COOKIE_KEY) + + if access_token is None or refresh_token is None: + raise HTTPException(status_code=401, detail="No session tokens found") + + client = await create_internal_client() + await client.auth.set_session(access_token=access_token, refresh_token=refresh_token) + + return client diff --git a/packages/backend/server/utils.py b/packages/backend/server/utils.py new file mode 100644 index 00000000..f7d8379e --- /dev/null +++ b/packages/backend/server/utils.py @@ -0,0 +1,10 @@ +import os + + +def assure_get_env(var: str) -> str: + """Get an environment variable or raise an error if it is not set.""" + value = os.getenv(var) + if value is None: + msg = f"Environment variable '{var}' is not set." + raise OSError(msg) + return value From 0ced45a1199d4846d66e2abf449dda12cbcc9a3b Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:44:35 +0300 Subject: [PATCH 067/198] Make packages/backend a uv workspace member --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9ee6de9c..f8fd21fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -65,4 +65,4 @@ ignore = [ ] [tool.uv.workspace] -members = ["packages/editor", "packages/gallery"] +members = ["packages/backend", "packages/editor", "packages/gallery"] From 7422206e43623e3460cbc075ffb47e6b3bffd705 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:45:03 +0300 Subject: [PATCH 068/198] create a main 'package' to make uv happy --- src/app/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/app/__init__.py diff --git a/src/app/__init__.py b/src/app/__init__.py new file mode 100644 index 00000000..e69de29b From 6040cfd99e8e9c475beb08c1318cf591a42d0ac7 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:46:53 +0300 Subject: [PATCH 069/198] remove unnecessary comments and format pyproject.toml --- pyproject.toml | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f8fd21fb..a2881d8e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,43 +1,28 @@ [project] -# This section contains metadata about your project. -# Don't forget to change the name, description, and authors to match your project! -name = "code-jam-template" -description = "Add your description here" +name = "insert-catchy-name-here" +description = "A little app" authors = [ { name = "Your Name" } ] version = "0.1.0" readme = "README.md" requires-python = ">=3.12" -dependencies = [ - "nicegui>=2.22.2", -] +dependencies = [] [dependency-groups] # This `dev` group contains all the development requirements for our linting toolchain. -# Don't forget to pin your dependencies! -# This list will have to be migrated if you wish to use another dependency manager. -dev = [ - "pre-commit~=4.2.0", - "ruff~=0.12.2", -] +dev = ["pre-commit~=4.2.0", "ruff~=0.12.2"] [tool.ruff] -# Increase the line length. This breaks PEP8 but it is way easier to work with. -# The original reason for this limit was a standard vim terminal is only 79 characters, -# but this doesn't really apply anymore. line-length = 119 -# Target Python 3.12. If you decide to use a different version of Python -# you will need to update this value. -target-version = "py312" +target-version = "py312" # Target Python 3.12 # Automatically fix auto-fixable issues. fix = true # The directory containing the source code. If you choose a different project layout # you will need to update this value. -src = ["src"] +src = ["src"] # TODO: fix [tool.ruff.lint] -# Enable all linting rules. select = ["ALL"] # Ignore some of the most obnoxious linting errors. ignore = [ From 432e8521df9eaa73e511ece472bdff9490cefbc1 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:47:17 +0300 Subject: [PATCH 070/198] add authors to pyproject.toml --- pyproject.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a2881d8e..29019ff0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,12 @@ name = "insert-catchy-name-here" description = "A little app" authors = [ - { name = "Your Name" } + { name = "Matiiss", email = "matiiss@matiiss.com" }, + { name = "PiLogic" }, + { name = "HiPeople21" }, + { name = "Sergio Díaz-Esparza" }, + { name = "Alan Manning" }, + { name = "Aadil Goyal" }, ] version = "0.1.0" readme = "README.md" From 814a877b51337e294ee59525d1830e2c96828315 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:47:54 +0300 Subject: [PATCH 071/198] ignore implicit namespace warning since we're using uv workspaces and ruff complains about it (question mark) --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 29019ff0..1dbccb71 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,8 @@ ignore = [ "TD002", "TD003", "FIX", + # Namespace packages. + "INP001", ] [tool.uv.workspace] From 279f97ab7a478c6e1820f231b45c722277c81b1f Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:48:20 +0300 Subject: [PATCH 072/198] ignore supabase volumes --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 233eb87e..7a1ead0b 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ build/ .vscode/ # MacOS .DS_Store + +# supabase volumes +volumes/ From 18219ea61c043799cf5ca944b0b7889fa3f481a7 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:48:38 +0300 Subject: [PATCH 073/198] update the uv lock file --- uv.lock | 1179 ++++++++++++++++--------------------------------------- 1 file changed, 331 insertions(+), 848 deletions(-) diff --git a/uv.lock b/uv.lock index 9a29edbf..d277ff83 100644 --- a/uv.lock +++ b/uv.lock @@ -1,96 +1,22 @@ version = 1 -revision = 3 +revision = 1 requires-python = ">=3.12" -[[package]] -name = "aiofiles" -version = "24.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0b/03/a88171e277e8caa88a4c77808c20ebb04ba74cc4681bf1e9416c862de237/aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c", size = 30247, upload-time = "2024-06-24T11:02:03.584Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/45/30bb92d442636f570cb5651bc661f52b610e2eec3f891a5dc3a4c3667db0/aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5", size = 15896, upload-time = "2024-06-24T11:02:01.529Z" }, -] - -[[package]] -name = "aiohappyeyeballs" -version = "2.6.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, -] - -[[package]] -name = "aiohttp" -version = "3.12.15" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiohappyeyeballs" }, - { name = "aiosignal" }, - { name = "attrs" }, - { name = "frozenlist" }, - { name = "multidict" }, - { name = "propcache" }, - { name = "yarl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9b/e7/d92a237d8802ca88483906c388f7c201bbe96cd80a165ffd0ac2f6a8d59f/aiohttp-3.12.15.tar.gz", hash = "sha256:4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2", size = 7823716, upload-time = "2025-07-29T05:52:32.215Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/63/97/77cb2450d9b35f517d6cf506256bf4f5bda3f93a66b4ad64ba7fc917899c/aiohttp-3.12.15-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:802d3868f5776e28f7bf69d349c26fc0efadb81676d0afa88ed00d98a26340b7", size = 702333, upload-time = "2025-07-29T05:50:46.507Z" }, - { url = "https://files.pythonhosted.org/packages/83/6d/0544e6b08b748682c30b9f65640d006e51f90763b41d7c546693bc22900d/aiohttp-3.12.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2800614cd560287be05e33a679638e586a2d7401f4ddf99e304d98878c29444", size = 476948, upload-time = "2025-07-29T05:50:48.067Z" }, - { url = "https://files.pythonhosted.org/packages/3a/1d/c8c40e611e5094330284b1aea8a4b02ca0858f8458614fa35754cab42b9c/aiohttp-3.12.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8466151554b593909d30a0a125d638b4e5f3836e5aecde85b66b80ded1cb5b0d", size = 469787, upload-time = "2025-07-29T05:50:49.669Z" }, - { url = "https://files.pythonhosted.org/packages/38/7d/b76438e70319796bfff717f325d97ce2e9310f752a267bfdf5192ac6082b/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e5a495cb1be69dae4b08f35a6c4579c539e9b5706f606632102c0f855bcba7c", size = 1716590, upload-time = "2025-07-29T05:50:51.368Z" }, - { url = "https://files.pythonhosted.org/packages/79/b1/60370d70cdf8b269ee1444b390cbd72ce514f0d1cd1a715821c784d272c9/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6404dfc8cdde35c69aaa489bb3542fb86ef215fc70277c892be8af540e5e21c0", size = 1699241, upload-time = "2025-07-29T05:50:53.628Z" }, - { url = "https://files.pythonhosted.org/packages/a3/2b/4968a7b8792437ebc12186db31523f541943e99bda8f30335c482bea6879/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ead1c00f8521a5c9070fcb88f02967b1d8a0544e6d85c253f6968b785e1a2ab", size = 1754335, upload-time = "2025-07-29T05:50:55.394Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c1/49524ed553f9a0bec1a11fac09e790f49ff669bcd14164f9fab608831c4d/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6990ef617f14450bc6b34941dba4f12d5613cbf4e33805932f853fbd1cf18bfb", size = 1800491, upload-time = "2025-07-29T05:50:57.202Z" }, - { url = "https://files.pythonhosted.org/packages/de/5e/3bf5acea47a96a28c121b167f5ef659cf71208b19e52a88cdfa5c37f1fcc/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd736ed420f4db2b8148b52b46b88ed038d0354255f9a73196b7bbce3ea97545", size = 1719929, upload-time = "2025-07-29T05:50:59.192Z" }, - { url = "https://files.pythonhosted.org/packages/39/94/8ae30b806835bcd1cba799ba35347dee6961a11bd507db634516210e91d8/aiohttp-3.12.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c5092ce14361a73086b90c6efb3948ffa5be2f5b6fbcf52e8d8c8b8848bb97c", size = 1635733, upload-time = "2025-07-29T05:51:01.394Z" }, - { url = "https://files.pythonhosted.org/packages/7a/46/06cdef71dd03acd9da7f51ab3a9107318aee12ad38d273f654e4f981583a/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:aaa2234bb60c4dbf82893e934d8ee8dea30446f0647e024074237a56a08c01bd", size = 1696790, upload-time = "2025-07-29T05:51:03.657Z" }, - { url = "https://files.pythonhosted.org/packages/02/90/6b4cfaaf92ed98d0ec4d173e78b99b4b1a7551250be8937d9d67ecb356b4/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6d86a2fbdd14192e2f234a92d3b494dd4457e683ba07e5905a0b3ee25389ac9f", size = 1718245, upload-time = "2025-07-29T05:51:05.911Z" }, - { url = "https://files.pythonhosted.org/packages/2e/e6/2593751670fa06f080a846f37f112cbe6f873ba510d070136a6ed46117c6/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a041e7e2612041a6ddf1c6a33b883be6a421247c7afd47e885969ee4cc58bd8d", size = 1658899, upload-time = "2025-07-29T05:51:07.753Z" }, - { url = "https://files.pythonhosted.org/packages/8f/28/c15bacbdb8b8eb5bf39b10680d129ea7410b859e379b03190f02fa104ffd/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5015082477abeafad7203757ae44299a610e89ee82a1503e3d4184e6bafdd519", size = 1738459, upload-time = "2025-07-29T05:51:09.56Z" }, - { url = "https://files.pythonhosted.org/packages/00/de/c269cbc4faa01fb10f143b1670633a8ddd5b2e1ffd0548f7aa49cb5c70e2/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56822ff5ddfd1b745534e658faba944012346184fbfe732e0d6134b744516eea", size = 1766434, upload-time = "2025-07-29T05:51:11.423Z" }, - { url = "https://files.pythonhosted.org/packages/52/b0/4ff3abd81aa7d929b27d2e1403722a65fc87b763e3a97b3a2a494bfc63bc/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2acbbfff69019d9014508c4ba0401822e8bae5a5fdc3b6814285b71231b60f3", size = 1726045, upload-time = "2025-07-29T05:51:13.689Z" }, - { url = "https://files.pythonhosted.org/packages/71/16/949225a6a2dd6efcbd855fbd90cf476052e648fb011aa538e3b15b89a57a/aiohttp-3.12.15-cp312-cp312-win32.whl", hash = "sha256:d849b0901b50f2185874b9a232f38e26b9b3d4810095a7572eacea939132d4e1", size = 423591, upload-time = "2025-07-29T05:51:15.452Z" }, - { url = "https://files.pythonhosted.org/packages/2b/d8/fa65d2a349fe938b76d309db1a56a75c4fb8cc7b17a398b698488a939903/aiohttp-3.12.15-cp312-cp312-win_amd64.whl", hash = "sha256:b390ef5f62bb508a9d67cb3bba9b8356e23b3996da7062f1a57ce1a79d2b3d34", size = 450266, upload-time = "2025-07-29T05:51:17.239Z" }, - { url = "https://files.pythonhosted.org/packages/f2/33/918091abcf102e39d15aba2476ad9e7bd35ddb190dcdd43a854000d3da0d/aiohttp-3.12.15-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9f922ffd05034d439dde1c77a20461cf4a1b0831e6caa26151fe7aa8aaebc315", size = 696741, upload-time = "2025-07-29T05:51:19.021Z" }, - { url = "https://files.pythonhosted.org/packages/b5/2a/7495a81e39a998e400f3ecdd44a62107254803d1681d9189be5c2e4530cd/aiohttp-3.12.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2ee8a8ac39ce45f3e55663891d4b1d15598c157b4d494a4613e704c8b43112cd", size = 474407, upload-time = "2025-07-29T05:51:21.165Z" }, - { url = "https://files.pythonhosted.org/packages/49/fc/a9576ab4be2dcbd0f73ee8675d16c707cfc12d5ee80ccf4015ba543480c9/aiohttp-3.12.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3eae49032c29d356b94eee45a3f39fdf4b0814b397638c2f718e96cfadf4c4e4", size = 466703, upload-time = "2025-07-29T05:51:22.948Z" }, - { url = "https://files.pythonhosted.org/packages/09/2f/d4bcc8448cf536b2b54eed48f19682031ad182faa3a3fee54ebe5b156387/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97752ff12cc12f46a9b20327104448042fce5c33a624f88c18f66f9368091c7", size = 1705532, upload-time = "2025-07-29T05:51:25.211Z" }, - { url = "https://files.pythonhosted.org/packages/f1/f3/59406396083f8b489261e3c011aa8aee9df360a96ac8fa5c2e7e1b8f0466/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:894261472691d6fe76ebb7fcf2e5870a2ac284c7406ddc95823c8598a1390f0d", size = 1686794, upload-time = "2025-07-29T05:51:27.145Z" }, - { url = "https://files.pythonhosted.org/packages/dc/71/164d194993a8d114ee5656c3b7ae9c12ceee7040d076bf7b32fb98a8c5c6/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5fa5d9eb82ce98959fc1031c28198b431b4d9396894f385cb63f1e2f3f20ca6b", size = 1738865, upload-time = "2025-07-29T05:51:29.366Z" }, - { url = "https://files.pythonhosted.org/packages/1c/00/d198461b699188a93ead39cb458554d9f0f69879b95078dce416d3209b54/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0fa751efb11a541f57db59c1dd821bec09031e01452b2b6217319b3a1f34f3d", size = 1788238, upload-time = "2025-07-29T05:51:31.285Z" }, - { url = "https://files.pythonhosted.org/packages/85/b8/9e7175e1fa0ac8e56baa83bf3c214823ce250d0028955dfb23f43d5e61fd/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5346b93e62ab51ee2a9d68e8f73c7cf96ffb73568a23e683f931e52450e4148d", size = 1710566, upload-time = "2025-07-29T05:51:33.219Z" }, - { url = "https://files.pythonhosted.org/packages/59/e4/16a8eac9df39b48ae102ec030fa9f726d3570732e46ba0c592aeeb507b93/aiohttp-3.12.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:049ec0360f939cd164ecbfd2873eaa432613d5e77d6b04535e3d1fbae5a9e645", size = 1624270, upload-time = "2025-07-29T05:51:35.195Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f8/cd84dee7b6ace0740908fd0af170f9fab50c2a41ccbc3806aabcb1050141/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b52dcf013b57464b6d1e51b627adfd69a8053e84b7103a7cd49c030f9ca44461", size = 1677294, upload-time = "2025-07-29T05:51:37.215Z" }, - { url = "https://files.pythonhosted.org/packages/ce/42/d0f1f85e50d401eccd12bf85c46ba84f947a84839c8a1c2c5f6e8ab1eb50/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:9b2af240143dd2765e0fb661fd0361a1b469cab235039ea57663cda087250ea9", size = 1708958, upload-time = "2025-07-29T05:51:39.328Z" }, - { url = "https://files.pythonhosted.org/packages/d5/6b/f6fa6c5790fb602538483aa5a1b86fcbad66244997e5230d88f9412ef24c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ac77f709a2cde2cc71257ab2d8c74dd157c67a0558a0d2799d5d571b4c63d44d", size = 1651553, upload-time = "2025-07-29T05:51:41.356Z" }, - { url = "https://files.pythonhosted.org/packages/04/36/a6d36ad545fa12e61d11d1932eef273928b0495e6a576eb2af04297fdd3c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:47f6b962246f0a774fbd3b6b7be25d59b06fdb2f164cf2513097998fc6a29693", size = 1727688, upload-time = "2025-07-29T05:51:43.452Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c8/f195e5e06608a97a4e52c5d41c7927301bf757a8e8bb5bbf8cef6c314961/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:760fb7db442f284996e39cf9915a94492e1896baac44f06ae551974907922b64", size = 1761157, upload-time = "2025-07-29T05:51:45.643Z" }, - { url = "https://files.pythonhosted.org/packages/05/6a/ea199e61b67f25ba688d3ce93f63b49b0a4e3b3d380f03971b4646412fc6/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad702e57dc385cae679c39d318def49aef754455f237499d5b99bea4ef582e51", size = 1710050, upload-time = "2025-07-29T05:51:48.203Z" }, - { url = "https://files.pythonhosted.org/packages/b4/2e/ffeb7f6256b33635c29dbed29a22a723ff2dd7401fff42ea60cf2060abfb/aiohttp-3.12.15-cp313-cp313-win32.whl", hash = "sha256:f813c3e9032331024de2eb2e32a88d86afb69291fbc37a3a3ae81cc9917fb3d0", size = 422647, upload-time = "2025-07-29T05:51:50.718Z" }, - { url = "https://files.pythonhosted.org/packages/1b/8e/78ee35774201f38d5e1ba079c9958f7629b1fd079459aea9467441dbfbf5/aiohttp-3.12.15-cp313-cp313-win_amd64.whl", hash = "sha256:1a649001580bdb37c6fdb1bebbd7e3bc688e8ec2b5c6f52edbb664662b17dc84", size = 449067, upload-time = "2025-07-29T05:51:52.549Z" }, -] - -[[package]] -name = "aiosignal" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "frozenlist" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +[manifest] +members = [ + "backend", + "editor", + "gallery", + "insert-catchy-name-here", ] [[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" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } 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" }, + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, ] [[package]] @@ -102,45 +28,48 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252, upload-time = "2025-08-04T08:54:26.451Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252 } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" }, + { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213 }, ] [[package]] -name = "attrs" -version = "25.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, +name = "backend" +version = "0.1.0" +source = { virtual = "packages/backend" } +dependencies = [ + { name = "fastapi" }, + { name = "httpx" }, + { name = "pyjwt" }, + { name = "supabase" }, + { name = "uvicorn" }, ] -[[package]] -name = "bidict" -version = "0.23.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9a/6e/026678aa5a830e07cd9498a05d3e7e650a4f56a42f267a53d22bcda1bdc9/bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71", size = 29093, upload-time = "2024-02-18T19:09:05.748Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5", size = 32764, upload-time = "2024-02-18T19:09:04.156Z" }, +[package.metadata] +requires-dist = [ + { name = "fastapi", specifier = ">=0.116.1" }, + { name = "httpx", specifier = ">=0.28.1" }, + { name = "pyjwt", specifier = ">=2.10.1" }, + { name = "supabase", specifier = ">=2.18.0" }, + { name = "uvicorn", specifier = ">=0.35.0" }, ] [[package]] name = "certifi" version = "2025.8.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, + { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216 }, ] [[package]] name = "cfgv" version = "3.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 }, ] [[package]] @@ -150,61 +79,46 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342 } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, -] - -[[package]] -name = "code-jam-template" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "nicegui" }, -] - -[package.dev-dependencies] -dev = [ - { name = "pre-commit" }, - { name = "ruff" }, -] - -[package.metadata] -requires-dist = [{ name = "nicegui", specifier = ">=2.22.2" }] - -[package.metadata.requires-dev] -dev = [ - { name = "pre-commit", specifier = "~=4.2.0" }, - { name = "ruff", specifier = "~=0.12.2" }, + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215 }, ] [[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" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } 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" }, + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, ] [[package]] -name = "distlib" -version = "0.4.0" +name = "deprecation" +version = "2.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5a/d3/8ae2869247df154b64c1884d7346d412fed0c49df84db635aab2d1c40e62/deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff", size = 173788 } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, + { url = "https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a", size = 11178 }, ] [[package]] -name = "docutils" -version = "0.22" +name = "distlib" +version = "0.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e9/86/5b41c32ecedcfdb4c77b28b6cb14234f252075f8cdb254531727a35547dd/docutils-0.22.tar.gz", hash = "sha256:ba9d57750e92331ebe7c08a1bbf7a7f8143b86c476acd51528b042216a6aad0f", size = 2277984, upload-time = "2025-07-29T15:20:31.06Z" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605 } wheels = [ - { url = "https://files.pythonhosted.org/packages/44/57/8db39bc5f98f042e0153b1de9fb88e1a409a33cda4dd7f723c2ed71e01f6/docutils-0.22-py3-none-any.whl", hash = "sha256:4ed966a0e96a0477d852f7af31bdcb3adc049fbb35ccba358c2ea8a03287615e", size = 630709, upload-time = "2025-07-29T15:20:28.335Z" }, + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047 }, ] +[[package]] +name = "editor" +version = "0.1.0" +source = { virtual = "packages/editor" } + [[package]] name = "fastapi" version = "0.116.1" @@ -214,122 +128,81 @@ dependencies = [ { name = "starlette" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/78/d7/6c8b3bfe33eeffa208183ec037fee0cce9f7f024089ab1c5d12ef04bd27c/fastapi-0.116.1.tar.gz", hash = "sha256:ed52cbf946abfd70c5a0dccb24673f0670deeb517a88b3544d03c2a6bf283143", size = 296485, upload-time = "2025-07-11T16:22:32.057Z" } +sdist = { url = "https://files.pythonhosted.org/packages/78/d7/6c8b3bfe33eeffa208183ec037fee0cce9f7f024089ab1c5d12ef04bd27c/fastapi-0.116.1.tar.gz", hash = "sha256:ed52cbf946abfd70c5a0dccb24673f0670deeb517a88b3544d03c2a6bf283143", size = 296485 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/47/d63c60f59a59467fda0f93f46335c9d18526d7071f025cb5b89d5353ea42/fastapi-0.116.1-py3-none-any.whl", hash = "sha256:c46ac7c312df840f0c9e220f7964bada936781bc4e2e6eb71f1c4d7553786565", size = 95631, upload-time = "2025-07-11T16:22:30.485Z" }, + { url = "https://files.pythonhosted.org/packages/e5/47/d63c60f59a59467fda0f93f46335c9d18526d7071f025cb5b89d5353ea42/fastapi-0.116.1-py3-none-any.whl", hash = "sha256:c46ac7c312df840f0c9e220f7964bada936781bc4e2e6eb71f1c4d7553786565", size = 95631 }, ] [[package]] name = "filelock" version = "3.18.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075 } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 }, ] [[package]] -name = "frozenlist" -version = "1.7.0" +name = "gallery" +version = "0.1.0" +source = { virtual = "packages/gallery" } + +[[package]] +name = "gotrue" +version = "2.12.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/79/b1/b64018016eeb087db503b038296fd782586432b9c077fc5c7839e9cb6ef6/frozenlist-1.7.0.tar.gz", hash = "sha256:2e310d81923c2437ea8670467121cc3e9b0f76d3043cc1d2331d56c7fb7a3a8f", size = 45078, upload-time = "2025-06-09T23:02:35.538Z" } +dependencies = [ + { name = "httpx", extra = ["http2"] }, + { name = "pydantic" }, + { name = "pyjwt" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/67/ae47f68daae1bbb56a9fbf960dfb7d08b3dec52a6ad1e96f69c2ba5b3116/gotrue-2.12.3.tar.gz", hash = "sha256:f874cf9d0b2f0335bfbd0d6e29e3f7aff79998cd1c14d2ad814db8c06cee3852", size = 38323 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/a2/c8131383f1e66adad5f6ecfcce383d584ca94055a34d683bbb24ac5f2f1c/frozenlist-1.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3dbf9952c4bb0e90e98aec1bd992b3318685005702656bc6f67c1a32b76787f2", size = 81424, upload-time = "2025-06-09T23:00:42.24Z" }, - { url = "https://files.pythonhosted.org/packages/4c/9d/02754159955088cb52567337d1113f945b9e444c4960771ea90eb73de8db/frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f5906d3359300b8a9bb194239491122e6cf1444c2efb88865426f170c262cdb", size = 47952, upload-time = "2025-06-09T23:00:43.481Z" }, - { url = "https://files.pythonhosted.org/packages/01/7a/0046ef1bd6699b40acd2067ed6d6670b4db2f425c56980fa21c982c2a9db/frozenlist-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3dabd5a8f84573c8d10d8859a50ea2dec01eea372031929871368c09fa103478", size = 46688, upload-time = "2025-06-09T23:00:44.793Z" }, - { url = "https://files.pythonhosted.org/packages/d6/a2/a910bafe29c86997363fb4c02069df4ff0b5bc39d33c5198b4e9dd42d8f8/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa57daa5917f1738064f302bf2626281a1cb01920c32f711fbc7bc36111058a8", size = 243084, upload-time = "2025-06-09T23:00:46.125Z" }, - { url = "https://files.pythonhosted.org/packages/64/3e/5036af9d5031374c64c387469bfcc3af537fc0f5b1187d83a1cf6fab1639/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c193dda2b6d49f4c4398962810fa7d7c78f032bf45572b3e04dd5249dff27e08", size = 233524, upload-time = "2025-06-09T23:00:47.73Z" }, - { url = "https://files.pythonhosted.org/packages/06/39/6a17b7c107a2887e781a48ecf20ad20f1c39d94b2a548c83615b5b879f28/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe2b675cf0aaa6d61bf8fbffd3c274b3c9b7b1623beb3809df8a81399a4a9c4", size = 248493, upload-time = "2025-06-09T23:00:49.742Z" }, - { url = "https://files.pythonhosted.org/packages/be/00/711d1337c7327d88c44d91dd0f556a1c47fb99afc060ae0ef66b4d24793d/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8fc5d5cda37f62b262405cf9652cf0856839c4be8ee41be0afe8858f17f4c94b", size = 244116, upload-time = "2025-06-09T23:00:51.352Z" }, - { url = "https://files.pythonhosted.org/packages/24/fe/74e6ec0639c115df13d5850e75722750adabdc7de24e37e05a40527ca539/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d5ce521d1dd7d620198829b87ea002956e4319002ef0bc8d3e6d045cb4646e", size = 224557, upload-time = "2025-06-09T23:00:52.855Z" }, - { url = "https://files.pythonhosted.org/packages/8d/db/48421f62a6f77c553575201e89048e97198046b793f4a089c79a6e3268bd/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488d0a7d6a0008ca0db273c542098a0fa9e7dfaa7e57f70acef43f32b3f69dca", size = 241820, upload-time = "2025-06-09T23:00:54.43Z" }, - { url = "https://files.pythonhosted.org/packages/1d/fa/cb4a76bea23047c8462976ea7b7a2bf53997a0ca171302deae9d6dd12096/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:15a7eaba63983d22c54d255b854e8108e7e5f3e89f647fc854bd77a237e767df", size = 236542, upload-time = "2025-06-09T23:00:56.409Z" }, - { url = "https://files.pythonhosted.org/packages/5d/32/476a4b5cfaa0ec94d3f808f193301debff2ea42288a099afe60757ef6282/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1eaa7e9c6d15df825bf255649e05bd8a74b04a4d2baa1ae46d9c2d00b2ca2cb5", size = 249350, upload-time = "2025-06-09T23:00:58.468Z" }, - { url = "https://files.pythonhosted.org/packages/8d/ba/9a28042f84a6bf8ea5dbc81cfff8eaef18d78b2a1ad9d51c7bc5b029ad16/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4389e06714cfa9d47ab87f784a7c5be91d3934cd6e9a7b85beef808297cc025", size = 225093, upload-time = "2025-06-09T23:01:00.015Z" }, - { url = "https://files.pythonhosted.org/packages/bc/29/3a32959e68f9cf000b04e79ba574527c17e8842e38c91d68214a37455786/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:73bd45e1488c40b63fe5a7df892baf9e2a4d4bb6409a2b3b78ac1c6236178e01", size = 245482, upload-time = "2025-06-09T23:01:01.474Z" }, - { url = "https://files.pythonhosted.org/packages/80/e8/edf2f9e00da553f07f5fa165325cfc302dead715cab6ac8336a5f3d0adc2/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99886d98e1643269760e5fe0df31e5ae7050788dd288947f7f007209b8c33f08", size = 249590, upload-time = "2025-06-09T23:01:02.961Z" }, - { url = "https://files.pythonhosted.org/packages/1c/80/9a0eb48b944050f94cc51ee1c413eb14a39543cc4f760ed12657a5a3c45a/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:290a172aae5a4c278c6da8a96222e6337744cd9c77313efe33d5670b9f65fc43", size = 237785, upload-time = "2025-06-09T23:01:05.095Z" }, - { url = "https://files.pythonhosted.org/packages/f3/74/87601e0fb0369b7a2baf404ea921769c53b7ae00dee7dcfe5162c8c6dbf0/frozenlist-1.7.0-cp312-cp312-win32.whl", hash = "sha256:426c7bc70e07cfebc178bc4c2bf2d861d720c4fff172181eeb4a4c41d4ca2ad3", size = 39487, upload-time = "2025-06-09T23:01:06.54Z" }, - { url = "https://files.pythonhosted.org/packages/0b/15/c026e9a9fc17585a9d461f65d8593d281fedf55fbf7eb53f16c6df2392f9/frozenlist-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:563b72efe5da92e02eb68c59cb37205457c977aa7a449ed1b37e6939e5c47c6a", size = 43874, upload-time = "2025-06-09T23:01:07.752Z" }, - { url = "https://files.pythonhosted.org/packages/24/90/6b2cebdabdbd50367273c20ff6b57a3dfa89bd0762de02c3a1eb42cb6462/frozenlist-1.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee80eeda5e2a4e660651370ebffd1286542b67e268aa1ac8d6dbe973120ef7ee", size = 79791, upload-time = "2025-06-09T23:01:09.368Z" }, - { url = "https://files.pythonhosted.org/packages/83/2e/5b70b6a3325363293fe5fc3ae74cdcbc3e996c2a11dde2fd9f1fb0776d19/frozenlist-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d1a81c85417b914139e3a9b995d4a1c84559afc839a93cf2cb7f15e6e5f6ed2d", size = 47165, upload-time = "2025-06-09T23:01:10.653Z" }, - { url = "https://files.pythonhosted.org/packages/f4/25/a0895c99270ca6966110f4ad98e87e5662eab416a17e7fd53c364bf8b954/frozenlist-1.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cbb65198a9132ebc334f237d7b0df163e4de83fb4f2bdfe46c1e654bdb0c5d43", size = 45881, upload-time = "2025-06-09T23:01:12.296Z" }, - { url = "https://files.pythonhosted.org/packages/19/7c/71bb0bbe0832793c601fff68cd0cf6143753d0c667f9aec93d3c323f4b55/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dab46c723eeb2c255a64f9dc05b8dd601fde66d6b19cdb82b2e09cc6ff8d8b5d", size = 232409, upload-time = "2025-06-09T23:01:13.641Z" }, - { url = "https://files.pythonhosted.org/packages/c0/45/ed2798718910fe6eb3ba574082aaceff4528e6323f9a8570be0f7028d8e9/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6aeac207a759d0dedd2e40745575ae32ab30926ff4fa49b1635def65806fddee", size = 225132, upload-time = "2025-06-09T23:01:15.264Z" }, - { url = "https://files.pythonhosted.org/packages/ba/e2/8417ae0f8eacb1d071d4950f32f229aa6bf68ab69aab797b72a07ea68d4f/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bd8c4e58ad14b4fa7802b8be49d47993182fdd4023393899632c88fd8cd994eb", size = 237638, upload-time = "2025-06-09T23:01:16.752Z" }, - { url = "https://files.pythonhosted.org/packages/f8/b7/2ace5450ce85f2af05a871b8c8719b341294775a0a6c5585d5e6170f2ce7/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04fb24d104f425da3540ed83cbfc31388a586a7696142004c577fa61c6298c3f", size = 233539, upload-time = "2025-06-09T23:01:18.202Z" }, - { url = "https://files.pythonhosted.org/packages/46/b9/6989292c5539553dba63f3c83dc4598186ab2888f67c0dc1d917e6887db6/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a5c505156368e4ea6b53b5ac23c92d7edc864537ff911d2fb24c140bb175e60", size = 215646, upload-time = "2025-06-09T23:01:19.649Z" }, - { url = "https://files.pythonhosted.org/packages/72/31/bc8c5c99c7818293458fe745dab4fd5730ff49697ccc82b554eb69f16a24/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bd7eb96a675f18aa5c553eb7ddc24a43c8c18f22e1f9925528128c052cdbe00", size = 232233, upload-time = "2025-06-09T23:01:21.175Z" }, - { url = "https://files.pythonhosted.org/packages/59/52/460db4d7ba0811b9ccb85af996019f5d70831f2f5f255f7cc61f86199795/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:05579bf020096fe05a764f1f84cd104a12f78eaab68842d036772dc6d4870b4b", size = 227996, upload-time = "2025-06-09T23:01:23.098Z" }, - { url = "https://files.pythonhosted.org/packages/ba/c9/f4b39e904c03927b7ecf891804fd3b4df3db29b9e487c6418e37988d6e9d/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:376b6222d114e97eeec13d46c486facd41d4f43bab626b7c3f6a8b4e81a5192c", size = 242280, upload-time = "2025-06-09T23:01:24.808Z" }, - { url = "https://files.pythonhosted.org/packages/b8/33/3f8d6ced42f162d743e3517781566b8481322be321b486d9d262adf70bfb/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0aa7e176ebe115379b5b1c95b4096fb1c17cce0847402e227e712c27bdb5a949", size = 217717, upload-time = "2025-06-09T23:01:26.28Z" }, - { url = "https://files.pythonhosted.org/packages/3e/e8/ad683e75da6ccef50d0ab0c2b2324b32f84fc88ceee778ed79b8e2d2fe2e/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3fbba20e662b9c2130dc771e332a99eff5da078b2b2648153a40669a6d0e36ca", size = 236644, upload-time = "2025-06-09T23:01:27.887Z" }, - { url = "https://files.pythonhosted.org/packages/b2/14/8d19ccdd3799310722195a72ac94ddc677541fb4bef4091d8e7775752360/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f3f4410a0a601d349dd406b5713fec59b4cee7e71678d5b17edda7f4655a940b", size = 238879, upload-time = "2025-06-09T23:01:29.524Z" }, - { url = "https://files.pythonhosted.org/packages/ce/13/c12bf657494c2fd1079a48b2db49fa4196325909249a52d8f09bc9123fd7/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e2cdfaaec6a2f9327bf43c933c0319a7c429058e8537c508964a133dffee412e", size = 232502, upload-time = "2025-06-09T23:01:31.287Z" }, - { url = "https://files.pythonhosted.org/packages/d7/8b/e7f9dfde869825489382bc0d512c15e96d3964180c9499efcec72e85db7e/frozenlist-1.7.0-cp313-cp313-win32.whl", hash = "sha256:5fc4df05a6591c7768459caba1b342d9ec23fa16195e744939ba5914596ae3e1", size = 39169, upload-time = "2025-06-09T23:01:35.503Z" }, - { url = "https://files.pythonhosted.org/packages/35/89/a487a98d94205d85745080a37860ff5744b9820a2c9acbcdd9440bfddf98/frozenlist-1.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:52109052b9791a3e6b5d1b65f4b909703984b770694d3eb64fad124c835d7cba", size = 43219, upload-time = "2025-06-09T23:01:36.784Z" }, - { url = "https://files.pythonhosted.org/packages/56/d5/5c4cf2319a49eddd9dd7145e66c4866bdc6f3dbc67ca3d59685149c11e0d/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a6f86e4193bb0e235ef6ce3dde5cbabed887e0b11f516ce8a0f4d3b33078ec2d", size = 84345, upload-time = "2025-06-09T23:01:38.295Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7d/ec2c1e1dc16b85bc9d526009961953df9cec8481b6886debb36ec9107799/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:82d664628865abeb32d90ae497fb93df398a69bb3434463d172b80fc25b0dd7d", size = 48880, upload-time = "2025-06-09T23:01:39.887Z" }, - { url = "https://files.pythonhosted.org/packages/69/86/f9596807b03de126e11e7d42ac91e3d0b19a6599c714a1989a4e85eeefc4/frozenlist-1.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:912a7e8375a1c9a68325a902f3953191b7b292aa3c3fb0d71a216221deca460b", size = 48498, upload-time = "2025-06-09T23:01:41.318Z" }, - { url = "https://files.pythonhosted.org/packages/5e/cb/df6de220f5036001005f2d726b789b2c0b65f2363b104bbc16f5be8084f8/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9537c2777167488d539bc5de2ad262efc44388230e5118868e172dd4a552b146", size = 292296, upload-time = "2025-06-09T23:01:42.685Z" }, - { url = "https://files.pythonhosted.org/packages/83/1f/de84c642f17c8f851a2905cee2dae401e5e0daca9b5ef121e120e19aa825/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f34560fb1b4c3e30ba35fa9a13894ba39e5acfc5f60f57d8accde65f46cc5e74", size = 273103, upload-time = "2025-06-09T23:01:44.166Z" }, - { url = "https://files.pythonhosted.org/packages/88/3c/c840bfa474ba3fa13c772b93070893c6e9d5c0350885760376cbe3b6c1b3/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:acd03d224b0175f5a850edc104ac19040d35419eddad04e7cf2d5986d98427f1", size = 292869, upload-time = "2025-06-09T23:01:45.681Z" }, - { url = "https://files.pythonhosted.org/packages/a6/1c/3efa6e7d5a39a1d5ef0abeb51c48fb657765794a46cf124e5aca2c7a592c/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2038310bc582f3d6a09b3816ab01737d60bf7b1ec70f5356b09e84fb7408ab1", size = 291467, upload-time = "2025-06-09T23:01:47.234Z" }, - { url = "https://files.pythonhosted.org/packages/4f/00/d5c5e09d4922c395e2f2f6b79b9a20dab4b67daaf78ab92e7729341f61f6/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8c05e4c8e5f36e5e088caa1bf78a687528f83c043706640a92cb76cd6999384", size = 266028, upload-time = "2025-06-09T23:01:48.819Z" }, - { url = "https://files.pythonhosted.org/packages/4e/27/72765be905619dfde25a7f33813ac0341eb6b076abede17a2e3fbfade0cb/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:765bb588c86e47d0b68f23c1bee323d4b703218037765dcf3f25c838c6fecceb", size = 284294, upload-time = "2025-06-09T23:01:50.394Z" }, - { url = "https://files.pythonhosted.org/packages/88/67/c94103a23001b17808eb7dd1200c156bb69fb68e63fcf0693dde4cd6228c/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:32dc2e08c67d86d0969714dd484fd60ff08ff81d1a1e40a77dd34a387e6ebc0c", size = 281898, upload-time = "2025-06-09T23:01:52.234Z" }, - { url = "https://files.pythonhosted.org/packages/42/34/a3e2c00c00f9e2a9db5653bca3fec306349e71aff14ae45ecc6d0951dd24/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:c0303e597eb5a5321b4de9c68e9845ac8f290d2ab3f3e2c864437d3c5a30cd65", size = 290465, upload-time = "2025-06-09T23:01:53.788Z" }, - { url = "https://files.pythonhosted.org/packages/bb/73/f89b7fbce8b0b0c095d82b008afd0590f71ccb3dee6eee41791cf8cd25fd/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a47f2abb4e29b3a8d0b530f7c3598badc6b134562b1a5caee867f7c62fee51e3", size = 266385, upload-time = "2025-06-09T23:01:55.769Z" }, - { url = "https://files.pythonhosted.org/packages/cd/45/e365fdb554159462ca12df54bc59bfa7a9a273ecc21e99e72e597564d1ae/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3d688126c242a6fabbd92e02633414d40f50bb6002fa4cf995a1d18051525657", size = 288771, upload-time = "2025-06-09T23:01:57.4Z" }, - { url = "https://files.pythonhosted.org/packages/00/11/47b6117002a0e904f004d70ec5194fe9144f117c33c851e3d51c765962d0/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:4e7e9652b3d367c7bd449a727dc79d5043f48b88d0cbfd4f9f1060cf2b414104", size = 288206, upload-time = "2025-06-09T23:01:58.936Z" }, - { url = "https://files.pythonhosted.org/packages/40/37/5f9f3c3fd7f7746082ec67bcdc204db72dad081f4f83a503d33220a92973/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1a85e345b4c43db8b842cab1feb41be5cc0b10a1830e6295b69d7310f99becaf", size = 282620, upload-time = "2025-06-09T23:02:00.493Z" }, - { url = "https://files.pythonhosted.org/packages/0b/31/8fbc5af2d183bff20f21aa743b4088eac4445d2bb1cdece449ae80e4e2d1/frozenlist-1.7.0-cp313-cp313t-win32.whl", hash = "sha256:3a14027124ddb70dfcee5148979998066897e79f89f64b13328595c4bdf77c81", size = 43059, upload-time = "2025-06-09T23:02:02.072Z" }, - { url = "https://files.pythonhosted.org/packages/bb/ed/41956f52105b8dbc26e457c5705340c67c8cc2b79f394b79bffc09d0e938/frozenlist-1.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3bf8010d71d4507775f658e9823210b7427be36625b387221642725b515dcf3e", size = 47516, upload-time = "2025-06-09T23:02:03.779Z" }, - { url = "https://files.pythonhosted.org/packages/ee/45/b82e3c16be2182bff01179db177fe144d58b5dc787a7d4492c6ed8b9317f/frozenlist-1.7.0-py3-none-any.whl", hash = "sha256:9a5af342e34f7e97caf8c995864c7a396418ae2859cc6fdf1b1073020d516a7e", size = 13106, upload-time = "2025-06-09T23:02:34.204Z" }, + { url = "https://files.pythonhosted.org/packages/42/fa/4165d298ef89254c9f742faa3f99a61fe6fd3552b4ba44df6924f8d307d7/gotrue-2.12.3-py3-none-any.whl", hash = "sha256:b1a3c6a5fe3f92e854a026c4c19de58706a96fd5fbdcc3d620b2802f6a46a26b", size = 44022 }, ] [[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" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250 } 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" }, + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515 }, ] [[package]] -name = "httpcore" -version = "1.0.9" +name = "h2" +version = "4.2.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "certifi" }, - { name = "h11" }, + { name = "hpack" }, + { name = "hyperframe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/38/d7f80fd13e6582fb8e0df8c9a653dcc02b03ca34f4d72f34869298c5baf8/h2-4.2.0.tar.gz", hash = "sha256:c8a52129695e88b1a0578d8d2cc6842bbd79128ac685463b887ee278126ad01f", size = 2150682 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d0/9e/984486f2d0a0bd2b024bf4bc1c62688fcafa9e61991f041fb0e2def4a982/h2-4.2.0-py3-none-any.whl", hash = "sha256:479a53ad425bb29af087f3458a61d30780bc818e4ebcf01f0b536ba916462ed0", size = 60957 }, +] + +[[package]] +name = "hpack" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/48/71de9ed269fdae9c8057e5a4c0aa7402e8bb16f2c6e90b3aa53327b113f8/hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca", size = 51276 } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, + { url = "https://files.pythonhosted.org/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357 }, ] [[package]] -name = "httptools" -version = "0.6.4" +name = "httpcore" +version = "1.0.9" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639, upload-time = "2024-10-16T19:45:08.902Z" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484 } wheels = [ - { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683, upload-time = "2024-10-16T19:44:30.175Z" }, - { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337, upload-time = "2024-10-16T19:44:31.786Z" }, - { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796, upload-time = "2024-10-16T19:44:32.825Z" }, - { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837, upload-time = "2024-10-16T19:44:33.974Z" }, - { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289, upload-time = "2024-10-16T19:44:35.111Z" }, - { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779, upload-time = "2024-10-16T19:44:36.253Z" }, - { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634, upload-time = "2024-10-16T19:44:37.357Z" }, - { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214, upload-time = "2024-10-16T19:44:38.738Z" }, - { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431, upload-time = "2024-10-16T19:44:39.818Z" }, - { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121, upload-time = "2024-10-16T19:44:41.189Z" }, - { url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805, upload-time = "2024-10-16T19:44:42.384Z" }, - { url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858, upload-time = "2024-10-16T19:44:43.959Z" }, - { url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042, upload-time = "2024-10-16T19:44:45.071Z" }, - { url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682, upload-time = "2024-10-16T19:44:46.46Z" }, + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784 }, ] [[package]] @@ -342,266 +215,101 @@ dependencies = [ { name = "httpcore" }, { name = "idna" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, ] -[[package]] -name = "identify" -version = "2.6.13" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/ca/ffbabe3635bb839aa36b3a893c91a9b0d368cb4d8073e03a12896970af82/identify-2.6.13.tar.gz", hash = "sha256:da8d6c828e773620e13bfa86ea601c5a5310ba4bcd65edf378198b56a1f9fb32", size = 99243, upload-time = "2025-08-09T19:35:00.6Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/ce/461b60a3ee109518c055953729bf9ed089a04db895d47e95444071dcdef2/identify-2.6.13-py2.py3-none-any.whl", hash = "sha256:60381139b3ae39447482ecc406944190f690d4a2997f2584062089848361b33b", size = 99153, upload-time = "2025-08-09T19:34:59.1Z" }, +[package.optional-dependencies] +http2 = [ + { name = "h2" }, ] [[package]] -name = "idna" -version = "3.10" +name = "hyperframe" +version = "6.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +sdist = { url = "https://files.pythonhosted.org/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566 } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, + { url = "https://files.pythonhosted.org/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007 }, ] [[package]] -name = "ifaddr" -version = "0.2.0" +name = "identify" +version = "2.6.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/ac/fb4c578f4a3256561548cd825646680edcadb9440f3f68add95ade1eb791/ifaddr-0.2.0.tar.gz", hash = "sha256:cc0cbfcaabf765d44595825fb96a99bb12c79716b73b44330ea38ee2b0c4aed4", size = 10485, upload-time = "2022-06-15T21:40:27.561Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ca/ffbabe3635bb839aa36b3a893c91a9b0d368cb4d8073e03a12896970af82/identify-2.6.13.tar.gz", hash = "sha256:da8d6c828e773620e13bfa86ea601c5a5310ba4bcd65edf378198b56a1f9fb32", size = 99243 } wheels = [ - { url = "https://files.pythonhosted.org/packages/9c/1f/19ebc343cc71a7ffa78f17018535adc5cbdd87afb31d7c34874680148b32/ifaddr-0.2.0-py3-none-any.whl", hash = "sha256:085e0305cfe6f16ab12d72e2024030f5d52674afad6911bb1eee207177b8a748", size = 12314, upload-time = "2022-06-15T21:40:25.756Z" }, + { url = "https://files.pythonhosted.org/packages/e7/ce/461b60a3ee109518c055953729bf9ed089a04db895d47e95444071dcdef2/identify-2.6.13-py2.py3-none-any.whl", hash = "sha256:60381139b3ae39447482ecc406944190f690d4a2997f2584062089848361b33b", size = 99153 }, ] [[package]] -name = "itsdangerous" -version = "2.2.0" +name = "idna" +version = "3.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } wheels = [ - { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] [[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" }, -] +name = "insert-catchy-name-here" +version = "0.1.0" +source = { virtual = "." } -[[package]] -name = "markdown2" -version = "2.5.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/42/f8/b2ae8bf5f28f9b510ae097415e6e4cb63226bb28d7ee01aec03a755ba03b/markdown2-2.5.4.tar.gz", hash = "sha256:a09873f0b3c23dbfae589b0080587df52ad75bb09a5fa6559147554736676889", size = 145652, upload-time = "2025-07-27T16:16:24.307Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b8/06/2697b5043c3ecb720ce0d243fc7cf5024c0b5b1e450506e9b21939019963/markdown2-2.5.4-py3-none-any.whl", hash = "sha256:3c4b2934e677be7fec0e6f2de4410e116681f4ad50ec8e5ba7557be506d3f439", size = 49954, upload-time = "2025-07-27T16:16:23.026Z" }, +[package.dev-dependencies] +dev = [ + { name = "pre-commit" }, + { name = "ruff" }, ] -[[package]] -name = "markupsafe" -version = "3.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, - { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, - { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, - { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, - { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, - { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, - { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, - { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, - { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, - { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, - { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, - { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, - { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, - { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, - { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, - { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, - { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, - { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, - { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, - { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, - { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, - { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, - { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, - { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, - { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, - { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, - { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, - { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, - { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, - { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, -] +[package.metadata] -[[package]] -name = "multidict" -version = "6.6.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3d/2c/5dad12e82fbdf7470f29bff2171484bf07cb3b16ada60a6589af8f376440/multidict-6.6.3.tar.gz", hash = "sha256:798a9eb12dab0a6c2e29c1de6f3468af5cb2da6053a20dfa3344907eed0937cc", size = 101006, upload-time = "2025-06-30T15:53:46.929Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/a0/6b57988ea102da0623ea814160ed78d45a2645e4bbb499c2896d12833a70/multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:056bebbeda16b2e38642d75e9e5310c484b7c24e3841dc0fb943206a72ec89d6", size = 76514, upload-time = "2025-06-30T15:51:48.728Z" }, - { url = "https://files.pythonhosted.org/packages/07/7a/d1e92665b0850c6c0508f101f9cf0410c1afa24973e1115fe9c6a185ebf7/multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e5f481cccb3c5c5e5de5d00b5141dc589c1047e60d07e85bbd7dea3d4580d63f", size = 45394, upload-time = "2025-06-30T15:51:49.986Z" }, - { url = "https://files.pythonhosted.org/packages/52/6f/dd104490e01be6ef8bf9573705d8572f8c2d2c561f06e3826b081d9e6591/multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:10bea2ee839a759ee368b5a6e47787f399b41e70cf0c20d90dfaf4158dfb4e55", size = 43590, upload-time = "2025-06-30T15:51:51.331Z" }, - { url = "https://files.pythonhosted.org/packages/44/fe/06e0e01b1b0611e6581b7fd5a85b43dacc08b6cea3034f902f383b0873e5/multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:2334cfb0fa9549d6ce2c21af2bfbcd3ac4ec3646b1b1581c88e3e2b1779ec92b", size = 237292, upload-time = "2025-06-30T15:51:52.584Z" }, - { url = "https://files.pythonhosted.org/packages/ce/71/4f0e558fb77696b89c233c1ee2d92f3e1d5459070a0e89153c9e9e804186/multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8fee016722550a2276ca2cb5bb624480e0ed2bd49125b2b73b7010b9090e888", size = 258385, upload-time = "2025-06-30T15:51:53.913Z" }, - { url = "https://files.pythonhosted.org/packages/e3/25/cca0e68228addad24903801ed1ab42e21307a1b4b6dd2cf63da5d3ae082a/multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5511cb35f5c50a2db21047c875eb42f308c5583edf96bd8ebf7d770a9d68f6d", size = 242328, upload-time = "2025-06-30T15:51:55.672Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a3/46f2d420d86bbcb8fe660b26a10a219871a0fbf4d43cb846a4031533f3e0/multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:712b348f7f449948e0a6c4564a21c7db965af900973a67db432d724619b3c680", size = 268057, upload-time = "2025-06-30T15:51:57.037Z" }, - { url = "https://files.pythonhosted.org/packages/9e/73/1c743542fe00794a2ec7466abd3f312ccb8fad8dff9f36d42e18fb1ec33e/multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e4e15d2138ee2694e038e33b7c3da70e6b0ad8868b9f8094a72e1414aeda9c1a", size = 269341, upload-time = "2025-06-30T15:51:59.111Z" }, - { url = "https://files.pythonhosted.org/packages/a4/11/6ec9dcbe2264b92778eeb85407d1df18812248bf3506a5a1754bc035db0c/multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8df25594989aebff8a130f7899fa03cbfcc5d2b5f4a461cf2518236fe6f15961", size = 256081, upload-time = "2025-06-30T15:52:00.533Z" }, - { url = "https://files.pythonhosted.org/packages/9b/2b/631b1e2afeb5f1696846d747d36cda075bfdc0bc7245d6ba5c319278d6c4/multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:159ca68bfd284a8860f8d8112cf0521113bffd9c17568579e4d13d1f1dc76b65", size = 253581, upload-time = "2025-06-30T15:52:02.43Z" }, - { url = "https://files.pythonhosted.org/packages/bf/0e/7e3b93f79efeb6111d3bf9a1a69e555ba1d07ad1c11bceb56b7310d0d7ee/multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e098c17856a8c9ade81b4810888c5ad1914099657226283cab3062c0540b0643", size = 250750, upload-time = "2025-06-30T15:52:04.26Z" }, - { url = "https://files.pythonhosted.org/packages/ad/9e/086846c1d6601948e7de556ee464a2d4c85e33883e749f46b9547d7b0704/multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:67c92ed673049dec52d7ed39f8cf9ebbadf5032c774058b4406d18c8f8fe7063", size = 251548, upload-time = "2025-06-30T15:52:06.002Z" }, - { url = "https://files.pythonhosted.org/packages/8c/7b/86ec260118e522f1a31550e87b23542294880c97cfbf6fb18cc67b044c66/multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:bd0578596e3a835ef451784053cfd327d607fc39ea1a14812139339a18a0dbc3", size = 262718, upload-time = "2025-06-30T15:52:07.707Z" }, - { url = "https://files.pythonhosted.org/packages/8c/bd/22ce8f47abb0be04692c9fc4638508b8340987b18691aa7775d927b73f72/multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:346055630a2df2115cd23ae271910b4cae40f4e336773550dca4889b12916e75", size = 259603, upload-time = "2025-06-30T15:52:09.58Z" }, - { url = "https://files.pythonhosted.org/packages/07/9c/91b7ac1691be95cd1f4a26e36a74b97cda6aa9820632d31aab4410f46ebd/multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:555ff55a359302b79de97e0468e9ee80637b0de1fce77721639f7cd9440b3a10", size = 251351, upload-time = "2025-06-30T15:52:10.947Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5c/4d7adc739884f7a9fbe00d1eac8c034023ef8bad71f2ebe12823ca2e3649/multidict-6.6.3-cp312-cp312-win32.whl", hash = "sha256:73ab034fb8d58ff85c2bcbadc470efc3fafeea8affcf8722855fb94557f14cc5", size = 41860, upload-time = "2025-06-30T15:52:12.334Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a3/0fbc7afdf7cb1aa12a086b02959307848eb6bcc8f66fcb66c0cb57e2a2c1/multidict-6.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:04cbcce84f63b9af41bad04a54d4cc4e60e90c35b9e6ccb130be2d75b71f8c17", size = 45982, upload-time = "2025-06-30T15:52:13.6Z" }, - { url = "https://files.pythonhosted.org/packages/b8/95/8c825bd70ff9b02462dc18d1295dd08d3e9e4eb66856d292ffa62cfe1920/multidict-6.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:0f1130b896ecb52d2a1e615260f3ea2af55fa7dc3d7c3003ba0c3121a759b18b", size = 43210, upload-time = "2025-06-30T15:52:14.893Z" }, - { url = "https://files.pythonhosted.org/packages/52/1d/0bebcbbb4f000751fbd09957257903d6e002943fc668d841a4cf2fb7f872/multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:540d3c06d48507357a7d57721e5094b4f7093399a0106c211f33540fdc374d55", size = 75843, upload-time = "2025-06-30T15:52:16.155Z" }, - { url = "https://files.pythonhosted.org/packages/07/8f/cbe241b0434cfe257f65c2b1bcf9e8d5fb52bc708c5061fb29b0fed22bdf/multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9c19cea2a690f04247d43f366d03e4eb110a0dc4cd1bbeee4d445435428ed35b", size = 45053, upload-time = "2025-06-30T15:52:17.429Z" }, - { url = "https://files.pythonhosted.org/packages/32/d2/0b3b23f9dbad5b270b22a3ac3ea73ed0a50ef2d9a390447061178ed6bdb8/multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7af039820cfd00effec86bda5d8debef711a3e86a1d3772e85bea0f243a4bd65", size = 43273, upload-time = "2025-06-30T15:52:19.346Z" }, - { url = "https://files.pythonhosted.org/packages/fd/fe/6eb68927e823999e3683bc49678eb20374ba9615097d085298fd5b386564/multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:500b84f51654fdc3944e936f2922114349bf8fdcac77c3092b03449f0e5bc2b3", size = 237124, upload-time = "2025-06-30T15:52:20.773Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ab/320d8507e7726c460cb77117848b3834ea0d59e769f36fdae495f7669929/multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3fc723ab8a5c5ed6c50418e9bfcd8e6dceba6c271cee6728a10a4ed8561520c", size = 256892, upload-time = "2025-06-30T15:52:22.242Z" }, - { url = "https://files.pythonhosted.org/packages/76/60/38ee422db515ac69834e60142a1a69111ac96026e76e8e9aa347fd2e4591/multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:94c47ea3ade005b5976789baaed66d4de4480d0a0bf31cef6edaa41c1e7b56a6", size = 240547, upload-time = "2025-06-30T15:52:23.736Z" }, - { url = "https://files.pythonhosted.org/packages/27/fb/905224fde2dff042b030c27ad95a7ae744325cf54b890b443d30a789b80e/multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dbc7cf464cc6d67e83e136c9f55726da3a30176f020a36ead246eceed87f1cd8", size = 266223, upload-time = "2025-06-30T15:52:25.185Z" }, - { url = "https://files.pythonhosted.org/packages/76/35/dc38ab361051beae08d1a53965e3e1a418752fc5be4d3fb983c5582d8784/multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:900eb9f9da25ada070f8ee4a23f884e0ee66fe4e1a38c3af644256a508ad81ca", size = 267262, upload-time = "2025-06-30T15:52:26.969Z" }, - { url = "https://files.pythonhosted.org/packages/1f/a3/0a485b7f36e422421b17e2bbb5a81c1af10eac1d4476f2ff92927c730479/multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c6df517cf177da5d47ab15407143a89cd1a23f8b335f3a28d57e8b0a3dbb884", size = 254345, upload-time = "2025-06-30T15:52:28.467Z" }, - { url = "https://files.pythonhosted.org/packages/b4/59/bcdd52c1dab7c0e0d75ff19cac751fbd5f850d1fc39172ce809a74aa9ea4/multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4ef421045f13879e21c994b36e728d8e7d126c91a64b9185810ab51d474f27e7", size = 252248, upload-time = "2025-06-30T15:52:29.938Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a4/2d96aaa6eae8067ce108d4acee6f45ced5728beda55c0f02ae1072c730d1/multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6c1e61bb4f80895c081790b6b09fa49e13566df8fbff817da3f85b3a8192e36b", size = 250115, upload-time = "2025-06-30T15:52:31.416Z" }, - { url = "https://files.pythonhosted.org/packages/25/d2/ed9f847fa5c7d0677d4f02ea2c163d5e48573de3f57bacf5670e43a5ffaa/multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e5e8523bb12d7623cd8300dbd91b9e439a46a028cd078ca695eb66ba31adee3c", size = 249649, upload-time = "2025-06-30T15:52:32.996Z" }, - { url = "https://files.pythonhosted.org/packages/1f/af/9155850372563fc550803d3f25373308aa70f59b52cff25854086ecb4a79/multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ef58340cc896219e4e653dade08fea5c55c6df41bcc68122e3be3e9d873d9a7b", size = 261203, upload-time = "2025-06-30T15:52:34.521Z" }, - { url = "https://files.pythonhosted.org/packages/36/2f/c6a728f699896252cf309769089568a33c6439626648843f78743660709d/multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc9dc435ec8699e7b602b94fe0cd4703e69273a01cbc34409af29e7820f777f1", size = 258051, upload-time = "2025-06-30T15:52:35.999Z" }, - { url = "https://files.pythonhosted.org/packages/d0/60/689880776d6b18fa2b70f6cc74ff87dd6c6b9b47bd9cf74c16fecfaa6ad9/multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9e864486ef4ab07db5e9cb997bad2b681514158d6954dd1958dfb163b83d53e6", size = 249601, upload-time = "2025-06-30T15:52:37.473Z" }, - { url = "https://files.pythonhosted.org/packages/75/5e/325b11f2222a549019cf2ef879c1f81f94a0d40ace3ef55cf529915ba6cc/multidict-6.6.3-cp313-cp313-win32.whl", hash = "sha256:5633a82fba8e841bc5c5c06b16e21529573cd654f67fd833650a215520a6210e", size = 41683, upload-time = "2025-06-30T15:52:38.927Z" }, - { url = "https://files.pythonhosted.org/packages/b1/ad/cf46e73f5d6e3c775cabd2a05976547f3f18b39bee06260369a42501f053/multidict-6.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:e93089c1570a4ad54c3714a12c2cef549dc9d58e97bcded193d928649cab78e9", size = 45811, upload-time = "2025-06-30T15:52:40.207Z" }, - { url = "https://files.pythonhosted.org/packages/c5/c9/2e3fe950db28fb7c62e1a5f46e1e38759b072e2089209bc033c2798bb5ec/multidict-6.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:c60b401f192e79caec61f166da9c924e9f8bc65548d4246842df91651e83d600", size = 43056, upload-time = "2025-06-30T15:52:41.575Z" }, - { url = "https://files.pythonhosted.org/packages/3a/58/aaf8114cf34966e084a8cc9517771288adb53465188843d5a19862cb6dc3/multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:02fd8f32d403a6ff13864b0851f1f523d4c988051eea0471d4f1fd8010f11134", size = 82811, upload-time = "2025-06-30T15:52:43.281Z" }, - { url = "https://files.pythonhosted.org/packages/71/af/5402e7b58a1f5b987a07ad98f2501fdba2a4f4b4c30cf114e3ce8db64c87/multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f3aa090106b1543f3f87b2041eef3c156c8da2aed90c63a2fbed62d875c49c37", size = 48304, upload-time = "2025-06-30T15:52:45.026Z" }, - { url = "https://files.pythonhosted.org/packages/39/65/ab3c8cafe21adb45b24a50266fd747147dec7847425bc2a0f6934b3ae9ce/multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e924fb978615a5e33ff644cc42e6aa241effcf4f3322c09d4f8cebde95aff5f8", size = 46775, upload-time = "2025-06-30T15:52:46.459Z" }, - { url = "https://files.pythonhosted.org/packages/49/ba/9fcc1b332f67cc0c0c8079e263bfab6660f87fe4e28a35921771ff3eea0d/multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:b9fe5a0e57c6dbd0e2ce81ca66272282c32cd11d31658ee9553849d91289e1c1", size = 229773, upload-time = "2025-06-30T15:52:47.88Z" }, - { url = "https://files.pythonhosted.org/packages/a4/14/0145a251f555f7c754ce2dcbcd012939bbd1f34f066fa5d28a50e722a054/multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b24576f208793ebae00280c59927c3b7c2a3b1655e443a25f753c4611bc1c373", size = 250083, upload-time = "2025-06-30T15:52:49.366Z" }, - { url = "https://files.pythonhosted.org/packages/9e/d4/d5c0bd2bbb173b586c249a151a26d2fb3ec7d53c96e42091c9fef4e1f10c/multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:135631cb6c58eac37d7ac0df380294fecdc026b28837fa07c02e459c7fb9c54e", size = 228980, upload-time = "2025-06-30T15:52:50.903Z" }, - { url = "https://files.pythonhosted.org/packages/21/32/c9a2d8444a50ec48c4733ccc67254100c10e1c8ae8e40c7a2d2183b59b97/multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:274d416b0df887aef98f19f21578653982cfb8a05b4e187d4a17103322eeaf8f", size = 257776, upload-time = "2025-06-30T15:52:52.764Z" }, - { url = "https://files.pythonhosted.org/packages/68/d0/14fa1699f4ef629eae08ad6201c6b476098f5efb051b296f4c26be7a9fdf/multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e252017a817fad7ce05cafbe5711ed40faeb580e63b16755a3a24e66fa1d87c0", size = 256882, upload-time = "2025-06-30T15:52:54.596Z" }, - { url = "https://files.pythonhosted.org/packages/da/88/84a27570fbe303c65607d517a5f147cd2fc046c2d1da02b84b17b9bdc2aa/multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4cc8d848cd4fe1cdee28c13ea79ab0ed37fc2e89dd77bac86a2e7959a8c3bc", size = 247816, upload-time = "2025-06-30T15:52:56.175Z" }, - { url = "https://files.pythonhosted.org/packages/1c/60/dca352a0c999ce96a5d8b8ee0b2b9f729dcad2e0b0c195f8286269a2074c/multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9e236a7094b9c4c1b7585f6b9cca34b9d833cf079f7e4c49e6a4a6ec9bfdc68f", size = 245341, upload-time = "2025-06-30T15:52:57.752Z" }, - { url = "https://files.pythonhosted.org/packages/50/ef/433fa3ed06028f03946f3993223dada70fb700f763f70c00079533c34578/multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e0cb0ab69915c55627c933f0b555a943d98ba71b4d1c57bc0d0a66e2567c7471", size = 235854, upload-time = "2025-06-30T15:52:59.74Z" }, - { url = "https://files.pythonhosted.org/packages/1b/1f/487612ab56fbe35715320905215a57fede20de7db40a261759690dc80471/multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:81ef2f64593aba09c5212a3d0f8c906a0d38d710a011f2f42759704d4557d3f2", size = 243432, upload-time = "2025-06-30T15:53:01.602Z" }, - { url = "https://files.pythonhosted.org/packages/da/6f/ce8b79de16cd885c6f9052c96a3671373d00c59b3ee635ea93e6e81b8ccf/multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:b9cbc60010de3562545fa198bfc6d3825df430ea96d2cc509c39bd71e2e7d648", size = 252731, upload-time = "2025-06-30T15:53:03.517Z" }, - { url = "https://files.pythonhosted.org/packages/bb/fe/a2514a6aba78e5abefa1624ca85ae18f542d95ac5cde2e3815a9fbf369aa/multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70d974eaaa37211390cd02ef93b7e938de564bbffa866f0b08d07e5e65da783d", size = 247086, upload-time = "2025-06-30T15:53:05.48Z" }, - { url = "https://files.pythonhosted.org/packages/8c/22/b788718d63bb3cce752d107a57c85fcd1a212c6c778628567c9713f9345a/multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3713303e4a6663c6d01d648a68f2848701001f3390a030edaaf3fc949c90bf7c", size = 243338, upload-time = "2025-06-30T15:53:07.522Z" }, - { url = "https://files.pythonhosted.org/packages/22/d6/fdb3d0670819f2228f3f7d9af613d5e652c15d170c83e5f1c94fbc55a25b/multidict-6.6.3-cp313-cp313t-win32.whl", hash = "sha256:639ecc9fe7cd73f2495f62c213e964843826f44505a3e5d82805aa85cac6f89e", size = 47812, upload-time = "2025-06-30T15:53:09.263Z" }, - { url = "https://files.pythonhosted.org/packages/b6/d6/a9d2c808f2c489ad199723197419207ecbfbc1776f6e155e1ecea9c883aa/multidict-6.6.3-cp313-cp313t-win_amd64.whl", hash = "sha256:9f97e181f344a0ef3881b573d31de8542cc0dbc559ec68c8f8b5ce2c2e91646d", size = 53011, upload-time = "2025-06-30T15:53:11.038Z" }, - { url = "https://files.pythonhosted.org/packages/f2/40/b68001cba8188dd267590a111f9661b6256debc327137667e832bf5d66e8/multidict-6.6.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ce8b7693da41a3c4fde5871c738a81490cea5496c671d74374c8ab889e1834fb", size = 45254, upload-time = "2025-06-30T15:53:12.421Z" }, - { url = "https://files.pythonhosted.org/packages/d8/30/9aec301e9772b098c1f5c0ca0279237c9766d94b97802e9888010c64b0ed/multidict-6.6.3-py3-none-any.whl", hash = "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a", size = 12313, upload-time = "2025-06-30T15:53:45.437Z" }, +[package.metadata.requires-dev] +dev = [ + { name = "pre-commit", specifier = "~=4.2.0" }, + { name = "ruff", specifier = "~=0.12.2" }, ] [[package]] -name = "nicegui" -version = "2.22.2" +name = "nodeenv" +version = "1.9.1" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "aiofiles" }, - { name = "aiohttp" }, - { name = "certifi" }, - { name = "docutils" }, - { name = "fastapi" }, - { name = "h11" }, - { name = "httpx" }, - { name = "ifaddr" }, - { name = "itsdangerous" }, - { name = "jinja2" }, - { name = "markdown2" }, - { name = "orjson", marker = "platform_machine != 'i386' and platform_machine != 'i686'" }, - { name = "pygments" }, - { name = "python-engineio" }, - { name = "python-multipart" }, - { name = "python-socketio", extra = ["asyncio-client"] }, - { name = "starlette" }, - { name = "typing-extensions" }, - { name = "uvicorn", extra = ["standard"] }, - { name = "vbuild" }, - { name = "watchfiles" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/cc/81/aaf1432abf54f25d62a3c346a087db39c4d7a38833795c3f1eb90feab5fd/nicegui-2.22.2.tar.gz", hash = "sha256:5c0aaf2d2365c665ae42955b17d6fa7ba19526d7aa9bd02ab547917e7bd1338c", size = 13107276, upload-time = "2025-08-09T15:31:08.031Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 } wheels = [ - { url = "https://files.pythonhosted.org/packages/84/2b/141c85335df3982ca9a54da95d0c8954efe9756da8f2edaba2afbd262014/nicegui-2.22.2-py3-none-any.whl", hash = "sha256:a0e371918419af5bae7b22e6b55a29065a7a4222908af66584fd599e391b5b5f", size = 13494497, upload-time = "2025-08-09T15:31:05.235Z" }, + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 }, ] [[package]] -name = "nodeenv" -version = "1.9.1" +name = "packaging" +version = "25.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, ] [[package]] -name = "orjson" -version = "3.11.1" +name = "platformdirs" +version = "4.3.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/19/3b/fd9ff8ff64ae3900f11554d5cfc835fb73e501e043c420ad32ec574fe27f/orjson-3.11.1.tar.gz", hash = "sha256:48d82770a5fd88778063604c566f9c7c71820270c9cc9338d25147cbf34afd96", size = 5393373, upload-time = "2025-07-25T14:33:52.898Z" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362 } wheels = [ - { url = "https://files.pythonhosted.org/packages/98/77/e55513826b712807caadb2b733eee192c1df105c6bbf0d965c253b72f124/orjson-3.11.1-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2b7c8be96db3a977367250c6367793a3c5851a6ca4263f92f0b48d00702f9910", size = 240955, upload-time = "2025-07-25T14:32:34.056Z" }, - { url = "https://files.pythonhosted.org/packages/c9/88/a78132dddcc9c3b80a9fa050b3516bb2c996a9d78ca6fb47c8da2a80a696/orjson-3.11.1-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:72e18088f567bd4a45db5e3196677d9ed1605e356e500c8e32dd6e303167a13d", size = 129294, upload-time = "2025-07-25T14:32:35.323Z" }, - { url = "https://files.pythonhosted.org/packages/09/02/6591e0dcb2af6bceea96cb1b5f4b48c1445492a3ef2891ac4aa306bb6f73/orjson-3.11.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d346e2ae1ce17888f7040b65a5a4a0c9734cb20ffbd228728661e020b4c8b3a5", size = 132310, upload-time = "2025-07-25T14:32:36.53Z" }, - { url = "https://files.pythonhosted.org/packages/e9/36/c1cfbc617bcfa4835db275d5e0fe9bbdbe561a4b53d3b2de16540ec29c50/orjson-3.11.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4bda5426ebb02ceb806a7d7ec9ba9ee5e0c93fca62375151a7b1c00bc634d06b", size = 128529, upload-time = "2025-07-25T14:32:37.817Z" }, - { url = "https://files.pythonhosted.org/packages/7c/bd/91a156c5df3aaf1d68b2ab5be06f1969955a8d3e328d7794f4338ac1d017/orjson-3.11.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10506cebe908542c4f024861102673db534fd2e03eb9b95b30d94438fa220abf", size = 130925, upload-time = "2025-07-25T14:32:39.03Z" }, - { url = "https://files.pythonhosted.org/packages/a3/4c/a65cc24e9a5f87c9833a50161ab97b5edbec98bec99dfbba13827549debc/orjson-3.11.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45202ee3f5494644e064c41abd1320497fb92fd31fc73af708708af664ac3b56", size = 132432, upload-time = "2025-07-25T14:32:40.619Z" }, - { url = "https://files.pythonhosted.org/packages/2e/4d/3fc3e5d7115f4f7d01b481e29e5a79bcbcc45711a2723242787455424f40/orjson-3.11.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5adaf01b92e0402a9ac5c3ebe04effe2bbb115f0914a0a53d34ea239a746289", size = 135069, upload-time = "2025-07-25T14:32:41.84Z" }, - { url = "https://files.pythonhosted.org/packages/dc/c6/7585aa8522af896060dc0cd7c336ba6c574ae854416811ee6642c505cc95/orjson-3.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6162a1a757a1f1f4a94bc6ffac834a3602e04ad5db022dd8395a54ed9dd51c81", size = 131045, upload-time = "2025-07-25T14:32:43.085Z" }, - { url = "https://files.pythonhosted.org/packages/6a/4e/b8a0a943793d2708ebc39e743c943251e08ee0f3279c880aefd8e9cb0c70/orjson-3.11.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:78404206977c9f946613d3f916727c189d43193e708d760ea5d4b2087d6b0968", size = 130597, upload-time = "2025-07-25T14:32:44.336Z" }, - { url = "https://files.pythonhosted.org/packages/72/2b/7d30e2aed2f585d5d385fb45c71d9b16ba09be58c04e8767ae6edc6c9282/orjson-3.11.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:db48f8e81072e26df6cdb0e9fff808c28597c6ac20a13d595756cf9ba1fed48a", size = 404207, upload-time = "2025-07-25T14:32:45.612Z" }, - { url = "https://files.pythonhosted.org/packages/1b/7e/772369ec66fcbce79477f0891918309594cd00e39b67a68d4c445d2ab754/orjson-3.11.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0c1e394e67ced6bb16fea7054d99fbdd99a539cf4d446d40378d4c06e0a8548d", size = 146628, upload-time = "2025-07-25T14:32:46.981Z" }, - { url = "https://files.pythonhosted.org/packages/b4/c8/62bdb59229d7e393ae309cef41e32cc1f0b567b21dfd0742da70efb8b40c/orjson-3.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e7a840752c93d4eecd1378e9bb465c3703e127b58f675cd5c620f361b6cf57a4", size = 135449, upload-time = "2025-07-25T14:32:48.727Z" }, - { url = "https://files.pythonhosted.org/packages/02/47/1c99aa60e19f781424eabeaacd9e999eafe5b59c81ead4273b773f0f3af1/orjson-3.11.1-cp312-cp312-win32.whl", hash = "sha256:4537b0e09f45d2b74cb69c7f39ca1e62c24c0488d6bf01cd24673c74cd9596bf", size = 136653, upload-time = "2025-07-25T14:32:50.622Z" }, - { url = "https://files.pythonhosted.org/packages/31/9a/132999929a2892ab07e916669accecc83e5bff17e11a1186b4c6f23231f0/orjson-3.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:dbee6b050062540ae404530cacec1bf25e56e8d87d8d9b610b935afeb6725cae", size = 131426, upload-time = "2025-07-25T14:32:51.883Z" }, - { url = "https://files.pythonhosted.org/packages/9c/77/d984ee5a1ca341090902e080b187721ba5d1573a8d9759e0c540975acfb2/orjson-3.11.1-cp312-cp312-win_arm64.whl", hash = "sha256:f55e557d4248322d87c4673e085c7634039ff04b47bfc823b87149ae12bef60d", size = 126635, upload-time = "2025-07-25T14:32:53.2Z" }, - { url = "https://files.pythonhosted.org/packages/c9/e9/880ef869e6f66279ce3a381a32afa0f34e29a94250146911eee029e56efc/orjson-3.11.1-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:53cfefe4af059e65aabe9683f76b9c88bf34b4341a77d329227c2424e0e59b0e", size = 240835, upload-time = "2025-07-25T14:32:54.507Z" }, - { url = "https://files.pythonhosted.org/packages/f0/1f/52039ef3d03eeea21763b46bc99ebe11d9de8510c72b7b5569433084a17e/orjson-3.11.1-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:93d5abed5a6f9e1b6f9b5bf6ed4423c11932b5447c2f7281d3b64e0f26c6d064", size = 129226, upload-time = "2025-07-25T14:32:55.908Z" }, - { url = "https://files.pythonhosted.org/packages/ee/da/59fdffc9465a760be2cd3764ef9cd5535eec8f095419f972fddb123b6d0e/orjson-3.11.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dbf06642f3db2966df504944cdd0eb68ca2717f0353bb20b20acd78109374a6", size = 132261, upload-time = "2025-07-25T14:32:57.538Z" }, - { url = "https://files.pythonhosted.org/packages/bb/5c/8610911c7e969db7cf928c8baac4b2f1e68d314bc3057acf5ca64f758435/orjson-3.11.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dddf4e78747fa7f2188273f84562017a3c4f0824485b78372513c1681ea7a894", size = 128614, upload-time = "2025-07-25T14:32:58.808Z" }, - { url = "https://files.pythonhosted.org/packages/f7/a1/a1db9d4310d014c90f3b7e9b72c6fb162cba82c5f46d0b345669eaebdd3a/orjson-3.11.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa3fe8653c9f57f0e16f008e43626485b6723b84b2f741f54d1258095b655912", size = 130968, upload-time = "2025-07-25T14:33:00.038Z" }, - { url = "https://files.pythonhosted.org/packages/56/ff/11acd1fd7c38ea7a1b5d6bf582ae3da05931bee64620995eb08fd63c77fe/orjson-3.11.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6334d2382aff975a61f6f4d1c3daf39368b887c7de08f7c16c58f485dcf7adb2", size = 132439, upload-time = "2025-07-25T14:33:01.354Z" }, - { url = "https://files.pythonhosted.org/packages/70/f9/bb564dd9450bf8725e034a8ad7f4ae9d4710a34caf63b85ce1c0c6d40af0/orjson-3.11.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3d0855b643f259ee0cb76fe3df4c04483354409a520a902b067c674842eb6b8", size = 135299, upload-time = "2025-07-25T14:33:03.079Z" }, - { url = "https://files.pythonhosted.org/packages/94/bb/c8eafe6051405e241dda3691db4d9132d3c3462d1d10a17f50837dd130b4/orjson-3.11.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0eacdfeefd0a79987926476eb16e0245546bedeb8febbbbcf4b653e79257a8e4", size = 131004, upload-time = "2025-07-25T14:33:04.416Z" }, - { url = "https://files.pythonhosted.org/packages/a2/40/bed8d7dcf1bd2df8813bf010a25f645863a2f75e8e0ebdb2b55784cf1a62/orjson-3.11.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0ed07faf9e4873518c60480325dcbc16d17c59a165532cccfb409b4cdbaeff24", size = 130583, upload-time = "2025-07-25T14:33:05.768Z" }, - { url = "https://files.pythonhosted.org/packages/57/e7/cfa2eb803ad52d74fbb5424a429b5be164e51d23f1d853e5e037173a5c48/orjson-3.11.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d6d308dd578ae3658f62bb9eba54801533225823cd3248c902be1ebc79b5e014", size = 404218, upload-time = "2025-07-25T14:33:07.117Z" }, - { url = "https://files.pythonhosted.org/packages/d5/21/bc703af5bc6e9c7e18dcf4404dcc4ec305ab9bb6c82d3aee5952c0c56abf/orjson-3.11.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c4aa13ca959ba6b15c0a98d3d204b850f9dc36c08c9ce422ffb024eb30d6e058", size = 146605, upload-time = "2025-07-25T14:33:08.55Z" }, - { url = "https://files.pythonhosted.org/packages/8f/fe/d26a0150534c4965a06f556aa68bf3c3b82999d5d7b0facd3af7b390c4af/orjson-3.11.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:be3d0653322abc9b68e5bcdaee6cfd58fcbe9973740ab222b87f4d687232ab1f", size = 135434, upload-time = "2025-07-25T14:33:09.967Z" }, - { url = "https://files.pythonhosted.org/packages/89/b6/1cb28365f08cbcffc464f8512320c6eb6db6a653f03d66de47ea3c19385f/orjson-3.11.1-cp313-cp313-win32.whl", hash = "sha256:4dd34e7e2518de8d7834268846f8cab7204364f427c56fb2251e098da86f5092", size = 136596, upload-time = "2025-07-25T14:33:11.333Z" }, - { url = "https://files.pythonhosted.org/packages/f9/35/7870d0d3ed843652676d84d8a6038791113eacc85237b673b925802826b8/orjson-3.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:d6895d32032b6362540e6d0694b19130bb4f2ad04694002dce7d8af588ca5f77", size = 131319, upload-time = "2025-07-25T14:33:12.614Z" }, - { url = "https://files.pythonhosted.org/packages/b7/3e/5bcd50fd865eb664d4edfdaaaff51e333593ceb5695a22c0d0a0d2b187ba/orjson-3.11.1-cp313-cp313-win_arm64.whl", hash = "sha256:bb7c36d5d3570fcbb01d24fa447a21a7fe5a41141fd88e78f7994053cc4e28f4", size = 126613, upload-time = "2025-07-25T14:33:13.927Z" }, - { url = "https://files.pythonhosted.org/packages/61/d8/0a5cd31ed100b4e569e143cb0cddefc21f0bcb8ce284f44bca0bb0e10f3d/orjson-3.11.1-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7b71ef394327b3d0b39f6ea7ade2ecda2731a56c6a7cbf0d6a7301203b92a89b", size = 240819, upload-time = "2025-07-25T14:33:15.223Z" }, - { url = "https://files.pythonhosted.org/packages/b9/95/7eb2c76c92192ceca16bc81845ff100bbb93f568b4b94d914b6a4da47d61/orjson-3.11.1-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:77c0fe28ed659b62273995244ae2aa430e432c71f86e4573ab16caa2f2e3ca5e", size = 129218, upload-time = "2025-07-25T14:33:16.637Z" }, - { url = "https://files.pythonhosted.org/packages/da/84/e6b67f301b18adbbc346882f456bea44daebbd032ba725dbd7b741e3a7f1/orjson-3.11.1-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:1495692f1f1ba2467df429343388a0ed259382835922e124c0cfdd56b3d1f727", size = 132238, upload-time = "2025-07-25T14:33:17.934Z" }, - { url = "https://files.pythonhosted.org/packages/84/78/a45a86e29d9b2f391f9d00b22da51bc4b46b86b788fd42df2c5fcf3e8005/orjson-3.11.1-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:08c6a762fca63ca4dc04f66c48ea5d2428db55839fec996890e1bfaf057b658c", size = 130998, upload-time = "2025-07-25T14:33:19.282Z" }, - { url = "https://files.pythonhosted.org/packages/ea/8f/6eb3ee6760d93b2ce996a8529164ee1f5bafbdf64b74c7314b68db622b32/orjson-3.11.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9e26794fe3976810b2c01fda29bd9ac7c91a3c1284b29cc9a383989f7b614037", size = 130559, upload-time = "2025-07-25T14:33:20.589Z" }, - { url = "https://files.pythonhosted.org/packages/1b/78/9572ae94bdba6813917c9387e7834224c011ea6b4530ade07d718fd31598/orjson-3.11.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4b4b4f8f0b1d3ef8dc73e55363a0ffe012a42f4e2f1a140bf559698dca39b3fa", size = 404231, upload-time = "2025-07-25T14:33:22.019Z" }, - { url = "https://files.pythonhosted.org/packages/1f/a3/68381ad0757e084927c5ee6cfdeab1c6c89405949ee493db557e60871c4c/orjson-3.11.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:848be553ea35aa89bfefbed2e27c8a41244c862956ab8ba00dc0b27e84fd58de", size = 146658, upload-time = "2025-07-25T14:33:23.675Z" }, - { url = "https://files.pythonhosted.org/packages/00/db/fac56acf77aab778296c3f541a3eec643266f28ecd71d6c0cba251e47655/orjson-3.11.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c964c29711a4b1df52f8d9966f015402a6cf87753a406c1c4405c407dd66fd45", size = 135443, upload-time = "2025-07-25T14:33:25.04Z" }, - { url = "https://files.pythonhosted.org/packages/76/b1/326fa4b87426197ead61c1eec2eeb3babc9eb33b480ac1f93894e40c8c08/orjson-3.11.1-cp314-cp314-win32.whl", hash = "sha256:33aada2e6b6bc9c540d396528b91e666cedb383740fee6e6a917f561b390ecb1", size = 136643, upload-time = "2025-07-25T14:33:26.449Z" }, - { url = "https://files.pythonhosted.org/packages/0f/8e/2987ae2109f3bfd39680f8a187d1bc09ad7f8fb019dcdc719b08c7242ade/orjson-3.11.1-cp314-cp314-win_amd64.whl", hash = "sha256:68e10fd804e44e36188b9952543e3fa22f5aa8394da1b5283ca2b423735c06e8", size = 131324, upload-time = "2025-07-25T14:33:27.896Z" }, - { url = "https://files.pythonhosted.org/packages/21/5f/253e08e6974752b124fbf3a4de3ad53baa766b0cb4a333d47706d307e396/orjson-3.11.1-cp314-cp314-win_arm64.whl", hash = "sha256:f3cf6c07f8b32127d836be8e1c55d4f34843f7df346536da768e9f73f22078a1", size = 126605, upload-time = "2025-07-25T14:33:29.244Z" }, + { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567 }, ] [[package]] -name = "platformdirs" -version = "4.3.8" +name = "postgrest" +version = "1.1.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +dependencies = [ + { name = "deprecation" }, + { name = "httpx", extra = ["http2"] }, + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/3e/1b50568e1f5db0bdced4a82c7887e37326585faef7ca43ead86849cb4861/postgrest-1.1.1.tar.gz", hash = "sha256:f3bb3e8c4602775c75c844a31f565f5f3dd584df4d36d683f0b67d01a86be322", size = 15431 } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, + { url = "https://files.pythonhosted.org/packages/a4/71/188a50ea64c17f73ff4df5196ec1553a8f1723421eb2d1069c73bab47d78/postgrest-1.1.1-py3-none-any.whl", hash = "sha256:98a6035ee1d14288484bfe36235942c5fb2d26af6d8120dfe3efbe007859251a", size = 22366 }, ] [[package]] @@ -615,75 +323,9 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, -] - -[[package]] -name = "propcache" -version = "0.3.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a6/16/43264e4a779dd8588c21a70f0709665ee8f611211bdd2c87d952cfa7c776/propcache-0.3.2.tar.gz", hash = "sha256:20d7d62e4e7ef05f221e0db2856b979540686342e7dd9973b815599c7057e168", size = 44139, upload-time = "2025-06-09T22:56:06.081Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a8/42/9ca01b0a6f48e81615dca4765a8f1dd2c057e0540f6116a27dc5ee01dfb6/propcache-0.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8de106b6c84506b31c27168582cd3cb3000a6412c16df14a8628e5871ff83c10", size = 73674, upload-time = "2025-06-09T22:54:30.551Z" }, - { url = "https://files.pythonhosted.org/packages/af/6e/21293133beb550f9c901bbece755d582bfaf2176bee4774000bd4dd41884/propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154", size = 43570, upload-time = "2025-06-09T22:54:32.296Z" }, - { url = "https://files.pythonhosted.org/packages/0c/c8/0393a0a3a2b8760eb3bde3c147f62b20044f0ddac81e9d6ed7318ec0d852/propcache-0.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce26862344bdf836650ed2487c3d724b00fbfec4233a1013f597b78c1cb73615", size = 43094, upload-time = "2025-06-09T22:54:33.929Z" }, - { url = "https://files.pythonhosted.org/packages/37/2c/489afe311a690399d04a3e03b069225670c1d489eb7b044a566511c1c498/propcache-0.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca54bd347a253af2cf4544bbec232ab982f4868de0dd684246b67a51bc6b1db", size = 226958, upload-time = "2025-06-09T22:54:35.186Z" }, - { url = "https://files.pythonhosted.org/packages/9d/ca/63b520d2f3d418c968bf596839ae26cf7f87bead026b6192d4da6a08c467/propcache-0.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55780d5e9a2ddc59711d727226bb1ba83a22dd32f64ee15594b9392b1f544eb1", size = 234894, upload-time = "2025-06-09T22:54:36.708Z" }, - { url = "https://files.pythonhosted.org/packages/11/60/1d0ed6fff455a028d678df30cc28dcee7af77fa2b0e6962ce1df95c9a2a9/propcache-0.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:035e631be25d6975ed87ab23153db6a73426a48db688070d925aa27e996fe93c", size = 233672, upload-time = "2025-06-09T22:54:38.062Z" }, - { url = "https://files.pythonhosted.org/packages/37/7c/54fd5301ef38505ab235d98827207176a5c9b2aa61939b10a460ca53e123/propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67", size = 224395, upload-time = "2025-06-09T22:54:39.634Z" }, - { url = "https://files.pythonhosted.org/packages/ee/1a/89a40e0846f5de05fdc6779883bf46ba980e6df4d2ff8fb02643de126592/propcache-0.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ca3aee1aa955438c4dba34fc20a9f390e4c79967257d830f137bd5a8a32ed3b", size = 212510, upload-time = "2025-06-09T22:54:41.565Z" }, - { url = "https://files.pythonhosted.org/packages/5e/33/ca98368586c9566a6b8d5ef66e30484f8da84c0aac3f2d9aec6d31a11bd5/propcache-0.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4f30862869fa2b68380d677cc1c5fcf1e0f2b9ea0cf665812895c75d0ca3b8", size = 222949, upload-time = "2025-06-09T22:54:43.038Z" }, - { url = "https://files.pythonhosted.org/packages/ba/11/ace870d0aafe443b33b2f0b7efdb872b7c3abd505bfb4890716ad7865e9d/propcache-0.3.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b77ec3c257d7816d9f3700013639db7491a434644c906a2578a11daf13176251", size = 217258, upload-time = "2025-06-09T22:54:44.376Z" }, - { url = "https://files.pythonhosted.org/packages/5b/d2/86fd6f7adffcfc74b42c10a6b7db721d1d9ca1055c45d39a1a8f2a740a21/propcache-0.3.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cab90ac9d3f14b2d5050928483d3d3b8fb6b4018893fc75710e6aa361ecb2474", size = 213036, upload-time = "2025-06-09T22:54:46.243Z" }, - { url = "https://files.pythonhosted.org/packages/07/94/2d7d1e328f45ff34a0a284cf5a2847013701e24c2a53117e7c280a4316b3/propcache-0.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0b504d29f3c47cf6b9e936c1852246c83d450e8e063d50562115a6be6d3a2535", size = 227684, upload-time = "2025-06-09T22:54:47.63Z" }, - { url = "https://files.pythonhosted.org/packages/b7/05/37ae63a0087677e90b1d14710e532ff104d44bc1efa3b3970fff99b891dc/propcache-0.3.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:ce2ac2675a6aa41ddb2a0c9cbff53780a617ac3d43e620f8fd77ba1c84dcfc06", size = 234562, upload-time = "2025-06-09T22:54:48.982Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7c/3f539fcae630408d0bd8bf3208b9a647ccad10976eda62402a80adf8fc34/propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1", size = 222142, upload-time = "2025-06-09T22:54:50.424Z" }, - { url = "https://files.pythonhosted.org/packages/7c/d2/34b9eac8c35f79f8a962546b3e97e9d4b990c420ee66ac8255d5d9611648/propcache-0.3.2-cp312-cp312-win32.whl", hash = "sha256:df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1", size = 37711, upload-time = "2025-06-09T22:54:52.072Z" }, - { url = "https://files.pythonhosted.org/packages/19/61/d582be5d226cf79071681d1b46b848d6cb03d7b70af7063e33a2787eaa03/propcache-0.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c", size = 41479, upload-time = "2025-06-09T22:54:53.234Z" }, - { url = "https://files.pythonhosted.org/packages/dc/d1/8c747fafa558c603c4ca19d8e20b288aa0c7cda74e9402f50f31eb65267e/propcache-0.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ca592ed634a73ca002967458187109265e980422116c0a107cf93d81f95af945", size = 71286, upload-time = "2025-06-09T22:54:54.369Z" }, - { url = "https://files.pythonhosted.org/packages/61/99/d606cb7986b60d89c36de8a85d58764323b3a5ff07770a99d8e993b3fa73/propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252", size = 42425, upload-time = "2025-06-09T22:54:55.642Z" }, - { url = "https://files.pythonhosted.org/packages/8c/96/ef98f91bbb42b79e9bb82bdd348b255eb9d65f14dbbe3b1594644c4073f7/propcache-0.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f08f1cc28bd2eade7a8a3d2954ccc673bb02062e3e7da09bc75d843386b342f", size = 41846, upload-time = "2025-06-09T22:54:57.246Z" }, - { url = "https://files.pythonhosted.org/packages/5b/ad/3f0f9a705fb630d175146cd7b1d2bf5555c9beaed54e94132b21aac098a6/propcache-0.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1a342c834734edb4be5ecb1e9fb48cb64b1e2320fccbd8c54bf8da8f2a84c33", size = 208871, upload-time = "2025-06-09T22:54:58.975Z" }, - { url = "https://files.pythonhosted.org/packages/3a/38/2085cda93d2c8b6ec3e92af2c89489a36a5886b712a34ab25de9fbca7992/propcache-0.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a544caaae1ac73f1fecfae70ded3e93728831affebd017d53449e3ac052ac1e", size = 215720, upload-time = "2025-06-09T22:55:00.471Z" }, - { url = "https://files.pythonhosted.org/packages/61/c1/d72ea2dc83ac7f2c8e182786ab0fc2c7bd123a1ff9b7975bee671866fe5f/propcache-0.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310d11aa44635298397db47a3ebce7db99a4cc4b9bbdfcf6c98a60c8d5261cf1", size = 215203, upload-time = "2025-06-09T22:55:01.834Z" }, - { url = "https://files.pythonhosted.org/packages/af/81/b324c44ae60c56ef12007105f1460d5c304b0626ab0cc6b07c8f2a9aa0b8/propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3", size = 206365, upload-time = "2025-06-09T22:55:03.199Z" }, - { url = "https://files.pythonhosted.org/packages/09/73/88549128bb89e66d2aff242488f62869014ae092db63ccea53c1cc75a81d/propcache-0.3.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cabf5b5902272565e78197edb682017d21cf3b550ba0460ee473753f28d23c1", size = 196016, upload-time = "2025-06-09T22:55:04.518Z" }, - { url = "https://files.pythonhosted.org/packages/b9/3f/3bdd14e737d145114a5eb83cb172903afba7242f67c5877f9909a20d948d/propcache-0.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0a2f2235ac46a7aa25bdeb03a9e7060f6ecbd213b1f9101c43b3090ffb971ef6", size = 205596, upload-time = "2025-06-09T22:55:05.942Z" }, - { url = "https://files.pythonhosted.org/packages/0f/ca/2f4aa819c357d3107c3763d7ef42c03980f9ed5c48c82e01e25945d437c1/propcache-0.3.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:92b69e12e34869a6970fd2f3da91669899994b47c98f5d430b781c26f1d9f387", size = 200977, upload-time = "2025-06-09T22:55:07.792Z" }, - { url = "https://files.pythonhosted.org/packages/cd/4a/e65276c7477533c59085251ae88505caf6831c0e85ff8b2e31ebcbb949b1/propcache-0.3.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:54e02207c79968ebbdffc169591009f4474dde3b4679e16634d34c9363ff56b4", size = 197220, upload-time = "2025-06-09T22:55:09.173Z" }, - { url = "https://files.pythonhosted.org/packages/7c/54/fc7152e517cf5578278b242396ce4d4b36795423988ef39bb8cd5bf274c8/propcache-0.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4adfb44cb588001f68c5466579d3f1157ca07f7504fc91ec87862e2b8e556b88", size = 210642, upload-time = "2025-06-09T22:55:10.62Z" }, - { url = "https://files.pythonhosted.org/packages/b9/80/abeb4a896d2767bf5f1ea7b92eb7be6a5330645bd7fb844049c0e4045d9d/propcache-0.3.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fd3e6019dc1261cd0291ee8919dd91fbab7b169bb76aeef6c716833a3f65d206", size = 212789, upload-time = "2025-06-09T22:55:12.029Z" }, - { url = "https://files.pythonhosted.org/packages/b3/db/ea12a49aa7b2b6d68a5da8293dcf50068d48d088100ac016ad92a6a780e6/propcache-0.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4c181cad81158d71c41a2bce88edce078458e2dd5ffee7eddd6b05da85079f43", size = 205880, upload-time = "2025-06-09T22:55:13.45Z" }, - { url = "https://files.pythonhosted.org/packages/d1/e5/9076a0bbbfb65d1198007059c65639dfd56266cf8e477a9707e4b1999ff4/propcache-0.3.2-cp313-cp313-win32.whl", hash = "sha256:8a08154613f2249519e549de2330cf8e2071c2887309a7b07fb56098f5170a02", size = 37220, upload-time = "2025-06-09T22:55:15.284Z" }, - { url = "https://files.pythonhosted.org/packages/d3/f5/b369e026b09a26cd77aa88d8fffd69141d2ae00a2abaaf5380d2603f4b7f/propcache-0.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e41671f1594fc4ab0a6dec1351864713cb3a279910ae8b58f884a88a0a632c05", size = 40678, upload-time = "2025-06-09T22:55:16.445Z" }, - { url = "https://files.pythonhosted.org/packages/a4/3a/6ece377b55544941a08d03581c7bc400a3c8cd3c2865900a68d5de79e21f/propcache-0.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9a3cf035bbaf035f109987d9d55dc90e4b0e36e04bbbb95af3055ef17194057b", size = 76560, upload-time = "2025-06-09T22:55:17.598Z" }, - { url = "https://files.pythonhosted.org/packages/0c/da/64a2bb16418740fa634b0e9c3d29edff1db07f56d3546ca2d86ddf0305e1/propcache-0.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:156c03d07dc1323d8dacaa221fbe028c5c70d16709cdd63502778e6c3ccca1b0", size = 44676, upload-time = "2025-06-09T22:55:18.922Z" }, - { url = "https://files.pythonhosted.org/packages/36/7b/f025e06ea51cb72c52fb87e9b395cced02786610b60a3ed51da8af017170/propcache-0.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74413c0ba02ba86f55cf60d18daab219f7e531620c15f1e23d95563f505efe7e", size = 44701, upload-time = "2025-06-09T22:55:20.106Z" }, - { url = "https://files.pythonhosted.org/packages/a4/00/faa1b1b7c3b74fc277f8642f32a4c72ba1d7b2de36d7cdfb676db7f4303e/propcache-0.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f066b437bb3fa39c58ff97ab2ca351db465157d68ed0440abecb21715eb24b28", size = 276934, upload-time = "2025-06-09T22:55:21.5Z" }, - { url = "https://files.pythonhosted.org/packages/74/ab/935beb6f1756e0476a4d5938ff44bf0d13a055fed880caf93859b4f1baf4/propcache-0.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1304b085c83067914721e7e9d9917d41ad87696bf70f0bc7dee450e9c71ad0a", size = 278316, upload-time = "2025-06-09T22:55:22.918Z" }, - { url = "https://files.pythonhosted.org/packages/f8/9d/994a5c1ce4389610838d1caec74bdf0e98b306c70314d46dbe4fcf21a3e2/propcache-0.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab50cef01b372763a13333b4e54021bdcb291fc9a8e2ccb9c2df98be51bcde6c", size = 282619, upload-time = "2025-06-09T22:55:24.651Z" }, - { url = "https://files.pythonhosted.org/packages/2b/00/a10afce3d1ed0287cef2e09506d3be9822513f2c1e96457ee369adb9a6cd/propcache-0.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad3b2a085ec259ad2c2842666b2a0a49dea8463579c606426128925af1ed725", size = 265896, upload-time = "2025-06-09T22:55:26.049Z" }, - { url = "https://files.pythonhosted.org/packages/2e/a8/2aa6716ffa566ca57c749edb909ad27884680887d68517e4be41b02299f3/propcache-0.3.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:261fa020c1c14deafd54c76b014956e2f86991af198c51139faf41c4d5e83892", size = 252111, upload-time = "2025-06-09T22:55:27.381Z" }, - { url = "https://files.pythonhosted.org/packages/36/4f/345ca9183b85ac29c8694b0941f7484bf419c7f0fea2d1e386b4f7893eed/propcache-0.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:46d7f8aa79c927e5f987ee3a80205c987717d3659f035c85cf0c3680526bdb44", size = 268334, upload-time = "2025-06-09T22:55:28.747Z" }, - { url = "https://files.pythonhosted.org/packages/3e/ca/fcd54f78b59e3f97b3b9715501e3147f5340167733d27db423aa321e7148/propcache-0.3.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:6d8f3f0eebf73e3c0ff0e7853f68be638b4043c65a70517bb575eff54edd8dbe", size = 255026, upload-time = "2025-06-09T22:55:30.184Z" }, - { url = "https://files.pythonhosted.org/packages/8b/95/8e6a6bbbd78ac89c30c225210a5c687790e532ba4088afb8c0445b77ef37/propcache-0.3.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:03c89c1b14a5452cf15403e291c0ccd7751d5b9736ecb2c5bab977ad6c5bcd81", size = 250724, upload-time = "2025-06-09T22:55:31.646Z" }, - { url = "https://files.pythonhosted.org/packages/ee/b0/0dd03616142baba28e8b2d14ce5df6631b4673850a3d4f9c0f9dd714a404/propcache-0.3.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cc17efde71e12bbaad086d679ce575268d70bc123a5a71ea7ad76f70ba30bba", size = 268868, upload-time = "2025-06-09T22:55:33.209Z" }, - { url = "https://files.pythonhosted.org/packages/c5/98/2c12407a7e4fbacd94ddd32f3b1e3d5231e77c30ef7162b12a60e2dd5ce3/propcache-0.3.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:acdf05d00696bc0447e278bb53cb04ca72354e562cf88ea6f9107df8e7fd9770", size = 271322, upload-time = "2025-06-09T22:55:35.065Z" }, - { url = "https://files.pythonhosted.org/packages/35/91/9cb56efbb428b006bb85db28591e40b7736847b8331d43fe335acf95f6c8/propcache-0.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4445542398bd0b5d32df908031cb1b30d43ac848e20470a878b770ec2dcc6330", size = 265778, upload-time = "2025-06-09T22:55:36.45Z" }, - { url = "https://files.pythonhosted.org/packages/9a/4c/b0fe775a2bdd01e176b14b574be679d84fc83958335790f7c9a686c1f468/propcache-0.3.2-cp313-cp313t-win32.whl", hash = "sha256:f86e5d7cd03afb3a1db8e9f9f6eff15794e79e791350ac48a8c924e6f439f394", size = 41175, upload-time = "2025-06-09T22:55:38.436Z" }, - { url = "https://files.pythonhosted.org/packages/a4/ff/47f08595e3d9b5e149c150f88d9714574f1a7cbd89fe2817158a952674bf/propcache-0.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9704bedf6e7cbe3c65eca4379a9b53ee6a83749f047808cbb5044d40d7d72198", size = 44857, upload-time = "2025-06-09T22:55:39.687Z" }, - { url = "https://files.pythonhosted.org/packages/cc/35/cc0aaecf278bb4575b8555f2b137de5ab821595ddae9da9d3cd1da4072c7/propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f", size = 12663, upload-time = "2025-06-09T22:56:04.484Z" }, -] - -[[package]] -name = "pscript" -version = "0.7.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/59/68/f918702e270eddc5f7c54108f6a2f2afc2d299985820dbb0db9beb77d66d/pscript-0.7.7.tar.gz", hash = "sha256:8632f7a4483f235514aadee110edee82eb6d67336bf68744a7b18d76e50442f8", size = 176138, upload-time = "2022-01-10T10:55:02.559Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/bc/980e2ebd442d2a8f1d22780f73db76f2a1df3bf79b3fb501b054b4b4dd03/pscript-0.7.7-py3-none-any.whl", hash = "sha256:b0fdac0df0393a4d7497153fea6a82e6429f32327c4c0a4817f1cd68adc08083", size = 126689, upload-time = "2022-01-10T10:55:00.793Z" }, + { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707 }, ] [[package]] @@ -696,9 +338,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350 } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782 }, ] [[package]] @@ -708,190 +350,218 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, - { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, - { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, - { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, - { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, - { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, - { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, - { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, - { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, - { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, - { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, - { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, - { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, - { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, - { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, - { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, - { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, - { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, - { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, - { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, - { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, - { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, - { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, - { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, - { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, - { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, - { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, - { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, - { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, -] - -[[package]] -name = "pygments" -version = "2.19.2" +sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000 }, + { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996 }, + { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957 }, + { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199 }, + { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296 }, + { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109 }, + { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028 }, + { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044 }, + { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881 }, + { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034 }, + { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187 }, + { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628 }, + { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866 }, + { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894 }, + { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688 }, + { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808 }, + { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580 }, + { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859 }, + { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810 }, + { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498 }, + { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611 }, + { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924 }, + { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196 }, + { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389 }, + { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223 }, + { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473 }, + { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269 }, + { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921 }, + { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162 }, + { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560 }, + { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777 }, +] + +[[package]] +name = "pyjwt" +version = "2.10.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997 }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" 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" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } 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" }, + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, ] [[package]] -name = "python-dotenv" -version = "1.1.1" +name = "pyyaml" +version = "6.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, ] [[package]] -name = "python-engineio" -version = "4.12.2" +name = "realtime" +version = "2.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "simple-websocket" }, + { name = "pydantic" }, + { name = "typing-extensions" }, + { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ba/0b/67295279b66835f9fa7a491650efcd78b20321c127036eef62c11a31e028/python_engineio-4.12.2.tar.gz", hash = "sha256:e7e712ffe1be1f6a05ee5f951e72d434854a32fcfc7f6e4d9d3cae24ec70defa", size = 91677, upload-time = "2025-06-04T19:22:18.789Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d3/ca/e408fbdb6b344bf529c7e8bf020372d21114fe538392c72089462edd26e5/realtime-2.7.0.tar.gz", hash = "sha256:6b9434eeba8d756c8faf94fc0a32081d09f250d14d82b90341170602adbb019f", size = 18860 } wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/fa/df59acedf7bbb937f69174d00f921a7b93aa5a5f5c17d05296c814fff6fc/python_engineio-4.12.2-py3-none-any.whl", hash = "sha256:8218ab66950e179dfec4b4bbb30aecf3f5d86f5e58e6fc1aa7fde2c698b2804f", size = 59536, upload-time = "2025-06-04T19:22:16.916Z" }, + { url = "https://files.pythonhosted.org/packages/d2/07/a5c7aef12f9a3497f5ad77157a37915645861e8b23b89b2ad4b0f11b48ad/realtime-2.7.0-py3-none-any.whl", hash = "sha256:d55a278803529a69d61c7174f16563a9cfa5bacc1664f656959694481903d99c", size = 22409 }, ] [[package]] -name = "python-multipart" -version = "0.0.20" +name = "ruff" +version = "0.12.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158, upload-time = "2024-12-16T19:45:46.972Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/da/5bd7565be729e86e1442dad2c9a364ceeff82227c2dece7c29697a9795eb/ruff-0.12.8.tar.gz", hash = "sha256:4cb3a45525176e1009b2b64126acf5f9444ea59066262791febf55e40493a033", size = 5242373 } wheels = [ - { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload-time = "2024-12-16T19:45:44.423Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1e/c843bfa8ad1114fab3eb2b78235dda76acd66384c663a4e0415ecc13aa1e/ruff-0.12.8-py3-none-linux_armv6l.whl", hash = "sha256:63cb5a5e933fc913e5823a0dfdc3c99add73f52d139d6cd5cc8639d0e0465513", size = 11675315 }, + { url = "https://files.pythonhosted.org/packages/24/ee/af6e5c2a8ca3a81676d5480a1025494fd104b8896266502bb4de2a0e8388/ruff-0.12.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a9bbe28f9f551accf84a24c366c1aa8774d6748438b47174f8e8565ab9dedbc", size = 12456653 }, + { url = "https://files.pythonhosted.org/packages/99/9d/e91f84dfe3866fa648c10512904991ecc326fd0b66578b324ee6ecb8f725/ruff-0.12.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2fae54e752a3150f7ee0e09bce2e133caf10ce9d971510a9b925392dc98d2fec", size = 11659690 }, + { url = "https://files.pythonhosted.org/packages/fe/ac/a363d25ec53040408ebdd4efcee929d48547665858ede0505d1d8041b2e5/ruff-0.12.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0acbcf01206df963d9331b5838fb31f3b44fa979ee7fa368b9b9057d89f4a53", size = 11896923 }, + { url = "https://files.pythonhosted.org/packages/58/9f/ea356cd87c395f6ade9bb81365bd909ff60860975ca1bc39f0e59de3da37/ruff-0.12.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae3e7504666ad4c62f9ac8eedb52a93f9ebdeb34742b8b71cd3cccd24912719f", size = 11477612 }, + { url = "https://files.pythonhosted.org/packages/1a/46/92e8fa3c9dcfd49175225c09053916cb97bb7204f9f899c2f2baca69e450/ruff-0.12.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb82efb5d35d07497813a1c5647867390a7d83304562607f3579602fa3d7d46f", size = 13182745 }, + { url = "https://files.pythonhosted.org/packages/5e/c4/f2176a310f26e6160deaf661ef60db6c3bb62b7a35e57ae28f27a09a7d63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dbea798fc0065ad0b84a2947b0aff4233f0cb30f226f00a2c5850ca4393de609", size = 14206885 }, + { url = "https://files.pythonhosted.org/packages/87/9d/98e162f3eeeb6689acbedbae5050b4b3220754554526c50c292b611d3a63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49ebcaccc2bdad86fd51b7864e3d808aad404aab8df33d469b6e65584656263a", size = 13639381 }, + { url = "https://files.pythonhosted.org/packages/81/4e/1b7478b072fcde5161b48f64774d6edd59d6d198e4ba8918d9f4702b8043/ruff-0.12.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ac9c570634b98c71c88cb17badd90f13fc076a472ba6ef1d113d8ed3df109fb", size = 12613271 }, + { url = "https://files.pythonhosted.org/packages/e8/67/0c3c9179a3ad19791ef1b8f7138aa27d4578c78700551c60d9260b2c660d/ruff-0.12.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:560e0cd641e45591a3e42cb50ef61ce07162b9c233786663fdce2d8557d99818", size = 12847783 }, + { url = "https://files.pythonhosted.org/packages/4e/2a/0b6ac3dd045acf8aa229b12c9c17bb35508191b71a14904baf99573a21bd/ruff-0.12.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:71c83121512e7743fba5a8848c261dcc454cafb3ef2934a43f1b7a4eb5a447ea", size = 11702672 }, + { url = "https://files.pythonhosted.org/packages/9d/ee/f9fdc9f341b0430110de8b39a6ee5fa68c5706dc7c0aa940817947d6937e/ruff-0.12.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:de4429ef2ba091ecddedd300f4c3f24bca875d3d8b23340728c3cb0da81072c3", size = 11440626 }, + { url = "https://files.pythonhosted.org/packages/89/fb/b3aa2d482d05f44e4d197d1de5e3863feb13067b22c571b9561085c999dc/ruff-0.12.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a2cab5f60d5b65b50fba39a8950c8746df1627d54ba1197f970763917184b161", size = 12462162 }, + { url = "https://files.pythonhosted.org/packages/18/9f/5c5d93e1d00d854d5013c96e1a92c33b703a0332707a7cdbd0a4880a84fb/ruff-0.12.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:45c32487e14f60b88aad6be9fd5da5093dbefb0e3e1224131cb1d441d7cb7d46", size = 12913212 }, + { url = "https://files.pythonhosted.org/packages/71/13/ab9120add1c0e4604c71bfc2e4ef7d63bebece0cfe617013da289539cef8/ruff-0.12.8-py3-none-win32.whl", hash = "sha256:daf3475060a617fd5bc80638aeaf2f5937f10af3ec44464e280a9d2218e720d3", size = 11694382 }, + { url = "https://files.pythonhosted.org/packages/f6/dc/a2873b7c5001c62f46266685863bee2888caf469d1edac84bf3242074be2/ruff-0.12.8-py3-none-win_amd64.whl", hash = "sha256:7209531f1a1fcfbe8e46bcd7ab30e2f43604d8ba1c49029bb420b103d0b5f76e", size = 12740482 }, + { url = "https://files.pythonhosted.org/packages/cb/5c/799a1efb8b5abab56e8a9f2a0b72d12bd64bb55815e9476c7d0a2887d2f7/ruff-0.12.8-py3-none-win_arm64.whl", hash = "sha256:c90e1a334683ce41b0e7a04f41790c429bf5073b62c1ae701c9dc5b3d14f0749", size = 11884718 }, ] [[package]] -name = "python-socketio" -version = "5.13.0" +name = "six" +version = "1.17.0" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "bidict" }, - { name = "python-engineio" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/21/1a/396d50ccf06ee539fa758ce5623b59a9cb27637fc4b2dc07ed08bf495e77/python_socketio-5.13.0.tar.gz", hash = "sha256:ac4e19a0302ae812e23b712ec8b6427ca0521f7c582d6abb096e36e24a263029", size = 121125, upload-time = "2025-04-12T15:46:59.933Z" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/32/b4fb8585d1be0f68bde7e110dffbcf354915f77ad8c778563f0ad9655c02/python_socketio-5.13.0-py3-none-any.whl", hash = "sha256:51f68d6499f2df8524668c24bcec13ba1414117cfb3a90115c559b601ab10caf", size = 77800, upload-time = "2025-04-12T15:46:58.412Z" }, -] - -[package.optional-dependencies] -asyncio-client = [ - { name = "aiohttp" }, + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, ] [[package]] -name = "pyyaml" -version = "6.0.2" +name = "sniffio" +version = "1.3.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } wheels = [ - { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, - { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, - { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, - { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, - { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, - { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, - { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, - { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, - { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, - { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, - { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, - { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, - { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, - { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, - { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, - { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, - { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, - { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, ] [[package]] -name = "ruff" -version = "0.12.8" +name = "starlette" +version = "0.47.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4b/da/5bd7565be729e86e1442dad2c9a364ceeff82227c2dece7c29697a9795eb/ruff-0.12.8.tar.gz", hash = "sha256:4cb3a45525176e1009b2b64126acf5f9444ea59066262791febf55e40493a033", size = 5242373, upload-time = "2025-08-07T19:05:47.268Z" } +dependencies = [ + { name = "anyio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/57/d062573f391d062710d4088fa1369428c38d51460ab6fedff920efef932e/starlette-0.47.2.tar.gz", hash = "sha256:6ae9aa5db235e4846decc1e7b79c4f346adf41e9777aebeb49dfd09bbd7023d8", size = 2583948 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c9/1e/c843bfa8ad1114fab3eb2b78235dda76acd66384c663a4e0415ecc13aa1e/ruff-0.12.8-py3-none-linux_armv6l.whl", hash = "sha256:63cb5a5e933fc913e5823a0dfdc3c99add73f52d139d6cd5cc8639d0e0465513", size = 11675315, upload-time = "2025-08-07T19:05:06.15Z" }, - { url = "https://files.pythonhosted.org/packages/24/ee/af6e5c2a8ca3a81676d5480a1025494fd104b8896266502bb4de2a0e8388/ruff-0.12.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a9bbe28f9f551accf84a24c366c1aa8774d6748438b47174f8e8565ab9dedbc", size = 12456653, upload-time = "2025-08-07T19:05:09.759Z" }, - { url = "https://files.pythonhosted.org/packages/99/9d/e91f84dfe3866fa648c10512904991ecc326fd0b66578b324ee6ecb8f725/ruff-0.12.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2fae54e752a3150f7ee0e09bce2e133caf10ce9d971510a9b925392dc98d2fec", size = 11659690, upload-time = "2025-08-07T19:05:12.551Z" }, - { url = "https://files.pythonhosted.org/packages/fe/ac/a363d25ec53040408ebdd4efcee929d48547665858ede0505d1d8041b2e5/ruff-0.12.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0acbcf01206df963d9331b5838fb31f3b44fa979ee7fa368b9b9057d89f4a53", size = 11896923, upload-time = "2025-08-07T19:05:14.821Z" }, - { url = "https://files.pythonhosted.org/packages/58/9f/ea356cd87c395f6ade9bb81365bd909ff60860975ca1bc39f0e59de3da37/ruff-0.12.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae3e7504666ad4c62f9ac8eedb52a93f9ebdeb34742b8b71cd3cccd24912719f", size = 11477612, upload-time = "2025-08-07T19:05:16.712Z" }, - { url = "https://files.pythonhosted.org/packages/1a/46/92e8fa3c9dcfd49175225c09053916cb97bb7204f9f899c2f2baca69e450/ruff-0.12.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb82efb5d35d07497813a1c5647867390a7d83304562607f3579602fa3d7d46f", size = 13182745, upload-time = "2025-08-07T19:05:18.709Z" }, - { url = "https://files.pythonhosted.org/packages/5e/c4/f2176a310f26e6160deaf661ef60db6c3bb62b7a35e57ae28f27a09a7d63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dbea798fc0065ad0b84a2947b0aff4233f0cb30f226f00a2c5850ca4393de609", size = 14206885, upload-time = "2025-08-07T19:05:21.025Z" }, - { url = "https://files.pythonhosted.org/packages/87/9d/98e162f3eeeb6689acbedbae5050b4b3220754554526c50c292b611d3a63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49ebcaccc2bdad86fd51b7864e3d808aad404aab8df33d469b6e65584656263a", size = 13639381, upload-time = "2025-08-07T19:05:23.423Z" }, - { url = "https://files.pythonhosted.org/packages/81/4e/1b7478b072fcde5161b48f64774d6edd59d6d198e4ba8918d9f4702b8043/ruff-0.12.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ac9c570634b98c71c88cb17badd90f13fc076a472ba6ef1d113d8ed3df109fb", size = 12613271, upload-time = "2025-08-07T19:05:25.507Z" }, - { url = "https://files.pythonhosted.org/packages/e8/67/0c3c9179a3ad19791ef1b8f7138aa27d4578c78700551c60d9260b2c660d/ruff-0.12.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:560e0cd641e45591a3e42cb50ef61ce07162b9c233786663fdce2d8557d99818", size = 12847783, upload-time = "2025-08-07T19:05:28.14Z" }, - { url = "https://files.pythonhosted.org/packages/4e/2a/0b6ac3dd045acf8aa229b12c9c17bb35508191b71a14904baf99573a21bd/ruff-0.12.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:71c83121512e7743fba5a8848c261dcc454cafb3ef2934a43f1b7a4eb5a447ea", size = 11702672, upload-time = "2025-08-07T19:05:30.413Z" }, - { url = "https://files.pythonhosted.org/packages/9d/ee/f9fdc9f341b0430110de8b39a6ee5fa68c5706dc7c0aa940817947d6937e/ruff-0.12.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:de4429ef2ba091ecddedd300f4c3f24bca875d3d8b23340728c3cb0da81072c3", size = 11440626, upload-time = "2025-08-07T19:05:32.492Z" }, - { url = "https://files.pythonhosted.org/packages/89/fb/b3aa2d482d05f44e4d197d1de5e3863feb13067b22c571b9561085c999dc/ruff-0.12.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a2cab5f60d5b65b50fba39a8950c8746df1627d54ba1197f970763917184b161", size = 12462162, upload-time = "2025-08-07T19:05:34.449Z" }, - { url = "https://files.pythonhosted.org/packages/18/9f/5c5d93e1d00d854d5013c96e1a92c33b703a0332707a7cdbd0a4880a84fb/ruff-0.12.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:45c32487e14f60b88aad6be9fd5da5093dbefb0e3e1224131cb1d441d7cb7d46", size = 12913212, upload-time = "2025-08-07T19:05:36.541Z" }, - { url = "https://files.pythonhosted.org/packages/71/13/ab9120add1c0e4604c71bfc2e4ef7d63bebece0cfe617013da289539cef8/ruff-0.12.8-py3-none-win32.whl", hash = "sha256:daf3475060a617fd5bc80638aeaf2f5937f10af3ec44464e280a9d2218e720d3", size = 11694382, upload-time = "2025-08-07T19:05:38.468Z" }, - { url = "https://files.pythonhosted.org/packages/f6/dc/a2873b7c5001c62f46266685863bee2888caf469d1edac84bf3242074be2/ruff-0.12.8-py3-none-win_amd64.whl", hash = "sha256:7209531f1a1fcfbe8e46bcd7ab30e2f43604d8ba1c49029bb420b103d0b5f76e", size = 12740482, upload-time = "2025-08-07T19:05:40.391Z" }, - { url = "https://files.pythonhosted.org/packages/cb/5c/799a1efb8b5abab56e8a9f2a0b72d12bd64bb55815e9476c7d0a2887d2f7/ruff-0.12.8-py3-none-win_arm64.whl", hash = "sha256:c90e1a334683ce41b0e7a04f41790c429bf5073b62c1ae701c9dc5b3d14f0749", size = 11884718, upload-time = "2025-08-07T19:05:42.866Z" }, + { url = "https://files.pythonhosted.org/packages/f7/1f/b876b1f83aef204198a42dc101613fefccb32258e5428b5f9259677864b4/starlette-0.47.2-py3-none-any.whl", hash = "sha256:c5847e96134e5c5371ee9fac6fdf1a67336d5815e09eb2a01fdb57a351ef915b", size = 72984 }, ] [[package]] -name = "simple-websocket" -version = "1.1.0" +name = "storage3" +version = "0.12.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "wsproto" }, + { name = "deprecation" }, + { name = "httpx", extra = ["http2"] }, + { name = "python-dateutil" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b0/d4/bfa032f961103eba93de583b161f0e6a5b63cebb8f2c7d0c6e6efe1e3d2e/simple_websocket-1.1.0.tar.gz", hash = "sha256:7939234e7aa067c534abdab3a9ed933ec9ce4691b0713c78acb195560aa52ae4", size = 17300, upload-time = "2024-10-10T22:39:31.412Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/e2/280fe75f65e7a3ca680b7843acfc572a63aa41230e3d3c54c66568809c85/storage3-0.12.1.tar.gz", hash = "sha256:32ea8f5eb2f7185c2114a4f6ae66d577722e32503f0a30b56e7ed5c7f13e6b48", size = 10198 } wheels = [ - { url = "https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl", hash = "sha256:4af6069630a38ed6c561010f0e11a5bc0d4ca569b36306eb257cd9a192497c8c", size = 13842, upload-time = "2024-10-10T22:39:29.645Z" }, + { url = "https://files.pythonhosted.org/packages/7f/3b/c5f8709fc5349928e591fee47592eeff78d29a7d75b097f96a4e01de028d/storage3-0.12.1-py3-none-any.whl", hash = "sha256:9da77fd4f406b019fdcba201e9916aefbf615ef87f551253ce427d8136459a34", size = 18420 }, ] [[package]] -name = "sniffio" -version = "1.3.1" +name = "strenum" +version = "0.4.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +sdist = { url = "https://files.pythonhosted.org/packages/85/ad/430fb60d90e1d112a62ff57bdd1f286ec73a2a0331272febfddd21f330e1/StrEnum-0.4.15.tar.gz", hash = "sha256:878fb5ab705442070e4dd1929bb5e2249511c0bcf2b0eeacf3bcd80875c82eff", size = 23384 } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, + { url = "https://files.pythonhosted.org/packages/81/69/297302c5f5f59c862faa31e6cb9a4cd74721cd1e052b38e464c5b402df8b/StrEnum-0.4.15-py3-none-any.whl", hash = "sha256:a30cda4af7cc6b5bf52c8055bc4bf4b2b6b14a93b574626da33df53cf7740659", size = 8851 }, ] [[package]] -name = "starlette" -version = "0.47.2" +name = "supabase" +version = "2.18.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, + { name = "gotrue" }, + { name = "httpx" }, + { name = "postgrest" }, + { name = "realtime" }, + { name = "storage3" }, + { name = "supafunc" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/e1/511411018596cfecfac99d9091630606e9a03cb07bd5dec2f15621d38b84/supabase-2.18.0.tar.gz", hash = "sha256:b1e98f0faff6e041e5347393a82524d9d5c2ddb87cb844e7557f967f23d8bc70", size = 11521 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f7/78/67238701e0253fdfef222a39df32f9883de2a8b046fa68d1ae47f3e52979/supabase-2.18.0-py3-none-any.whl", hash = "sha256:73774e6edd5ffd02653a99e2e98f92191c4ffb5089dcff3ed93f5d7c18ddaeb3", size = 18677 }, +] + +[[package]] +name = "supafunc" +version = "0.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "httpx", extra = ["http2"] }, + { name = "strenum" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/57/d062573f391d062710d4088fa1369428c38d51460ab6fedff920efef932e/starlette-0.47.2.tar.gz", hash = "sha256:6ae9aa5db235e4846decc1e7b79c4f346adf41e9777aebeb49dfd09bbd7023d8", size = 2583948, upload-time = "2025-07-20T17:31:58.522Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/4b/16f94bcae8a49f5e09544a4fb0e6ad1c2288038036cefdeedb72fcffd92c/supafunc-0.10.1.tar.gz", hash = "sha256:a5b33c8baecb6b5297d25da29a2503e2ec67ee6986f3d44c137e651b8a59a17d", size = 5036 } wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/1f/b876b1f83aef204198a42dc101613fefccb32258e5428b5f9259677864b4/starlette-0.47.2-py3-none-any.whl", hash = "sha256:c5847e96134e5c5371ee9fac6fdf1a67336d5815e09eb2a01fdb57a351ef915b", size = 72984, upload-time = "2025-07-20T17:31:56.738Z" }, + { url = "https://files.pythonhosted.org/packages/76/4a/9cbea12d86a741d4e73a6e278c2b1d6479fb03d1002efb00e8e71aea76db/supafunc-0.10.1-py3-none-any.whl", hash = "sha256:26df9bd25ff2ef56cb5bfb8962de98f43331f7f8ff69572bac3ed9c3a9672040", size = 8028 }, ] [[package]] name = "typing-extensions" version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906 }, ] [[package]] @@ -901,9 +571,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726 } wheels = [ - { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552 }, ] [[package]] @@ -914,52 +584,9 @@ dependencies = [ { name = "click" }, { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473 } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, -] - -[package.optional-dependencies] -standard = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "httptools" }, - { name = "python-dotenv" }, - { name = "pyyaml" }, - { name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, - { name = "watchfiles" }, - { name = "websockets" }, -] - -[[package]] -name = "uvloop" -version = "0.21.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741, upload-time = "2024-10-14T23:38:35.489Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", size = 1471284, upload-time = "2024-10-14T23:37:47.833Z" }, - { url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2", size = 821349, upload-time = "2024-10-14T23:37:50.149Z" }, - { url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", size = 4580089, upload-time = "2024-10-14T23:37:51.703Z" }, - { url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", size = 4693770, upload-time = "2024-10-14T23:37:54.122Z" }, - { url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", size = 4451321, upload-time = "2024-10-14T23:37:55.766Z" }, - { url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022, upload-time = "2024-10-14T23:37:58.195Z" }, - { url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123, upload-time = "2024-10-14T23:38:00.688Z" }, - { url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325, upload-time = "2024-10-14T23:38:02.309Z" }, - { url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806, upload-time = "2024-10-14T23:38:04.711Z" }, - { url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", size = 4701068, upload-time = "2024-10-14T23:38:06.385Z" }, - { url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", size = 4454428, upload-time = "2024-10-14T23:38:08.416Z" }, - { url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", size = 4660018, upload-time = "2024-10-14T23:38:10.888Z" }, -] - -[[package]] -name = "vbuild" -version = "0.8.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pscript" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/22/be/f0c6204a36440bbcc086bfa25964d009b7391c5a3c74d6e73188efd47adb/vbuild-0.8.2.tar.gz", hash = "sha256:270cd9078349d907dfae6c0e6364a5a5e74cb86183bb5093613f12a18b435fa9", size = 8937, upload-time = "2023-08-03T09:26:36.196Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/3d/7b22abbdb059d551507275a2815bc2b1974e3b9f6a13781c1eac9e858965/vbuild-0.8.2-py2.py3-none-any.whl", hash = "sha256:d76bcc976a1c53b6a5776ac947606f9e7786c25df33a587ebe33ed09dd8a1076", size = 9371, upload-time = "2023-08-03T09:26:35.023Z" }, + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406 }, ] [[package]] @@ -971,182 +598,38 @@ dependencies = [ { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/60/4f20960df6c7b363a18a55ab034c8f2bcd5d9770d1f94f9370ec104c1855/virtualenv-20.33.1.tar.gz", hash = "sha256:1b44478d9e261b3fb8baa5e74a0ca3bc0e05f21aa36167bf9cbf850e542765b8", size = 6082160, upload-time = "2025-08-05T16:10:55.605Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8b/60/4f20960df6c7b363a18a55ab034c8f2bcd5d9770d1f94f9370ec104c1855/virtualenv-20.33.1.tar.gz", hash = "sha256:1b44478d9e261b3fb8baa5e74a0ca3bc0e05f21aa36167bf9cbf850e542765b8", size = 6082160 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/ff/ded57ac5ff40a09e6e198550bab075d780941e0b0f83cbeabd087c59383a/virtualenv-20.33.1-py3-none-any.whl", hash = "sha256:07c19bc66c11acab6a5958b815cbcee30891cd1c2ccf53785a28651a0d8d8a67", size = 6060362, upload-time = "2025-08-05T16:10:52.81Z" }, -] - -[[package]] -name = "watchfiles" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/2a/9a/d451fcc97d029f5812e898fd30a53fd8c15c7bbd058fd75cfc6beb9bd761/watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575", size = 94406, upload-time = "2025-06-15T19:06:59.42Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f6/b8/858957045a38a4079203a33aaa7d23ea9269ca7761c8a074af3524fbb240/watchfiles-1.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9dc001c3e10de4725c749d4c2f2bdc6ae24de5a88a339c4bce32300a31ede179", size = 402339, upload-time = "2025-06-15T19:05:24.516Z" }, - { url = "https://files.pythonhosted.org/packages/80/28/98b222cca751ba68e88521fabd79a4fab64005fc5976ea49b53fa205d1fa/watchfiles-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9ba68ec283153dead62cbe81872d28e053745f12335d037de9cbd14bd1877f5", size = 394409, upload-time = "2025-06-15T19:05:25.469Z" }, - { url = "https://files.pythonhosted.org/packages/86/50/dee79968566c03190677c26f7f47960aff738d32087087bdf63a5473e7df/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130fc497b8ee68dce163e4254d9b0356411d1490e868bd8790028bc46c5cc297", size = 450939, upload-time = "2025-06-15T19:05:26.494Z" }, - { url = "https://files.pythonhosted.org/packages/40/45/a7b56fb129700f3cfe2594a01aa38d033b92a33dddce86c8dfdfc1247b72/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50a51a90610d0845a5931a780d8e51d7bd7f309ebc25132ba975aca016b576a0", size = 457270, upload-time = "2025-06-15T19:05:27.466Z" }, - { url = "https://files.pythonhosted.org/packages/b5/c8/fa5ef9476b1d02dc6b5e258f515fcaaecf559037edf8b6feffcbc097c4b8/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc44678a72ac0910bac46fa6a0de6af9ba1355669b3dfaf1ce5f05ca7a74364e", size = 483370, upload-time = "2025-06-15T19:05:28.548Z" }, - { url = "https://files.pythonhosted.org/packages/98/68/42cfcdd6533ec94f0a7aab83f759ec11280f70b11bfba0b0f885e298f9bd/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a543492513a93b001975ae283a51f4b67973662a375a403ae82f420d2c7205ee", size = 598654, upload-time = "2025-06-15T19:05:29.997Z" }, - { url = "https://files.pythonhosted.org/packages/d3/74/b2a1544224118cc28df7e59008a929e711f9c68ce7d554e171b2dc531352/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ac164e20d17cc285f2b94dc31c384bc3aa3dd5e7490473b3db043dd70fbccfd", size = 478667, upload-time = "2025-06-15T19:05:31.172Z" }, - { url = "https://files.pythonhosted.org/packages/8c/77/e3362fe308358dc9f8588102481e599c83e1b91c2ae843780a7ded939a35/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7590d5a455321e53857892ab8879dce62d1f4b04748769f5adf2e707afb9d4f", size = 452213, upload-time = "2025-06-15T19:05:32.299Z" }, - { url = "https://files.pythonhosted.org/packages/6e/17/c8f1a36540c9a1558d4faf08e909399e8133599fa359bf52ec8fcee5be6f/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:37d3d3f7defb13f62ece99e9be912afe9dd8a0077b7c45ee5a57c74811d581a4", size = 626718, upload-time = "2025-06-15T19:05:33.415Z" }, - { url = "https://files.pythonhosted.org/packages/26/45/fb599be38b4bd38032643783d7496a26a6f9ae05dea1a42e58229a20ac13/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7080c4bb3efd70a07b1cc2df99a7aa51d98685be56be6038c3169199d0a1c69f", size = 623098, upload-time = "2025-06-15T19:05:34.534Z" }, - { url = "https://files.pythonhosted.org/packages/a1/e7/fdf40e038475498e160cd167333c946e45d8563ae4dd65caf757e9ffe6b4/watchfiles-1.1.0-cp312-cp312-win32.whl", hash = "sha256:cbcf8630ef4afb05dc30107bfa17f16c0896bb30ee48fc24bf64c1f970f3b1fd", size = 279209, upload-time = "2025-06-15T19:05:35.577Z" }, - { url = "https://files.pythonhosted.org/packages/3f/d3/3ae9d5124ec75143bdf088d436cba39812122edc47709cd2caafeac3266f/watchfiles-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:cbd949bdd87567b0ad183d7676feb98136cde5bb9025403794a4c0db28ed3a47", size = 292786, upload-time = "2025-06-15T19:05:36.559Z" }, - { url = "https://files.pythonhosted.org/packages/26/2f/7dd4fc8b5f2b34b545e19629b4a018bfb1de23b3a496766a2c1165ca890d/watchfiles-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:0a7d40b77f07be87c6faa93d0951a0fcd8cbca1ddff60a1b65d741bac6f3a9f6", size = 284343, upload-time = "2025-06-15T19:05:37.5Z" }, - { url = "https://files.pythonhosted.org/packages/d3/42/fae874df96595556a9089ade83be34a2e04f0f11eb53a8dbf8a8a5e562b4/watchfiles-1.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5007f860c7f1f8df471e4e04aaa8c43673429047d63205d1630880f7637bca30", size = 402004, upload-time = "2025-06-15T19:05:38.499Z" }, - { url = "https://files.pythonhosted.org/packages/fa/55/a77e533e59c3003d9803c09c44c3651224067cbe7fb5d574ddbaa31e11ca/watchfiles-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:20ecc8abbd957046f1fe9562757903f5eaf57c3bce70929fda6c7711bb58074a", size = 393671, upload-time = "2025-06-15T19:05:39.52Z" }, - { url = "https://files.pythonhosted.org/packages/05/68/b0afb3f79c8e832e6571022611adbdc36e35a44e14f129ba09709aa4bb7a/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2f0498b7d2a3c072766dba3274fe22a183dbea1f99d188f1c6c72209a1063dc", size = 449772, upload-time = "2025-06-15T19:05:40.897Z" }, - { url = "https://files.pythonhosted.org/packages/ff/05/46dd1f6879bc40e1e74c6c39a1b9ab9e790bf1f5a2fe6c08b463d9a807f4/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:239736577e848678e13b201bba14e89718f5c2133dfd6b1f7846fa1b58a8532b", size = 456789, upload-time = "2025-06-15T19:05:42.045Z" }, - { url = "https://files.pythonhosted.org/packages/8b/ca/0eeb2c06227ca7f12e50a47a3679df0cd1ba487ea19cf844a905920f8e95/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff4b8d89f444f7e49136dc695599a591ff769300734446c0a86cba2eb2f9895", size = 482551, upload-time = "2025-06-15T19:05:43.781Z" }, - { url = "https://files.pythonhosted.org/packages/31/47/2cecbd8694095647406645f822781008cc524320466ea393f55fe70eed3b/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12b0a02a91762c08f7264e2e79542f76870c3040bbc847fb67410ab81474932a", size = 597420, upload-time = "2025-06-15T19:05:45.244Z" }, - { url = "https://files.pythonhosted.org/packages/d9/7e/82abc4240e0806846548559d70f0b1a6dfdca75c1b4f9fa62b504ae9b083/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29e7bc2eee15cbb339c68445959108803dc14ee0c7b4eea556400131a8de462b", size = 477950, upload-time = "2025-06-15T19:05:46.332Z" }, - { url = "https://files.pythonhosted.org/packages/25/0d/4d564798a49bf5482a4fa9416dea6b6c0733a3b5700cb8a5a503c4b15853/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9481174d3ed982e269c090f780122fb59cee6c3796f74efe74e70f7780ed94c", size = 451706, upload-time = "2025-06-15T19:05:47.459Z" }, - { url = "https://files.pythonhosted.org/packages/81/b5/5516cf46b033192d544102ea07c65b6f770f10ed1d0a6d388f5d3874f6e4/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:80f811146831c8c86ab17b640801c25dc0a88c630e855e2bef3568f30434d52b", size = 625814, upload-time = "2025-06-15T19:05:48.654Z" }, - { url = "https://files.pythonhosted.org/packages/0c/dd/7c1331f902f30669ac3e754680b6edb9a0dd06dea5438e61128111fadd2c/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:60022527e71d1d1fda67a33150ee42869042bce3d0fcc9cc49be009a9cded3fb", size = 622820, upload-time = "2025-06-15T19:05:50.088Z" }, - { url = "https://files.pythonhosted.org/packages/1b/14/36d7a8e27cd128d7b1009e7715a7c02f6c131be9d4ce1e5c3b73d0e342d8/watchfiles-1.1.0-cp313-cp313-win32.whl", hash = "sha256:32d6d4e583593cb8576e129879ea0991660b935177c0f93c6681359b3654bfa9", size = 279194, upload-time = "2025-06-15T19:05:51.186Z" }, - { url = "https://files.pythonhosted.org/packages/25/41/2dd88054b849aa546dbeef5696019c58f8e0774f4d1c42123273304cdb2e/watchfiles-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:f21af781a4a6fbad54f03c598ab620e3a77032c5878f3d780448421a6e1818c7", size = 292349, upload-time = "2025-06-15T19:05:52.201Z" }, - { url = "https://files.pythonhosted.org/packages/c8/cf/421d659de88285eb13941cf11a81f875c176f76a6d99342599be88e08d03/watchfiles-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:5366164391873ed76bfdf618818c82084c9db7fac82b64a20c44d335eec9ced5", size = 283836, upload-time = "2025-06-15T19:05:53.265Z" }, - { url = "https://files.pythonhosted.org/packages/45/10/6faf6858d527e3599cc50ec9fcae73590fbddc1420bd4fdccfebffeedbc6/watchfiles-1.1.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:17ab167cca6339c2b830b744eaf10803d2a5b6683be4d79d8475d88b4a8a4be1", size = 400343, upload-time = "2025-06-15T19:05:54.252Z" }, - { url = "https://files.pythonhosted.org/packages/03/20/5cb7d3966f5e8c718006d0e97dfe379a82f16fecd3caa7810f634412047a/watchfiles-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:328dbc9bff7205c215a7807da7c18dce37da7da718e798356212d22696404339", size = 392916, upload-time = "2025-06-15T19:05:55.264Z" }, - { url = "https://files.pythonhosted.org/packages/8c/07/d8f1176328fa9e9581b6f120b017e286d2a2d22ae3f554efd9515c8e1b49/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7208ab6e009c627b7557ce55c465c98967e8caa8b11833531fdf95799372633", size = 449582, upload-time = "2025-06-15T19:05:56.317Z" }, - { url = "https://files.pythonhosted.org/packages/66/e8/80a14a453cf6038e81d072a86c05276692a1826471fef91df7537dba8b46/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8f6f72974a19efead54195bc9bed4d850fc047bb7aa971268fd9a8387c89011", size = 456752, upload-time = "2025-06-15T19:05:57.359Z" }, - { url = "https://files.pythonhosted.org/packages/5a/25/0853b3fe0e3c2f5af9ea60eb2e781eade939760239a72c2d38fc4cc335f6/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d181ef50923c29cf0450c3cd47e2f0557b62218c50b2ab8ce2ecaa02bd97e670", size = 481436, upload-time = "2025-06-15T19:05:58.447Z" }, - { url = "https://files.pythonhosted.org/packages/fe/9e/4af0056c258b861fbb29dcb36258de1e2b857be4a9509e6298abcf31e5c9/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adb4167043d3a78280d5d05ce0ba22055c266cf8655ce942f2fb881262ff3cdf", size = 596016, upload-time = "2025-06-15T19:05:59.59Z" }, - { url = "https://files.pythonhosted.org/packages/c5/fa/95d604b58aa375e781daf350897aaaa089cff59d84147e9ccff2447c8294/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5701dc474b041e2934a26d31d39f90fac8a3dee2322b39f7729867f932b1d4", size = 476727, upload-time = "2025-06-15T19:06:01.086Z" }, - { url = "https://files.pythonhosted.org/packages/65/95/fe479b2664f19be4cf5ceeb21be05afd491d95f142e72d26a42f41b7c4f8/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b067915e3c3936966a8607f6fe5487df0c9c4afb85226613b520890049deea20", size = 451864, upload-time = "2025-06-15T19:06:02.144Z" }, - { url = "https://files.pythonhosted.org/packages/d3/8a/3c4af14b93a15ce55901cd7a92e1a4701910f1768c78fb30f61d2b79785b/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:9c733cda03b6d636b4219625a4acb5c6ffb10803338e437fb614fef9516825ef", size = 625626, upload-time = "2025-06-15T19:06:03.578Z" }, - { url = "https://files.pythonhosted.org/packages/da/f5/cf6aa047d4d9e128f4b7cde615236a915673775ef171ff85971d698f3c2c/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:cc08ef8b90d78bfac66f0def80240b0197008e4852c9f285907377b2947ffdcb", size = 622744, upload-time = "2025-06-15T19:06:05.066Z" }, - { url = "https://files.pythonhosted.org/packages/2c/00/70f75c47f05dea6fd30df90f047765f6fc2d6eb8b5a3921379b0b04defa2/watchfiles-1.1.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9974d2f7dc561cce3bb88dfa8eb309dab64c729de85fba32e98d75cf24b66297", size = 402114, upload-time = "2025-06-15T19:06:06.186Z" }, - { url = "https://files.pythonhosted.org/packages/53/03/acd69c48db4a1ed1de26b349d94077cca2238ff98fd64393f3e97484cae6/watchfiles-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c68e9f1fcb4d43798ad8814c4c1b61547b014b667216cb754e606bfade587018", size = 393879, upload-time = "2025-06-15T19:06:07.369Z" }, - { url = "https://files.pythonhosted.org/packages/2f/c8/a9a2a6f9c8baa4eceae5887fecd421e1b7ce86802bcfc8b6a942e2add834/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95ab1594377effac17110e1352989bdd7bdfca9ff0e5eeccd8c69c5389b826d0", size = 450026, upload-time = "2025-06-15T19:06:08.476Z" }, - { url = "https://files.pythonhosted.org/packages/fe/51/d572260d98388e6e2b967425c985e07d47ee6f62e6455cefb46a6e06eda5/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba9b62da882c1be1280a7584ec4515d0a6006a94d6e5819730ec2eab60ffe12", size = 457917, upload-time = "2025-06-15T19:06:09.988Z" }, - { url = "https://files.pythonhosted.org/packages/c6/2d/4258e52917bf9f12909b6ec314ff9636276f3542f9d3807d143f27309104/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3434e401f3ce0ed6b42569128b3d1e3af773d7ec18751b918b89cd49c14eaafb", size = 483602, upload-time = "2025-06-15T19:06:11.088Z" }, - { url = "https://files.pythonhosted.org/packages/84/99/bee17a5f341a4345fe7b7972a475809af9e528deba056f8963d61ea49f75/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa257a4d0d21fcbca5b5fcba9dca5a78011cb93c0323fb8855c6d2dfbc76eb77", size = 596758, upload-time = "2025-06-15T19:06:12.197Z" }, - { url = "https://files.pythonhosted.org/packages/40/76/e4bec1d59b25b89d2b0716b41b461ed655a9a53c60dc78ad5771fda5b3e6/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd1b3879a578a8ec2076c7961076df540b9af317123f84569f5a9ddee64ce92", size = 477601, upload-time = "2025-06-15T19:06:13.391Z" }, - { url = "https://files.pythonhosted.org/packages/1f/fa/a514292956f4a9ce3c567ec0c13cce427c158e9f272062685a8a727d08fc/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc7a30eeb0e20ecc5f4bd113cd69dcdb745a07c68c0370cea919f373f65d9e", size = 451936, upload-time = "2025-06-15T19:06:14.656Z" }, - { url = "https://files.pythonhosted.org/packages/32/5d/c3bf927ec3bbeb4566984eba8dd7a8eb69569400f5509904545576741f88/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:891c69e027748b4a73847335d208e374ce54ca3c335907d381fde4e41661b13b", size = 626243, upload-time = "2025-06-15T19:06:16.232Z" }, - { url = "https://files.pythonhosted.org/packages/e6/65/6e12c042f1a68c556802a84d54bb06d35577c81e29fba14019562479159c/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:12fe8eaffaf0faa7906895b4f8bb88264035b3f0243275e0bf24af0436b27259", size = 623073, upload-time = "2025-06-15T19:06:17.457Z" }, - { url = "https://files.pythonhosted.org/packages/89/ab/7f79d9bf57329e7cbb0a6fd4c7bd7d0cee1e4a8ef0041459f5409da3506c/watchfiles-1.1.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:bfe3c517c283e484843cb2e357dd57ba009cff351edf45fb455b5fbd1f45b15f", size = 400872, upload-time = "2025-06-15T19:06:18.57Z" }, - { url = "https://files.pythonhosted.org/packages/df/d5/3f7bf9912798e9e6c516094db6b8932df53b223660c781ee37607030b6d3/watchfiles-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a9ccbf1f129480ed3044f540c0fdbc4ee556f7175e5ab40fe077ff6baf286d4e", size = 392877, upload-time = "2025-06-15T19:06:19.55Z" }, - { url = "https://files.pythonhosted.org/packages/0d/c5/54ec7601a2798604e01c75294770dbee8150e81c6e471445d7601610b495/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba0e3255b0396cac3cc7bbace76404dd72b5438bf0d8e7cefa2f79a7f3649caa", size = 449645, upload-time = "2025-06-15T19:06:20.66Z" }, - { url = "https://files.pythonhosted.org/packages/0a/04/c2f44afc3b2fce21ca0b7802cbd37ed90a29874f96069ed30a36dfe57c2b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4281cd9fce9fc0a9dbf0fc1217f39bf9cf2b4d315d9626ef1d4e87b84699e7e8", size = 457424, upload-time = "2025-06-15T19:06:21.712Z" }, - { url = "https://files.pythonhosted.org/packages/9f/b0/eec32cb6c14d248095261a04f290636da3df3119d4040ef91a4a50b29fa5/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d2404af8db1329f9a3c9b79ff63e0ae7131986446901582067d9304ae8aaf7f", size = 481584, upload-time = "2025-06-15T19:06:22.777Z" }, - { url = "https://files.pythonhosted.org/packages/d1/e2/ca4bb71c68a937d7145aa25709e4f5d68eb7698a25ce266e84b55d591bbd/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e78b6ed8165996013165eeabd875c5dfc19d41b54f94b40e9fff0eb3193e5e8e", size = 596675, upload-time = "2025-06-15T19:06:24.226Z" }, - { url = "https://files.pythonhosted.org/packages/a1/dd/b0e4b7fb5acf783816bc950180a6cd7c6c1d2cf7e9372c0ea634e722712b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:249590eb75ccc117f488e2fabd1bfa33c580e24b96f00658ad88e38844a040bb", size = 477363, upload-time = "2025-06-15T19:06:25.42Z" }, - { url = "https://files.pythonhosted.org/packages/69/c4/088825b75489cb5b6a761a4542645718893d395d8c530b38734f19da44d2/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05686b5487cfa2e2c28ff1aa370ea3e6c5accfe6435944ddea1e10d93872147", size = 452240, upload-time = "2025-06-15T19:06:26.552Z" }, - { url = "https://files.pythonhosted.org/packages/10/8c/22b074814970eeef43b7c44df98c3e9667c1f7bf5b83e0ff0201b0bd43f9/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d0e10e6f8f6dc5762adee7dece33b722282e1f59aa6a55da5d493a97282fedd8", size = 625607, upload-time = "2025-06-15T19:06:27.606Z" }, - { url = "https://files.pythonhosted.org/packages/32/fa/a4f5c2046385492b2273213ef815bf71a0d4c1943b784fb904e184e30201/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:af06c863f152005c7592df1d6a7009c836a247c9d8adb78fef8575a5a98699db", size = 623315, upload-time = "2025-06-15T19:06:29.076Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ff/ded57ac5ff40a09e6e198550bab075d780941e0b0f83cbeabd087c59383a/virtualenv-20.33.1-py3-none-any.whl", hash = "sha256:07c19bc66c11acab6a5958b815cbcee30891cd1c2ccf53785a28651a0d8d8a67", size = 6060362 }, ] [[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/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/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, -] - -[[package]] -name = "wsproto" -version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425, upload-time = "2022-08-23T19:58:21.447Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226, upload-time = "2022-08-23T19:58:19.96Z" }, -] - -[[package]] -name = "yarl" -version = "1.20.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "multidict" }, - { name = "propcache" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3c/fb/efaa23fa4e45537b827620f04cf8f3cd658b76642205162e072703a5b963/yarl-1.20.1.tar.gz", hash = "sha256:d017a4997ee50c91fd5466cef416231bb82177b93b029906cefc542ce14c35ac", size = 186428, upload-time = "2025-06-10T00:46:09.923Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/9a/cb7fad7d73c69f296eda6815e4a2c7ed53fc70c2f136479a91c8e5fbdb6d/yarl-1.20.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdcc4cd244e58593a4379fe60fdee5ac0331f8eb70320a24d591a3be197b94a9", size = 133667, upload-time = "2025-06-10T00:43:44.369Z" }, - { url = "https://files.pythonhosted.org/packages/67/38/688577a1cb1e656e3971fb66a3492501c5a5df56d99722e57c98249e5b8a/yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a", size = 91025, upload-time = "2025-06-10T00:43:46.295Z" }, - { url = "https://files.pythonhosted.org/packages/50/ec/72991ae51febeb11a42813fc259f0d4c8e0507f2b74b5514618d8b640365/yarl-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1112ae8154186dfe2de4732197f59c05a83dc814849a5ced892b708033f40dc2", size = 89709, upload-time = "2025-06-10T00:43:48.22Z" }, - { url = "https://files.pythonhosted.org/packages/99/da/4d798025490e89426e9f976702e5f9482005c548c579bdae792a4c37769e/yarl-1.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90bbd29c4fe234233f7fa2b9b121fb63c321830e5d05b45153a2ca68f7d310ee", size = 352287, upload-time = "2025-06-10T00:43:49.924Z" }, - { url = "https://files.pythonhosted.org/packages/1a/26/54a15c6a567aac1c61b18aa0f4b8aa2e285a52d547d1be8bf48abe2b3991/yarl-1.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:680e19c7ce3710ac4cd964e90dad99bf9b5029372ba0c7cbfcd55e54d90ea819", size = 345429, upload-time = "2025-06-10T00:43:51.7Z" }, - { url = "https://files.pythonhosted.org/packages/d6/95/9dcf2386cb875b234353b93ec43e40219e14900e046bf6ac118f94b1e353/yarl-1.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a979218c1fdb4246a05efc2cc23859d47c89af463a90b99b7c56094daf25a16", size = 365429, upload-time = "2025-06-10T00:43:53.494Z" }, - { url = "https://files.pythonhosted.org/packages/91/b2/33a8750f6a4bc224242a635f5f2cff6d6ad5ba651f6edcccf721992c21a0/yarl-1.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255b468adf57b4a7b65d8aad5b5138dce6a0752c139965711bdcb81bc370e1b6", size = 363862, upload-time = "2025-06-10T00:43:55.766Z" }, - { url = "https://files.pythonhosted.org/packages/98/28/3ab7acc5b51f4434b181b0cee8f1f4b77a65919700a355fb3617f9488874/yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd", size = 355616, upload-time = "2025-06-10T00:43:58.056Z" }, - { url = "https://files.pythonhosted.org/packages/36/a3/f666894aa947a371724ec7cd2e5daa78ee8a777b21509b4252dd7bd15e29/yarl-1.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8570d998db4ddbfb9a590b185a0a33dbf8aafb831d07a5257b4ec9948df9cb0a", size = 339954, upload-time = "2025-06-10T00:43:59.773Z" }, - { url = "https://files.pythonhosted.org/packages/f1/81/5f466427e09773c04219d3450d7a1256138a010b6c9f0af2d48565e9ad13/yarl-1.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:97c75596019baae7c71ccf1d8cc4738bc08134060d0adfcbe5642f778d1dca38", size = 365575, upload-time = "2025-06-10T00:44:02.051Z" }, - { url = "https://files.pythonhosted.org/packages/2e/e3/e4b0ad8403e97e6c9972dd587388940a032f030ebec196ab81a3b8e94d31/yarl-1.20.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c48912653e63aef91ff988c5432832692ac5a1d8f0fb8a33091520b5bbe19ef", size = 365061, upload-time = "2025-06-10T00:44:04.196Z" }, - { url = "https://files.pythonhosted.org/packages/ac/99/b8a142e79eb86c926f9f06452eb13ecb1bb5713bd01dc0038faf5452e544/yarl-1.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4c3ae28f3ae1563c50f3d37f064ddb1511ecc1d5584e88c6b7c63cf7702a6d5f", size = 364142, upload-time = "2025-06-10T00:44:06.527Z" }, - { url = "https://files.pythonhosted.org/packages/34/f2/08ed34a4a506d82a1a3e5bab99ccd930a040f9b6449e9fd050320e45845c/yarl-1.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e9642f27036283550f5f57dc6156c51084b458570b9d0d96100c8bebb186a8", size = 381894, upload-time = "2025-06-10T00:44:08.379Z" }, - { url = "https://files.pythonhosted.org/packages/92/f8/9a3fbf0968eac704f681726eff595dce9b49c8a25cd92bf83df209668285/yarl-1.20.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2c26b0c49220d5799f7b22c6838409ee9bc58ee5c95361a4d7831f03cc225b5a", size = 383378, upload-time = "2025-06-10T00:44:10.51Z" }, - { url = "https://files.pythonhosted.org/packages/af/85/9363f77bdfa1e4d690957cd39d192c4cacd1c58965df0470a4905253b54f/yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004", size = 374069, upload-time = "2025-06-10T00:44:12.834Z" }, - { url = "https://files.pythonhosted.org/packages/35/99/9918c8739ba271dcd935400cff8b32e3cd319eaf02fcd023d5dcd487a7c8/yarl-1.20.1-cp312-cp312-win32.whl", hash = "sha256:daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5", size = 81249, upload-time = "2025-06-10T00:44:14.731Z" }, - { url = "https://files.pythonhosted.org/packages/eb/83/5d9092950565481b413b31a23e75dd3418ff0a277d6e0abf3729d4d1ce25/yarl-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698", size = 86710, upload-time = "2025-06-10T00:44:16.716Z" }, - { url = "https://files.pythonhosted.org/packages/8a/e1/2411b6d7f769a07687acee88a062af5833cf1966b7266f3d8dfb3d3dc7d3/yarl-1.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0b5ff0fbb7c9f1b1b5ab53330acbfc5247893069e7716840c8e7d5bb7355038a", size = 131811, upload-time = "2025-06-10T00:44:18.933Z" }, - { url = "https://files.pythonhosted.org/packages/b2/27/584394e1cb76fb771371770eccad35de400e7b434ce3142c2dd27392c968/yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3", size = 90078, upload-time = "2025-06-10T00:44:20.635Z" }, - { url = "https://files.pythonhosted.org/packages/bf/9a/3246ae92d4049099f52d9b0fe3486e3b500e29b7ea872d0f152966fc209d/yarl-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f60e4ad5db23f0b96e49c018596707c3ae89f5d0bd97f0ad3684bcbad899f1e7", size = 88748, upload-time = "2025-06-10T00:44:22.34Z" }, - { url = "https://files.pythonhosted.org/packages/a3/25/35afe384e31115a1a801fbcf84012d7a066d89035befae7c5d4284df1e03/yarl-1.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49bdd1b8e00ce57e68ba51916e4bb04461746e794e7c4d4bbc42ba2f18297691", size = 349595, upload-time = "2025-06-10T00:44:24.314Z" }, - { url = "https://files.pythonhosted.org/packages/28/2d/8aca6cb2cabc8f12efcb82749b9cefecbccfc7b0384e56cd71058ccee433/yarl-1.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:66252d780b45189975abfed839616e8fd2dbacbdc262105ad7742c6ae58f3e31", size = 342616, upload-time = "2025-06-10T00:44:26.167Z" }, - { url = "https://files.pythonhosted.org/packages/0b/e9/1312633d16b31acf0098d30440ca855e3492d66623dafb8e25b03d00c3da/yarl-1.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59174e7332f5d153d8f7452a102b103e2e74035ad085f404df2e40e663a22b28", size = 361324, upload-time = "2025-06-10T00:44:27.915Z" }, - { url = "https://files.pythonhosted.org/packages/bc/a0/688cc99463f12f7669eec7c8acc71ef56a1521b99eab7cd3abb75af887b0/yarl-1.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3968ec7d92a0c0f9ac34d5ecfd03869ec0cab0697c91a45db3fbbd95fe1b653", size = 359676, upload-time = "2025-06-10T00:44:30.041Z" }, - { url = "https://files.pythonhosted.org/packages/af/44/46407d7f7a56e9a85a4c207724c9f2c545c060380718eea9088f222ba697/yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5", size = 352614, upload-time = "2025-06-10T00:44:32.171Z" }, - { url = "https://files.pythonhosted.org/packages/b1/91/31163295e82b8d5485d31d9cf7754d973d41915cadce070491778d9c9825/yarl-1.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a62c839c3a8eac2410e951301309426f368388ff2f33799052787035793b02", size = 336766, upload-time = "2025-06-10T00:44:34.494Z" }, - { url = "https://files.pythonhosted.org/packages/b4/8e/c41a5bc482121f51c083c4c2bcd16b9e01e1cf8729e380273a952513a21f/yarl-1.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:041eaa14f73ff5a8986b4388ac6bb43a77f2ea09bf1913df7a35d4646db69e53", size = 364615, upload-time = "2025-06-10T00:44:36.856Z" }, - { url = "https://files.pythonhosted.org/packages/e3/5b/61a3b054238d33d70ea06ebba7e58597891b71c699e247df35cc984ab393/yarl-1.20.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:377fae2fef158e8fd9d60b4c8751387b8d1fb121d3d0b8e9b0be07d1b41e83dc", size = 360982, upload-time = "2025-06-10T00:44:39.141Z" }, - { url = "https://files.pythonhosted.org/packages/df/a3/6a72fb83f8d478cb201d14927bc8040af901811a88e0ff2da7842dd0ed19/yarl-1.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1c92f4390e407513f619d49319023664643d3339bd5e5a56a3bebe01bc67ec04", size = 369792, upload-time = "2025-06-10T00:44:40.934Z" }, - { url = "https://files.pythonhosted.org/packages/7c/af/4cc3c36dfc7c077f8dedb561eb21f69e1e9f2456b91b593882b0b18c19dc/yarl-1.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d25ddcf954df1754ab0f86bb696af765c5bfaba39b74095f27eececa049ef9a4", size = 382049, upload-time = "2025-06-10T00:44:42.854Z" }, - { url = "https://files.pythonhosted.org/packages/19/3a/e54e2c4752160115183a66dc9ee75a153f81f3ab2ba4bf79c3c53b33de34/yarl-1.20.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:909313577e9619dcff8c31a0ea2aa0a2a828341d92673015456b3ae492e7317b", size = 384774, upload-time = "2025-06-10T00:44:45.275Z" }, - { url = "https://files.pythonhosted.org/packages/9c/20/200ae86dabfca89060ec6447649f219b4cbd94531e425e50d57e5f5ac330/yarl-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:793fd0580cb9664548c6b83c63b43c477212c0260891ddf86809e1c06c8b08f1", size = 374252, upload-time = "2025-06-10T00:44:47.31Z" }, - { url = "https://files.pythonhosted.org/packages/83/75/11ee332f2f516b3d094e89448da73d557687f7d137d5a0f48c40ff211487/yarl-1.20.1-cp313-cp313-win32.whl", hash = "sha256:468f6e40285de5a5b3c44981ca3a319a4b208ccc07d526b20b12aeedcfa654b7", size = 81198, upload-time = "2025-06-10T00:44:49.164Z" }, - { url = "https://files.pythonhosted.org/packages/ba/ba/39b1ecbf51620b40ab402b0fc817f0ff750f6d92712b44689c2c215be89d/yarl-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:495b4ef2fea40596bfc0affe3837411d6aa3371abcf31aac0ccc4bdd64d4ef5c", size = 86346, upload-time = "2025-06-10T00:44:51.182Z" }, - { url = "https://files.pythonhosted.org/packages/43/c7/669c52519dca4c95153c8ad96dd123c79f354a376346b198f438e56ffeb4/yarl-1.20.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f60233b98423aab21d249a30eb27c389c14929f47be8430efa7dbd91493a729d", size = 138826, upload-time = "2025-06-10T00:44:52.883Z" }, - { url = "https://files.pythonhosted.org/packages/6a/42/fc0053719b44f6ad04a75d7f05e0e9674d45ef62f2d9ad2c1163e5c05827/yarl-1.20.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6f3eff4cc3f03d650d8755c6eefc844edde99d641d0dcf4da3ab27141a5f8ddf", size = 93217, upload-time = "2025-06-10T00:44:54.658Z" }, - { url = "https://files.pythonhosted.org/packages/4f/7f/fa59c4c27e2a076bba0d959386e26eba77eb52ea4a0aac48e3515c186b4c/yarl-1.20.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:69ff8439d8ba832d6bed88af2c2b3445977eba9a4588b787b32945871c2444e3", size = 92700, upload-time = "2025-06-10T00:44:56.784Z" }, - { url = "https://files.pythonhosted.org/packages/2f/d4/062b2f48e7c93481e88eff97a6312dca15ea200e959f23e96d8ab898c5b8/yarl-1.20.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf34efa60eb81dd2645a2e13e00bb98b76c35ab5061a3989c7a70f78c85006d", size = 347644, upload-time = "2025-06-10T00:44:59.071Z" }, - { url = "https://files.pythonhosted.org/packages/89/47/78b7f40d13c8f62b499cc702fdf69e090455518ae544c00a3bf4afc9fc77/yarl-1.20.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8e0fe9364ad0fddab2688ce72cb7a8e61ea42eff3c7caeeb83874a5d479c896c", size = 323452, upload-time = "2025-06-10T00:45:01.605Z" }, - { url = "https://files.pythonhosted.org/packages/eb/2b/490d3b2dc66f52987d4ee0d3090a147ea67732ce6b4d61e362c1846d0d32/yarl-1.20.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f64fbf81878ba914562c672024089e3401974a39767747691c65080a67b18c1", size = 346378, upload-time = "2025-06-10T00:45:03.946Z" }, - { url = "https://files.pythonhosted.org/packages/66/ad/775da9c8a94ce925d1537f939a4f17d782efef1f973039d821cbe4bcc211/yarl-1.20.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6342d643bf9a1de97e512e45e4b9560a043347e779a173250824f8b254bd5ce", size = 353261, upload-time = "2025-06-10T00:45:05.992Z" }, - { url = "https://files.pythonhosted.org/packages/4b/23/0ed0922b47a4f5c6eb9065d5ff1e459747226ddce5c6a4c111e728c9f701/yarl-1.20.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56dac5f452ed25eef0f6e3c6a066c6ab68971d96a9fb441791cad0efba6140d3", size = 335987, upload-time = "2025-06-10T00:45:08.227Z" }, - { url = "https://files.pythonhosted.org/packages/3e/49/bc728a7fe7d0e9336e2b78f0958a2d6b288ba89f25a1762407a222bf53c3/yarl-1.20.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7d7f497126d65e2cad8dc5f97d34c27b19199b6414a40cb36b52f41b79014be", size = 329361, upload-time = "2025-06-10T00:45:10.11Z" }, - { url = "https://files.pythonhosted.org/packages/93/8f/b811b9d1f617c83c907e7082a76e2b92b655400e61730cd61a1f67178393/yarl-1.20.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:67e708dfb8e78d8a19169818eeb5c7a80717562de9051bf2413aca8e3696bf16", size = 346460, upload-time = "2025-06-10T00:45:12.055Z" }, - { url = "https://files.pythonhosted.org/packages/70/fd/af94f04f275f95da2c3b8b5e1d49e3e79f1ed8b6ceb0f1664cbd902773ff/yarl-1.20.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:595c07bc79af2494365cc96ddeb772f76272364ef7c80fb892ef9d0649586513", size = 334486, upload-time = "2025-06-10T00:45:13.995Z" }, - { url = "https://files.pythonhosted.org/packages/84/65/04c62e82704e7dd0a9b3f61dbaa8447f8507655fd16c51da0637b39b2910/yarl-1.20.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7bdd2f80f4a7df852ab9ab49484a4dee8030023aa536df41f2d922fd57bf023f", size = 342219, upload-time = "2025-06-10T00:45:16.479Z" }, - { url = "https://files.pythonhosted.org/packages/91/95/459ca62eb958381b342d94ab9a4b6aec1ddec1f7057c487e926f03c06d30/yarl-1.20.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c03bfebc4ae8d862f853a9757199677ab74ec25424d0ebd68a0027e9c639a390", size = 350693, upload-time = "2025-06-10T00:45:18.399Z" }, - { url = "https://files.pythonhosted.org/packages/a6/00/d393e82dd955ad20617abc546a8f1aee40534d599ff555ea053d0ec9bf03/yarl-1.20.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:344d1103e9c1523f32a5ed704d576172d2cabed3122ea90b1d4e11fe17c66458", size = 355803, upload-time = "2025-06-10T00:45:20.677Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ed/c5fb04869b99b717985e244fd93029c7a8e8febdfcffa06093e32d7d44e7/yarl-1.20.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88cab98aa4e13e1ade8c141daeedd300a4603b7132819c484841bb7af3edce9e", size = 341709, upload-time = "2025-06-10T00:45:23.221Z" }, - { url = "https://files.pythonhosted.org/packages/24/fd/725b8e73ac2a50e78a4534ac43c6addf5c1c2d65380dd48a9169cc6739a9/yarl-1.20.1-cp313-cp313t-win32.whl", hash = "sha256:b121ff6a7cbd4abc28985b6028235491941b9fe8fe226e6fdc539c977ea1739d", size = 86591, upload-time = "2025-06-10T00:45:25.793Z" }, - { url = "https://files.pythonhosted.org/packages/94/c3/b2e9f38bc3e11191981d57ea08cab2166e74ea770024a646617c9cddd9f6/yarl-1.20.1-cp313-cp313t-win_amd64.whl", hash = "sha256:541d050a355bbbc27e55d906bc91cb6fe42f96c01413dd0f4ed5a5240513874f", size = 93003, upload-time = "2025-06-10T00:45:27.752Z" }, - { url = "https://files.pythonhosted.org/packages/b4/2d/2345fce04cfd4bee161bf1e7d9cdc702e3e16109021035dbb24db654a622/yarl-1.20.1-py3-none-any.whl", hash = "sha256:83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77", size = 46542, upload-time = "2025-06-10T00:46:07.521Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/21/e6/26d09fab466b7ca9c7737474c52be4f76a40301b08362eb2dbc19dcc16c1/websockets-15.0.1.tar.gz", hash = "sha256:82544de02076bafba038ce055ee6412d68da13ab47f0c60cab827346de828dee", size = 177016 } +wheels = [ + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395 }, + { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { 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 }, + { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393 }, + { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837 }, + { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743 }, ] From f2e3d4b06685d9558f8dab36209a62e8e4e672f4 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:48:59 +0300 Subject: [PATCH 074/198] dockerize the backend --- Dockerfile.backend | 18 ++++ docker-compose.yaml | 227 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 Dockerfile.backend create mode 100644 docker-compose.yaml diff --git a/Dockerfile.backend b/Dockerfile.backend new file mode 100644 index 00000000..3457eb71 --- /dev/null +++ b/Dockerfile.backend @@ -0,0 +1,18 @@ +FROM python:3.12-slim + +COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ + +WORKDIR /app + +RUN --mount=type=cache,target=/root/.cache/uv \ + --mount=type=bind,source=uv.lock,target=uv.lock \ + --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ + uv sync --frozen --no-install-workspace --package=backend + +ADD ./packages/backend /app + +# RUN --mount=type=cache,target=/root/.cache/uv \ +# uv sync --frozen + +# Run with uvicorn +CMD ["uv", "run", "uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8060"] diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000..b5463fbe --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,227 @@ +name: cj12 + +services: + backend: + build: + context: . + dockerfile: Dockerfile.backend + image: cj12-backend + container_name: cj12-backend + ports: + - "9000:8060" + env_file: ./packages/backend/.env + # networks: + # - shared-net + + studio: + container_name: supabase-studio + image: supabase/studio:2025.06.30-sha-6f5982d + restart: unless-stopped + healthcheck: + test: + [ + "CMD", + "node", + "-e", + "fetch('http://studio:3000/api/platform/profile').then((r) => {if (r.status !== 200) throw new Error(r.status)})", + ] + timeout: 10s + interval: 5s + retries: 3 + environment: + STUDIO_PG_META_URL: http://meta:8080 + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + + DEFAULT_ORGANIZATION_NAME: ${STUDIO_DEFAULT_ORGANIZATION} + DEFAULT_PROJECT_NAME: ${STUDIO_DEFAULT_PROJECT} + + SUPABASE_URL: http://kong:8000 + SUPABASE_PUBLIC_URL: ${SUPABASE_PUBLIC_URL} + SUPABASE_ANON_KEY: ${ANON_KEY} + SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY} + AUTH_JWT_SECRET: ${JWT_SECRET} + + kong: + container_name: supabase-kong + image: kong:2.8.1 + restart: unless-stopped + ports: + - ${KONG_HTTP_PORT}:8000/tcp + - ${KONG_HTTPS_PORT}:8443/tcp + volumes: + # https://github.com/supabase/supabase/issues/12661 + - ./volumes/api/kong.yml:/home/kong/temp.yml:ro,z + environment: + KONG_DATABASE: "off" + KONG_DECLARATIVE_CONFIG: /home/kong/kong.yml + # https://github.com/supabase/cli/issues/14 + KONG_DNS_ORDER: LAST,A,CNAME + KONG_PLUGINS: request-transformer,cors,key-auth,acl,basic-auth + KONG_NGINX_PROXY_PROXY_BUFFER_SIZE: 160k + KONG_NGINX_PROXY_PROXY_BUFFERS: 64 160k + SUPABASE_ANON_KEY: ${ANON_KEY} + SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY} + DASHBOARD_USERNAME: ${DASHBOARD_USERNAME} + DASHBOARD_PASSWORD: ${DASHBOARD_PASSWORD} + # https://unix.stackexchange.com/a/294837 + entrypoint: bash -c 'eval "echo \"$$(cat ~/temp.yml)\"" > ~/kong.yml && /docker-entrypoint.sh kong docker-start' + + auth: + container_name: supabase-auth + image: supabase/gotrue:v2.177.0 + restart: unless-stopped + healthcheck: + test: + [ + "CMD", + "wget", + "--no-verbose", + "--tries=1", + "--spider", + "http://localhost:9999/health", + ] + timeout: 5s + interval: 5s + retries: 3 + depends_on: + db: + condition: service_healthy + environment: + GOTRUE_API_HOST: 0.0.0.0 + GOTRUE_API_PORT: 9999 + API_EXTERNAL_URL: ${API_EXTERNAL_URL} + + GOTRUE_DB_DRIVER: postgres + GOTRUE_DB_DATABASE_URL: postgres://supabase_auth_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} + + GOTRUE_SITE_URL: ${SITE_URL} + GOTRUE_URI_ALLOW_LIST: ${ADDITIONAL_REDIRECT_URLS} + GOTRUE_DISABLE_SIGNUP: ${DISABLE_SIGNUP} + + GOTRUE_JWT_ADMIN_ROLES: service_role + GOTRUE_JWT_AUD: authenticated + GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated + GOTRUE_JWT_EXP: ${JWT_EXPIRY} + GOTRUE_JWT_SECRET: ${JWT_SECRET} + + GOTRUE_EXTERNAL_GITHUB_ENABLED: true + GOTRUE_EXTERNAL_GITHUB_CLIENT_ID: ${CLIENT_ID} + GOTRUE_EXTERNAL_GITHUB_SECRET: ${CLIENT_SECRET} + GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI: "http://localhost:8000/auth/v1/callback" + + meta: + container_name: supabase-meta + image: supabase/postgres-meta:v0.91.0 + restart: unless-stopped + depends_on: + db: + condition: service_healthy + environment: + PG_META_PORT: 8080 + PG_META_DB_HOST: ${POSTGRES_HOST} + PG_META_DB_PORT: ${POSTGRES_PORT} + PG_META_DB_NAME: ${POSTGRES_DB} + PG_META_DB_USER: supabase_admin + PG_META_DB_PASSWORD: ${POSTGRES_PASSWORD} + + db: + container_name: supabase-db + image: supabase/postgres:15.8.1.060 + restart: unless-stopped + volumes: + - ./volumes/db/realtime.sql:/docker-entrypoint-initdb.d/migrations/99-realtime.sql:Z + # Must be superuser to create event trigger + - ./volumes/db/webhooks.sql:/docker-entrypoint-initdb.d/init-scripts/98-webhooks.sql:Z + # Must be superuser to alter reserved role + - ./volumes/db/roles.sql:/docker-entrypoint-initdb.d/init-scripts/99-roles.sql:Z + # Initialize the database settings with JWT_SECRET and JWT_EXP + - ./volumes/db/jwt.sql:/docker-entrypoint-initdb.d/init-scripts/99-jwt.sql:Z + # PGDATA directory is persisted between restarts + - ./volumes/db/data:/var/lib/postgresql/data:Z + # Changes required for internal supabase data such as _analytics + - ./volumes/db/_supabase.sql:/docker-entrypoint-initdb.d/migrations/97-_supabase.sql:Z + # Changes required for Analytics support + - ./volumes/db/logs.sql:/docker-entrypoint-initdb.d/migrations/99-logs.sql:Z + # Changes required for Pooler support + - ./volumes/db/pooler.sql:/docker-entrypoint-initdb.d/migrations/99-pooler.sql:Z + # Use named volume to persist pgsodium decryption key between restarts + - db-config:/etc/postgresql-custom + healthcheck: + test: ["CMD", "pg_isready", "-U", "postgres", "-h", "localhost"] + interval: 5s + timeout: 5s + retries: 10 + environment: + POSTGRES_HOST: /var/run/postgresql + PGPORT: ${POSTGRES_PORT} + POSTGRES_PORT: ${POSTGRES_PORT} + PGPASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + PGDATABASE: ${POSTGRES_DB} + POSTGRES_DB: ${POSTGRES_DB} + JWT_SECRET: ${JWT_SECRET} + JWT_EXP: ${JWT_EXPIRY} + command: [ + "postgres", + "-c", + "config_file=/etc/postgresql/postgresql.conf", + "-c", + "log_min_messages=fatal", # prevents Realtime polling queries from appearing in logs + ] + + supavisor: + container_name: supabase-pooler + image: supabase/supavisor:2.5.7 + restart: unless-stopped + ports: + - ${POSTGRES_PORT}:5432 + - ${POOLER_PROXY_PORT_TRANSACTION}:6543 + volumes: + - ./volumes/pooler/pooler.exs:/etc/pooler/pooler.exs:ro,z + healthcheck: + test: + [ + "CMD", + "curl", + "-sSfL", + "--head", + "-o", + "/dev/null", + "http://127.0.0.1:4000/api/health", + ] + interval: 10s + timeout: 5s + retries: 5 + depends_on: + db: + condition: service_healthy + environment: + PORT: 4000 + POSTGRES_PORT: ${POSTGRES_PORT} + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + DATABASE_URL: ecto://supabase_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/_supabase + CLUSTER_POSTGRES: true + SECRET_KEY_BASE: ${SECRET_KEY_BASE} + VAULT_ENC_KEY: ${VAULT_ENC_KEY} + API_JWT_SECRET: ${JWT_SECRET} + METRICS_JWT_SECRET: ${JWT_SECRET} + REGION: local + ERL_AFLAGS: -proto_dist inet_tcp + POOLER_TENANT_ID: ${POOLER_TENANT_ID} + POOLER_DEFAULT_POOL_SIZE: ${POOLER_DEFAULT_POOL_SIZE} + POOLER_MAX_CLIENT_CONN: ${POOLER_MAX_CLIENT_CONN} + POOLER_POOL_MODE: transaction + DB_POOL_SIZE: ${POOLER_DB_POOL_SIZE} + command: + [ + "/bin/sh", + "-c", + '/app/bin/migrate && /app/bin/supavisor eval "$$(cat /etc/pooler/pooler.exs)" && /app/bin/server', + ] + +volumes: + db-config: +# networks: +# shared-net: +# external: true From a29d7a9539889d61ef1d2f34ecbf6b0517fb21aa Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Fri, 15 Aug 2025 02:14:08 +0300 Subject: [PATCH 075/198] prettify the backend .env template --- packages/backend/.env.template | 90 ++++++++++++++-------------------- 1 file changed, 36 insertions(+), 54 deletions(-) diff --git a/packages/backend/.env.template b/packages/backend/.env.template index 21449bf1..1ec44501 100644 --- a/packages/backend/.env.template +++ b/packages/backend/.env.template @@ -1,69 +1,51 @@ +# --- GitHub App Configuration --- + CLIENT_ID="YOUR_CLIENT_ID" CLIENT_SECRET="YOUR_CLIENT_SECRET" -############ + +# --- Supabase Configuration --- +# For more information visit https://supabase.com/docs/guides/self-hosting/docker +# These variables are "inspired" by the official Supabase configuration example: +# https://github.com/supabase/supabase/blob/master/docker/.env.example + # Secrets # YOU MUST CHANGE THESE BEFORE GOING INTO PRODUCTION -############ +POSTGRES_PASSWORD="your-super-secret-and-long-postgres-password" +JWT_SECRET="your-super-secret-jwt-token-with-at-least-32-characters-long" +ANON_KEY="your-anon-jwt-token" +SERVICE_ROLE_KEY="your-service-jwt-token" +DASHBOARD_USERNAME="supabase" +DASHBOARD_PASSWORD="this_password_is_insecure_and_should_be_updated" +SECRET_KEY_BASE="UpNVntn3cDxHJpq99YMc1T1AQgQpc8kfYTuRgBiYa15BLrx8etQoXz3gZv1/u2oq" +VAULT_ENC_KEY="your-encryption-key-32-chars-min" -POSTGRES_PASSWORD=your-super-secret-and-long-postgres-password -JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long -ANON_KEY=your-anon-jwt-token -SERVICE_ROLE_KEY=your-service-jwt-token -DASHBOARD_USERNAME=supabase -DASHBOARD_PASSWORD=this_password_is_insecure_and_should_be_updated -SECRET_KEY_BASE=UpNVntn3cDxHJpq99YMc1T1AQgQpc8kfYTuRgBiYa15BLrx8etQoXz3gZv1/u2oq -VAULT_ENC_KEY=your-encryption-key-32-chars-min - -############ # Database - You can change these to any PostgreSQL database that has logical replication enabled. -############ - -POSTGRES_HOST=db -POSTGRES_DB=postgres -POSTGRES_PORT=5432 +POSTGRES_HOST="db" +POSTGRES_DB="postgres" +POSTGRES_PORT="5432" # default user is postgres -############ # Supavisor -- Database pooler -############ -# Port Supavisor listens on for transaction pooling connections -POOLER_PROXY_PORT_TRANSACTION=6543 -# Maximum number of PostgreSQL connections Supavisor opens per pool -POOLER_DEFAULT_POOL_SIZE=20 -# Maximum number of client connections Supavisor accepts per pool -POOLER_MAX_CLIENT_CONN=100 -# Unique tenant identifier -POOLER_TENANT_ID=your-tenant-id -# Pool size for internal metadata storage used by Supavisor -# This is separate from client connections and used only by Supavisor itself -POOLER_DB_POOL_SIZE=5 +POOLER_PROXY_PORT_TRANSACTION="6543" +POOLER_DEFAULT_POOL_SIZE="20" +POOLER_MAX_CLIENT_CONN="100" +POOLER_TENANT_ID="your-tenant-id" +POOLER_DB_POOL_SIZE="5" -############ # API Proxy - Configuration for the Kong Reverse proxy. -############ +KONG_HTTP_PORT="8000" +KONG_HTTPS_PORT="8443" -KONG_HTTP_PORT=8000 -KONG_HTTPS_PORT=8443 +# General +SITE_URL="http://localhost:3000" +ADDITIONAL_REDIRECT_URLS="http://localhost:9000/auth" +JWT_EXPIRY="3600" +DISABLE_SIGNUP="false" +API_EXTERNAL_URL="http://localhost:8000" -############ -# Auth - Configuration for the GoTrue authentication server. -############ - -## General -SITE_URL=http://localhost:3000 -ADDITIONAL_REDIRECT_URLS=http://localhost:9000/auth -JWT_EXPIRY=3600 -DISABLE_SIGNUP=false -API_EXTERNAL_URL=http://localhost:8000 - -############ # Studio - Configuration for the Dashboard -############ - -STUDIO_DEFAULT_ORGANIZATION=Default Organization -STUDIO_DEFAULT_PROJECT=Default Project - -STUDIO_PORT=3000 -# replace if you intend to use Studio outside of localhost -SUPABASE_PUBLIC_URL=http://localhost:8000 +STUDIO_DEFAULT_ORGANIZATION="Default Organization" +STUDIO_DEFAULT_PROJECT="Default Project" +STUDIO_PORT="3000" +SUPABASE_PUBLIC_URL="http://localhost:8000" From 869a7af25335eb7c643eb962c383b5e3260c3219 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 00:41:49 +0100 Subject: [PATCH 076/198] Fix merge issues --- packages/editor/scripts/editor.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index 79809dae..79c1bb6a 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -1,5 +1,5 @@ # This should be under the other imports but because it isn't imported in the traditional way, it's above them. -from canvas_ctx import CanvasContext +from canvas_ctx import CanvasContext # pyright: ignore[reportMissingImports] # # Following imports have the ignore flag as they are not pip installed from js import ( # pyright: ignore[reportMissingImports] @@ -137,6 +137,7 @@ def draw_pixel(x: float, y: float) -> None: Args: x (float): X coordinate y (float): Y coordinate + """ ctx.fillStyle = ctx.strokeStyle ctx.fillRect(x - PIXEL_SIZE // 2, y - PIXEL_SIZE // 2, PIXEL_SIZE, PIXEL_SIZE) @@ -151,6 +152,7 @@ def show_action_icon(x: float, y: float) -> bool: Returns: bool: If True is returned mousemove doesn't do anything else + """ buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) if ctx.moving_image: @@ -217,6 +219,7 @@ def draw_smudge(event: MouseEvent) -> None: Args: event (MouseEvent): The javascript mouse event + """ x, y = get_canvas_coords(event) # draw the pevious smudge data at the current xy. @@ -233,6 +236,7 @@ def get_canvas_coords(event: MouseEvent) -> tuple[float, float]: Returns: tuple[float, float]: The x and y coordinates + """ x = (event.pageX - ctx.bounding_rect.left) * ctx.scaled_by y = (event.pageY - ctx.bounding_rect.top) * ctx.scaled_by @@ -248,6 +252,7 @@ def start_path(event: MouseEvent) -> None: Args: event (MouseEvent): The mouse event + """ if event.button != 0: return @@ -271,6 +276,7 @@ def mouse_tracker(event: MouseEvent) -> None: Args: event (MouseEvent): The mouse event + """ x, y = get_canvas_coords(event) @@ -310,6 +316,7 @@ def stop_path(_: MouseEvent) -> None: Args: event (MouseEvent): The mouse event + """ if ctx.text_placed: ctx.writing_text = False @@ -324,6 +331,7 @@ def start_reentry_path(event: MouseEvent) -> None: Args: event (MouseEvent): Mouse event + """ if ctx.drawing: x, y = get_canvas_coords(event) @@ -337,6 +345,7 @@ def leaves_canvas(event: MouseEvent) -> None: Args: event (MouseEvent): The mouse event + """ if not ctx.drawing: return @@ -356,6 +365,7 @@ def canvas_click(event: MouseEvent) -> None: Args: event (MouseEvent): The mouse event + """ if event.button != 0: return @@ -394,6 +404,7 @@ def colour_change(_: Event) -> None: Args: _ (Event): Change event + """ ctx.strokeStyle = window.pen.colour ctx.fillStyle = window.pen.colour @@ -407,6 +418,7 @@ def width_change(event: Event) -> None: Args: event (Event): Change event + """ ctx.lineWidth = int(event.target.getAttribute("aria-valuenow")) buffer_ctx.lineWidth = ctx.lineWidth @@ -418,6 +430,7 @@ def action_change(event: Event) -> None: Args: event (Event): Change event + """ ctx.action = event.target.getAttribute("value") match ctx.action: @@ -435,6 +448,7 @@ def add_text(_: Event) -> None: Args: _ (Event): Add text event + """ ctx.text_value = text_input.value if ctx.text_value: @@ -456,6 +470,7 @@ def type_change(event: Event) -> None: Args: event (Event): Change event + """ ctx.type = event.target.getAttribute("value") if ctx.type == "smooth": @@ -475,6 +490,7 @@ def reset_board(_: Event) -> None: Args: _ (Event): Reset event + """ ctx.clearRect(0, 0, canvas.width, canvas.height) @@ -485,6 +501,7 @@ def download_image(_: Event) -> None: Args: _ (Event): Click event + """ link = document.createElement("a") link.download = "download.avif" @@ -499,6 +516,7 @@ def upload_image(e: Event) -> None: Args: e (Event): Upload event + """ ctx.prev_operation = ctx.globalCompositeOperation ctx.globalCompositeOperation = "source-over" @@ -515,6 +533,7 @@ def resize(_: Event, keep_content: dict | bool = True) -> None: # noqa: FBT001, _ (Event): Resize event keep_content (bool): Flag to keep the existing content. It's technically not a dict. It's an Object, but I can't type hint with it. + """ data = ctx.getImageData(0, 0, canvas.width, canvas.height) line_width = ctx.lineWidth @@ -572,6 +591,7 @@ def handle_scroll(e: Event) -> None: Args: e (Event): Scroll event + """ e.preventDefault() print(e.deltaY) From 0a7e60bfb9423fa829a1e012dbe98e0aa7bf66ae Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 01:06:47 +0100 Subject: [PATCH 077/198] Delete history when changing modes. --- packages/editor/main.py | 7 ++++++- packages/editor/scripts/editor.py | 9 ++++++++- pyproject.toml | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/editor/main.py b/packages/editor/main.py index 78f8cfce..f1ec6455 100644 --- a/packages/editor/main.py +++ b/packages/editor/main.py @@ -98,7 +98,12 @@ def change_type(*, mode_value: bool = False) -> None: if global_vars["type_programatically_changed"]: return with ui.dialog() as dialog, ui.card(): - ui.label("Are you sure you want to change the drawing mode? This will clear the canvas.") + ui.label( + """ + Are you sure you want to change the drawing mode? This will clear the canvas. + You will not be able to undo this. + """, + ).style("text-align: center;") with ui.row().style("display: flex; justify-content: space-between; width: 100%;"): ui.button( "Cancel", diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index 79c1bb6a..acdf91a0 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -60,7 +60,7 @@ ctx.lineWidth = 5 ctx.lineCap = "round" ctx.lineJoin = "round" -ctx.font = "50px Brush Script MT" +ctx.font = "50px Arial" # Custom attributes attached so we don't need to use global vars ctx.drawing = False @@ -483,6 +483,11 @@ def type_change(event: Event) -> None: resize(event, keep_content=False) + # As far as I know there's no way to check when we change from pixel to smooth in the history so there's + # no way to switch the modes in the UI. Hence I've decided to just clear the history instead. + ctx.history.clear() + save_history() + @when("reset", "body") def reset_board(_: Event) -> None: @@ -564,6 +569,7 @@ def resize(_: Event, keep_content: dict | bool = True) -> None: # noqa: FBT001, ctx.lineWidth = line_width ctx.strokeStyle = stroke_style + ctx.fillStyle = stroke_style ctx.imageSmoothingEnabled = False ctx.lineCap = "round" @@ -580,6 +586,7 @@ def resize(_: Event, keep_content: dict | bool = True) -> None: # noqa: FBT001, buffer_ctx.imageSmoothingEnabled = False buffer_ctx.strokeStyle = stroke_style buffer_ctx.lineWidth = line_width + buffer_ctx.fillStyle = stroke_style buffer_ctx.lineCap = "round" buffer_ctx.lineJoin = "round" buffer_ctx.font = font diff --git a/pyproject.toml b/pyproject.toml index 1dbccb71..e89baa61 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ description = "A little app" authors = [ { name = "Matiiss", email = "matiiss@matiiss.com" }, { name = "PiLogic" }, - { name = "HiPeople21" }, + { name = "HiPeople21", email = "hipeople3.14159@gmail.com" }, { name = "Sergio Díaz-Esparza" }, { name = "Alan Manning" }, { name = "Aadil Goyal" }, From 9365558d4cebebe3b5c810b74f475170becd5e4c Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 01:08:06 +0100 Subject: [PATCH 078/198] Add dependency to packages/editor/pyproject.toml --- packages/editor/pyproject.toml | 4 +- uv.lock | 1090 +++++++++++++++++++++++++++----- 2 files changed, 918 insertions(+), 176 deletions(-) diff --git a/packages/editor/pyproject.toml b/packages/editor/pyproject.toml index e5766e22..233e1071 100644 --- a/packages/editor/pyproject.toml +++ b/packages/editor/pyproject.toml @@ -4,4 +4,6 @@ version = "0.1.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" -dependencies = [] +dependencies = [ + "nicegui>=2.22.2", +] diff --git a/uv.lock b/uv.lock index d277ff83..b8ecb4d1 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 1 +revision = 3 requires-python = ">=3.12" [manifest] @@ -10,13 +10,95 @@ members = [ "insert-catchy-name-here", ] +[[package]] +name = "aiofiles" +version = "24.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/03/a88171e277e8caa88a4c77808c20ebb04ba74cc4681bf1e9416c862de237/aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c", size = 30247, upload-time = "2024-06-24T11:02:03.584Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a5/45/30bb92d442636f570cb5651bc661f52b610e2eec3f891a5dc3a4c3667db0/aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5", size = 15896, upload-time = "2024-06-24T11:02:01.529Z" }, +] + +[[package]] +name = "aiohappyeyeballs" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/30/f84a107a9c4331c14b2b586036f40965c128aa4fee4dda5d3d51cb14ad54/aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558", size = 22760, upload-time = "2025-03-12T01:42:48.764Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/15/5bf3b99495fb160b63f95972b81750f18f7f4e02ad051373b669d17d44f2/aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8", size = 15265, upload-time = "2025-03-12T01:42:47.083Z" }, +] + +[[package]] +name = "aiohttp" +version = "3.12.15" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiohappyeyeballs" }, + { name = "aiosignal" }, + { name = "attrs" }, + { name = "frozenlist" }, + { name = "multidict" }, + { name = "propcache" }, + { name = "yarl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/e7/d92a237d8802ca88483906c388f7c201bbe96cd80a165ffd0ac2f6a8d59f/aiohttp-3.12.15.tar.gz", hash = "sha256:4fc61385e9c98d72fcdf47e6dd81833f47b2f77c114c29cd64a361be57a763a2", size = 7823716, upload-time = "2025-07-29T05:52:32.215Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/97/77cb2450d9b35f517d6cf506256bf4f5bda3f93a66b4ad64ba7fc917899c/aiohttp-3.12.15-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:802d3868f5776e28f7bf69d349c26fc0efadb81676d0afa88ed00d98a26340b7", size = 702333, upload-time = "2025-07-29T05:50:46.507Z" }, + { url = "https://files.pythonhosted.org/packages/83/6d/0544e6b08b748682c30b9f65640d006e51f90763b41d7c546693bc22900d/aiohttp-3.12.15-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2800614cd560287be05e33a679638e586a2d7401f4ddf99e304d98878c29444", size = 476948, upload-time = "2025-07-29T05:50:48.067Z" }, + { url = "https://files.pythonhosted.org/packages/3a/1d/c8c40e611e5094330284b1aea8a4b02ca0858f8458614fa35754cab42b9c/aiohttp-3.12.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8466151554b593909d30a0a125d638b4e5f3836e5aecde85b66b80ded1cb5b0d", size = 469787, upload-time = "2025-07-29T05:50:49.669Z" }, + { url = "https://files.pythonhosted.org/packages/38/7d/b76438e70319796bfff717f325d97ce2e9310f752a267bfdf5192ac6082b/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e5a495cb1be69dae4b08f35a6c4579c539e9b5706f606632102c0f855bcba7c", size = 1716590, upload-time = "2025-07-29T05:50:51.368Z" }, + { url = "https://files.pythonhosted.org/packages/79/b1/60370d70cdf8b269ee1444b390cbd72ce514f0d1cd1a715821c784d272c9/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6404dfc8cdde35c69aaa489bb3542fb86ef215fc70277c892be8af540e5e21c0", size = 1699241, upload-time = "2025-07-29T05:50:53.628Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2b/4968a7b8792437ebc12186db31523f541943e99bda8f30335c482bea6879/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ead1c00f8521a5c9070fcb88f02967b1d8a0544e6d85c253f6968b785e1a2ab", size = 1754335, upload-time = "2025-07-29T05:50:55.394Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c1/49524ed553f9a0bec1a11fac09e790f49ff669bcd14164f9fab608831c4d/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6990ef617f14450bc6b34941dba4f12d5613cbf4e33805932f853fbd1cf18bfb", size = 1800491, upload-time = "2025-07-29T05:50:57.202Z" }, + { url = "https://files.pythonhosted.org/packages/de/5e/3bf5acea47a96a28c121b167f5ef659cf71208b19e52a88cdfa5c37f1fcc/aiohttp-3.12.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd736ed420f4db2b8148b52b46b88ed038d0354255f9a73196b7bbce3ea97545", size = 1719929, upload-time = "2025-07-29T05:50:59.192Z" }, + { url = "https://files.pythonhosted.org/packages/39/94/8ae30b806835bcd1cba799ba35347dee6961a11bd507db634516210e91d8/aiohttp-3.12.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c5092ce14361a73086b90c6efb3948ffa5be2f5b6fbcf52e8d8c8b8848bb97c", size = 1635733, upload-time = "2025-07-29T05:51:01.394Z" }, + { url = "https://files.pythonhosted.org/packages/7a/46/06cdef71dd03acd9da7f51ab3a9107318aee12ad38d273f654e4f981583a/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:aaa2234bb60c4dbf82893e934d8ee8dea30446f0647e024074237a56a08c01bd", size = 1696790, upload-time = "2025-07-29T05:51:03.657Z" }, + { url = "https://files.pythonhosted.org/packages/02/90/6b4cfaaf92ed98d0ec4d173e78b99b4b1a7551250be8937d9d67ecb356b4/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6d86a2fbdd14192e2f234a92d3b494dd4457e683ba07e5905a0b3ee25389ac9f", size = 1718245, upload-time = "2025-07-29T05:51:05.911Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e6/2593751670fa06f080a846f37f112cbe6f873ba510d070136a6ed46117c6/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a041e7e2612041a6ddf1c6a33b883be6a421247c7afd47e885969ee4cc58bd8d", size = 1658899, upload-time = "2025-07-29T05:51:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/8f/28/c15bacbdb8b8eb5bf39b10680d129ea7410b859e379b03190f02fa104ffd/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5015082477abeafad7203757ae44299a610e89ee82a1503e3d4184e6bafdd519", size = 1738459, upload-time = "2025-07-29T05:51:09.56Z" }, + { url = "https://files.pythonhosted.org/packages/00/de/c269cbc4faa01fb10f143b1670633a8ddd5b2e1ffd0548f7aa49cb5c70e2/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56822ff5ddfd1b745534e658faba944012346184fbfe732e0d6134b744516eea", size = 1766434, upload-time = "2025-07-29T05:51:11.423Z" }, + { url = "https://files.pythonhosted.org/packages/52/b0/4ff3abd81aa7d929b27d2e1403722a65fc87b763e3a97b3a2a494bfc63bc/aiohttp-3.12.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b2acbbfff69019d9014508c4ba0401822e8bae5a5fdc3b6814285b71231b60f3", size = 1726045, upload-time = "2025-07-29T05:51:13.689Z" }, + { url = "https://files.pythonhosted.org/packages/71/16/949225a6a2dd6efcbd855fbd90cf476052e648fb011aa538e3b15b89a57a/aiohttp-3.12.15-cp312-cp312-win32.whl", hash = "sha256:d849b0901b50f2185874b9a232f38e26b9b3d4810095a7572eacea939132d4e1", size = 423591, upload-time = "2025-07-29T05:51:15.452Z" }, + { url = "https://files.pythonhosted.org/packages/2b/d8/fa65d2a349fe938b76d309db1a56a75c4fb8cc7b17a398b698488a939903/aiohttp-3.12.15-cp312-cp312-win_amd64.whl", hash = "sha256:b390ef5f62bb508a9d67cb3bba9b8356e23b3996da7062f1a57ce1a79d2b3d34", size = 450266, upload-time = "2025-07-29T05:51:17.239Z" }, + { url = "https://files.pythonhosted.org/packages/f2/33/918091abcf102e39d15aba2476ad9e7bd35ddb190dcdd43a854000d3da0d/aiohttp-3.12.15-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9f922ffd05034d439dde1c77a20461cf4a1b0831e6caa26151fe7aa8aaebc315", size = 696741, upload-time = "2025-07-29T05:51:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/b5/2a/7495a81e39a998e400f3ecdd44a62107254803d1681d9189be5c2e4530cd/aiohttp-3.12.15-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2ee8a8ac39ce45f3e55663891d4b1d15598c157b4d494a4613e704c8b43112cd", size = 474407, upload-time = "2025-07-29T05:51:21.165Z" }, + { url = "https://files.pythonhosted.org/packages/49/fc/a9576ab4be2dcbd0f73ee8675d16c707cfc12d5ee80ccf4015ba543480c9/aiohttp-3.12.15-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3eae49032c29d356b94eee45a3f39fdf4b0814b397638c2f718e96cfadf4c4e4", size = 466703, upload-time = "2025-07-29T05:51:22.948Z" }, + { url = "https://files.pythonhosted.org/packages/09/2f/d4bcc8448cf536b2b54eed48f19682031ad182faa3a3fee54ebe5b156387/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97752ff12cc12f46a9b20327104448042fce5c33a624f88c18f66f9368091c7", size = 1705532, upload-time = "2025-07-29T05:51:25.211Z" }, + { url = "https://files.pythonhosted.org/packages/f1/f3/59406396083f8b489261e3c011aa8aee9df360a96ac8fa5c2e7e1b8f0466/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:894261472691d6fe76ebb7fcf2e5870a2ac284c7406ddc95823c8598a1390f0d", size = 1686794, upload-time = "2025-07-29T05:51:27.145Z" }, + { url = "https://files.pythonhosted.org/packages/dc/71/164d194993a8d114ee5656c3b7ae9c12ceee7040d076bf7b32fb98a8c5c6/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5fa5d9eb82ce98959fc1031c28198b431b4d9396894f385cb63f1e2f3f20ca6b", size = 1738865, upload-time = "2025-07-29T05:51:29.366Z" }, + { url = "https://files.pythonhosted.org/packages/1c/00/d198461b699188a93ead39cb458554d9f0f69879b95078dce416d3209b54/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0fa751efb11a541f57db59c1dd821bec09031e01452b2b6217319b3a1f34f3d", size = 1788238, upload-time = "2025-07-29T05:51:31.285Z" }, + { url = "https://files.pythonhosted.org/packages/85/b8/9e7175e1fa0ac8e56baa83bf3c214823ce250d0028955dfb23f43d5e61fd/aiohttp-3.12.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5346b93e62ab51ee2a9d68e8f73c7cf96ffb73568a23e683f931e52450e4148d", size = 1710566, upload-time = "2025-07-29T05:51:33.219Z" }, + { url = "https://files.pythonhosted.org/packages/59/e4/16a8eac9df39b48ae102ec030fa9f726d3570732e46ba0c592aeeb507b93/aiohttp-3.12.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:049ec0360f939cd164ecbfd2873eaa432613d5e77d6b04535e3d1fbae5a9e645", size = 1624270, upload-time = "2025-07-29T05:51:35.195Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f8/cd84dee7b6ace0740908fd0af170f9fab50c2a41ccbc3806aabcb1050141/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b52dcf013b57464b6d1e51b627adfd69a8053e84b7103a7cd49c030f9ca44461", size = 1677294, upload-time = "2025-07-29T05:51:37.215Z" }, + { url = "https://files.pythonhosted.org/packages/ce/42/d0f1f85e50d401eccd12bf85c46ba84f947a84839c8a1c2c5f6e8ab1eb50/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:9b2af240143dd2765e0fb661fd0361a1b469cab235039ea57663cda087250ea9", size = 1708958, upload-time = "2025-07-29T05:51:39.328Z" }, + { url = "https://files.pythonhosted.org/packages/d5/6b/f6fa6c5790fb602538483aa5a1b86fcbad66244997e5230d88f9412ef24c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ac77f709a2cde2cc71257ab2d8c74dd157c67a0558a0d2799d5d571b4c63d44d", size = 1651553, upload-time = "2025-07-29T05:51:41.356Z" }, + { url = "https://files.pythonhosted.org/packages/04/36/a6d36ad545fa12e61d11d1932eef273928b0495e6a576eb2af04297fdd3c/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:47f6b962246f0a774fbd3b6b7be25d59b06fdb2f164cf2513097998fc6a29693", size = 1727688, upload-time = "2025-07-29T05:51:43.452Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c8/f195e5e06608a97a4e52c5d41c7927301bf757a8e8bb5bbf8cef6c314961/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:760fb7db442f284996e39cf9915a94492e1896baac44f06ae551974907922b64", size = 1761157, upload-time = "2025-07-29T05:51:45.643Z" }, + { url = "https://files.pythonhosted.org/packages/05/6a/ea199e61b67f25ba688d3ce93f63b49b0a4e3b3d380f03971b4646412fc6/aiohttp-3.12.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad702e57dc385cae679c39d318def49aef754455f237499d5b99bea4ef582e51", size = 1710050, upload-time = "2025-07-29T05:51:48.203Z" }, + { url = "https://files.pythonhosted.org/packages/b4/2e/ffeb7f6256b33635c29dbed29a22a723ff2dd7401fff42ea60cf2060abfb/aiohttp-3.12.15-cp313-cp313-win32.whl", hash = "sha256:f813c3e9032331024de2eb2e32a88d86afb69291fbc37a3a3ae81cc9917fb3d0", size = 422647, upload-time = "2025-07-29T05:51:50.718Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8e/78ee35774201f38d5e1ba079c9958f7629b1fd079459aea9467441dbfbf5/aiohttp-3.12.15-cp313-cp313-win_amd64.whl", hash = "sha256:1a649001580bdb37c6fdb1bebbd7e3bc688e8ec2b5c6f52edbb664662b17dc84", size = 449067, upload-time = "2025-07-29T05:51:52.549Z" }, +] + +[[package]] +name = "aiosignal" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "frozenlist" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/62/06741b579156360248d1ec624842ad0edf697050bbaf7c3e46394e106ad1/aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7", size = 25007, upload-time = "2025-07-03T22:54:43.528Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fb/76/641ae371508676492379f16e2fa48f4e2c11741bd63c48be4b12a6b09cba/aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e", size = 7490, upload-time = "2025-07-03T22:54:42.156Z" }, +] + [[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 } +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 }, + { 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]] @@ -28,9 +110,18 @@ dependencies = [ { name = "sniffio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252 } +sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252, upload-time = "2025-08-04T08:54:26.451Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" }, +] + +[[package]] +name = "attrs" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213 }, + { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, ] [[package]] @@ -54,22 +145,31 @@ requires-dist = [ { name = "uvicorn", specifier = ">=0.35.0" }, ] +[[package]] +name = "bidict" +version = "0.23.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/6e/026678aa5a830e07cd9498a05d3e7e650a4f56a42f267a53d22bcda1bdc9/bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71", size = 29093, upload-time = "2024-02-18T19:09:05.748Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/37/e8730c3587a65eb5645d4aba2d27aae48e8003614d6aaf15dda67f702f1f/bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5", size = 32764, upload-time = "2024-02-18T19:09:04.156Z" }, +] + [[package]] name = "certifi" version = "2025.8.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386 } +sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216 }, + { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, ] [[package]] name = "cfgv" version = "3.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114 } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 }, + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, ] [[package]] @@ -79,18 +179,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342 } +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215 }, + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, ] [[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 } +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 }, + { 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]] @@ -100,24 +200,39 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5a/d3/8ae2869247df154b64c1884d7346d412fed0c49df84db635aab2d1c40e62/deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff", size = 173788 } +sdist = { url = "https://files.pythonhosted.org/packages/5a/d3/8ae2869247df154b64c1884d7346d412fed0c49df84db635aab2d1c40e62/deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff", size = 173788, upload-time = "2020-04-20T14:23:38.738Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a", size = 11178 }, + { url = "https://files.pythonhosted.org/packages/02/c3/253a89ee03fc9b9682f1541728eb66db7db22148cd94f89ab22528cd1e1b/deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a", size = 11178, upload-time = "2020-04-20T14:23:36.581Z" }, ] [[package]] name = "distlib" version = "0.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605 } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047 }, + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, +] + +[[package]] +name = "docutils" +version = "0.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e9/86/5b41c32ecedcfdb4c77b28b6cb14234f252075f8cdb254531727a35547dd/docutils-0.22.tar.gz", hash = "sha256:ba9d57750e92331ebe7c08a1bbf7a7f8143b86c476acd51528b042216a6aad0f", size = 2277984, upload-time = "2025-07-29T15:20:31.06Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/57/8db39bc5f98f042e0153b1de9fb88e1a409a33cda4dd7f723c2ed71e01f6/docutils-0.22-py3-none-any.whl", hash = "sha256:4ed966a0e96a0477d852f7af31bdcb3adc049fbb35ccba358c2ea8a03287615e", size = 630709, upload-time = "2025-07-29T15:20:28.335Z" }, ] [[package]] name = "editor" version = "0.1.0" source = { virtual = "packages/editor" } +dependencies = [ + { name = "nicegui" }, +] + +[package.metadata] +requires-dist = [{ name = "nicegui", specifier = ">=2.22.2" }] [[package]] name = "fastapi" @@ -128,18 +243,78 @@ dependencies = [ { name = "starlette" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/78/d7/6c8b3bfe33eeffa208183ec037fee0cce9f7f024089ab1c5d12ef04bd27c/fastapi-0.116.1.tar.gz", hash = "sha256:ed52cbf946abfd70c5a0dccb24673f0670deeb517a88b3544d03c2a6bf283143", size = 296485 } +sdist = { url = "https://files.pythonhosted.org/packages/78/d7/6c8b3bfe33eeffa208183ec037fee0cce9f7f024089ab1c5d12ef04bd27c/fastapi-0.116.1.tar.gz", hash = "sha256:ed52cbf946abfd70c5a0dccb24673f0670deeb517a88b3544d03c2a6bf283143", size = 296485, upload-time = "2025-07-11T16:22:32.057Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/47/d63c60f59a59467fda0f93f46335c9d18526d7071f025cb5b89d5353ea42/fastapi-0.116.1-py3-none-any.whl", hash = "sha256:c46ac7c312df840f0c9e220f7964bada936781bc4e2e6eb71f1c4d7553786565", size = 95631 }, + { url = "https://files.pythonhosted.org/packages/e5/47/d63c60f59a59467fda0f93f46335c9d18526d7071f025cb5b89d5353ea42/fastapi-0.116.1-py3-none-any.whl", hash = "sha256:c46ac7c312df840f0c9e220f7964bada936781bc4e2e6eb71f1c4d7553786565", size = 95631, upload-time = "2025-07-11T16:22:30.485Z" }, ] [[package]] name = "filelock" version = "3.18.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075 } +sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, +] + +[[package]] +name = "frozenlist" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/79/b1/b64018016eeb087db503b038296fd782586432b9c077fc5c7839e9cb6ef6/frozenlist-1.7.0.tar.gz", hash = "sha256:2e310d81923c2437ea8670467121cc3e9b0f76d3043cc1d2331d56c7fb7a3a8f", size = 45078, upload-time = "2025-06-09T23:02:35.538Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215 }, + { url = "https://files.pythonhosted.org/packages/ef/a2/c8131383f1e66adad5f6ecfcce383d584ca94055a34d683bbb24ac5f2f1c/frozenlist-1.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3dbf9952c4bb0e90e98aec1bd992b3318685005702656bc6f67c1a32b76787f2", size = 81424, upload-time = "2025-06-09T23:00:42.24Z" }, + { url = "https://files.pythonhosted.org/packages/4c/9d/02754159955088cb52567337d1113f945b9e444c4960771ea90eb73de8db/frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f5906d3359300b8a9bb194239491122e6cf1444c2efb88865426f170c262cdb", size = 47952, upload-time = "2025-06-09T23:00:43.481Z" }, + { url = "https://files.pythonhosted.org/packages/01/7a/0046ef1bd6699b40acd2067ed6d6670b4db2f425c56980fa21c982c2a9db/frozenlist-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3dabd5a8f84573c8d10d8859a50ea2dec01eea372031929871368c09fa103478", size = 46688, upload-time = "2025-06-09T23:00:44.793Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a2/a910bafe29c86997363fb4c02069df4ff0b5bc39d33c5198b4e9dd42d8f8/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa57daa5917f1738064f302bf2626281a1cb01920c32f711fbc7bc36111058a8", size = 243084, upload-time = "2025-06-09T23:00:46.125Z" }, + { url = "https://files.pythonhosted.org/packages/64/3e/5036af9d5031374c64c387469bfcc3af537fc0f5b1187d83a1cf6fab1639/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c193dda2b6d49f4c4398962810fa7d7c78f032bf45572b3e04dd5249dff27e08", size = 233524, upload-time = "2025-06-09T23:00:47.73Z" }, + { url = "https://files.pythonhosted.org/packages/06/39/6a17b7c107a2887e781a48ecf20ad20f1c39d94b2a548c83615b5b879f28/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe2b675cf0aaa6d61bf8fbffd3c274b3c9b7b1623beb3809df8a81399a4a9c4", size = 248493, upload-time = "2025-06-09T23:00:49.742Z" }, + { url = "https://files.pythonhosted.org/packages/be/00/711d1337c7327d88c44d91dd0f556a1c47fb99afc060ae0ef66b4d24793d/frozenlist-1.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8fc5d5cda37f62b262405cf9652cf0856839c4be8ee41be0afe8858f17f4c94b", size = 244116, upload-time = "2025-06-09T23:00:51.352Z" }, + { url = "https://files.pythonhosted.org/packages/24/fe/74e6ec0639c115df13d5850e75722750adabdc7de24e37e05a40527ca539/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d5ce521d1dd7d620198829b87ea002956e4319002ef0bc8d3e6d045cb4646e", size = 224557, upload-time = "2025-06-09T23:00:52.855Z" }, + { url = "https://files.pythonhosted.org/packages/8d/db/48421f62a6f77c553575201e89048e97198046b793f4a089c79a6e3268bd/frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488d0a7d6a0008ca0db273c542098a0fa9e7dfaa7e57f70acef43f32b3f69dca", size = 241820, upload-time = "2025-06-09T23:00:54.43Z" }, + { url = "https://files.pythonhosted.org/packages/1d/fa/cb4a76bea23047c8462976ea7b7a2bf53997a0ca171302deae9d6dd12096/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:15a7eaba63983d22c54d255b854e8108e7e5f3e89f647fc854bd77a237e767df", size = 236542, upload-time = "2025-06-09T23:00:56.409Z" }, + { url = "https://files.pythonhosted.org/packages/5d/32/476a4b5cfaa0ec94d3f808f193301debff2ea42288a099afe60757ef6282/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1eaa7e9c6d15df825bf255649e05bd8a74b04a4d2baa1ae46d9c2d00b2ca2cb5", size = 249350, upload-time = "2025-06-09T23:00:58.468Z" }, + { url = "https://files.pythonhosted.org/packages/8d/ba/9a28042f84a6bf8ea5dbc81cfff8eaef18d78b2a1ad9d51c7bc5b029ad16/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4389e06714cfa9d47ab87f784a7c5be91d3934cd6e9a7b85beef808297cc025", size = 225093, upload-time = "2025-06-09T23:01:00.015Z" }, + { url = "https://files.pythonhosted.org/packages/bc/29/3a32959e68f9cf000b04e79ba574527c17e8842e38c91d68214a37455786/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:73bd45e1488c40b63fe5a7df892baf9e2a4d4bb6409a2b3b78ac1c6236178e01", size = 245482, upload-time = "2025-06-09T23:01:01.474Z" }, + { url = "https://files.pythonhosted.org/packages/80/e8/edf2f9e00da553f07f5fa165325cfc302dead715cab6ac8336a5f3d0adc2/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99886d98e1643269760e5fe0df31e5ae7050788dd288947f7f007209b8c33f08", size = 249590, upload-time = "2025-06-09T23:01:02.961Z" }, + { url = "https://files.pythonhosted.org/packages/1c/80/9a0eb48b944050f94cc51ee1c413eb14a39543cc4f760ed12657a5a3c45a/frozenlist-1.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:290a172aae5a4c278c6da8a96222e6337744cd9c77313efe33d5670b9f65fc43", size = 237785, upload-time = "2025-06-09T23:01:05.095Z" }, + { url = "https://files.pythonhosted.org/packages/f3/74/87601e0fb0369b7a2baf404ea921769c53b7ae00dee7dcfe5162c8c6dbf0/frozenlist-1.7.0-cp312-cp312-win32.whl", hash = "sha256:426c7bc70e07cfebc178bc4c2bf2d861d720c4fff172181eeb4a4c41d4ca2ad3", size = 39487, upload-time = "2025-06-09T23:01:06.54Z" }, + { url = "https://files.pythonhosted.org/packages/0b/15/c026e9a9fc17585a9d461f65d8593d281fedf55fbf7eb53f16c6df2392f9/frozenlist-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:563b72efe5da92e02eb68c59cb37205457c977aa7a449ed1b37e6939e5c47c6a", size = 43874, upload-time = "2025-06-09T23:01:07.752Z" }, + { url = "https://files.pythonhosted.org/packages/24/90/6b2cebdabdbd50367273c20ff6b57a3dfa89bd0762de02c3a1eb42cb6462/frozenlist-1.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee80eeda5e2a4e660651370ebffd1286542b67e268aa1ac8d6dbe973120ef7ee", size = 79791, upload-time = "2025-06-09T23:01:09.368Z" }, + { url = "https://files.pythonhosted.org/packages/83/2e/5b70b6a3325363293fe5fc3ae74cdcbc3e996c2a11dde2fd9f1fb0776d19/frozenlist-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d1a81c85417b914139e3a9b995d4a1c84559afc839a93cf2cb7f15e6e5f6ed2d", size = 47165, upload-time = "2025-06-09T23:01:10.653Z" }, + { url = "https://files.pythonhosted.org/packages/f4/25/a0895c99270ca6966110f4ad98e87e5662eab416a17e7fd53c364bf8b954/frozenlist-1.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cbb65198a9132ebc334f237d7b0df163e4de83fb4f2bdfe46c1e654bdb0c5d43", size = 45881, upload-time = "2025-06-09T23:01:12.296Z" }, + { url = "https://files.pythonhosted.org/packages/19/7c/71bb0bbe0832793c601fff68cd0cf6143753d0c667f9aec93d3c323f4b55/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dab46c723eeb2c255a64f9dc05b8dd601fde66d6b19cdb82b2e09cc6ff8d8b5d", size = 232409, upload-time = "2025-06-09T23:01:13.641Z" }, + { url = "https://files.pythonhosted.org/packages/c0/45/ed2798718910fe6eb3ba574082aaceff4528e6323f9a8570be0f7028d8e9/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6aeac207a759d0dedd2e40745575ae32ab30926ff4fa49b1635def65806fddee", size = 225132, upload-time = "2025-06-09T23:01:15.264Z" }, + { url = "https://files.pythonhosted.org/packages/ba/e2/8417ae0f8eacb1d071d4950f32f229aa6bf68ab69aab797b72a07ea68d4f/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bd8c4e58ad14b4fa7802b8be49d47993182fdd4023393899632c88fd8cd994eb", size = 237638, upload-time = "2025-06-09T23:01:16.752Z" }, + { url = "https://files.pythonhosted.org/packages/f8/b7/2ace5450ce85f2af05a871b8c8719b341294775a0a6c5585d5e6170f2ce7/frozenlist-1.7.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04fb24d104f425da3540ed83cbfc31388a586a7696142004c577fa61c6298c3f", size = 233539, upload-time = "2025-06-09T23:01:18.202Z" }, + { url = "https://files.pythonhosted.org/packages/46/b9/6989292c5539553dba63f3c83dc4598186ab2888f67c0dc1d917e6887db6/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a5c505156368e4ea6b53b5ac23c92d7edc864537ff911d2fb24c140bb175e60", size = 215646, upload-time = "2025-06-09T23:01:19.649Z" }, + { url = "https://files.pythonhosted.org/packages/72/31/bc8c5c99c7818293458fe745dab4fd5730ff49697ccc82b554eb69f16a24/frozenlist-1.7.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bd7eb96a675f18aa5c553eb7ddc24a43c8c18f22e1f9925528128c052cdbe00", size = 232233, upload-time = "2025-06-09T23:01:21.175Z" }, + { url = "https://files.pythonhosted.org/packages/59/52/460db4d7ba0811b9ccb85af996019f5d70831f2f5f255f7cc61f86199795/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:05579bf020096fe05a764f1f84cd104a12f78eaab68842d036772dc6d4870b4b", size = 227996, upload-time = "2025-06-09T23:01:23.098Z" }, + { url = "https://files.pythonhosted.org/packages/ba/c9/f4b39e904c03927b7ecf891804fd3b4df3db29b9e487c6418e37988d6e9d/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:376b6222d114e97eeec13d46c486facd41d4f43bab626b7c3f6a8b4e81a5192c", size = 242280, upload-time = "2025-06-09T23:01:24.808Z" }, + { url = "https://files.pythonhosted.org/packages/b8/33/3f8d6ced42f162d743e3517781566b8481322be321b486d9d262adf70bfb/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0aa7e176ebe115379b5b1c95b4096fb1c17cce0847402e227e712c27bdb5a949", size = 217717, upload-time = "2025-06-09T23:01:26.28Z" }, + { url = "https://files.pythonhosted.org/packages/3e/e8/ad683e75da6ccef50d0ab0c2b2324b32f84fc88ceee778ed79b8e2d2fe2e/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3fbba20e662b9c2130dc771e332a99eff5da078b2b2648153a40669a6d0e36ca", size = 236644, upload-time = "2025-06-09T23:01:27.887Z" }, + { url = "https://files.pythonhosted.org/packages/b2/14/8d19ccdd3799310722195a72ac94ddc677541fb4bef4091d8e7775752360/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f3f4410a0a601d349dd406b5713fec59b4cee7e71678d5b17edda7f4655a940b", size = 238879, upload-time = "2025-06-09T23:01:29.524Z" }, + { url = "https://files.pythonhosted.org/packages/ce/13/c12bf657494c2fd1079a48b2db49fa4196325909249a52d8f09bc9123fd7/frozenlist-1.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e2cdfaaec6a2f9327bf43c933c0319a7c429058e8537c508964a133dffee412e", size = 232502, upload-time = "2025-06-09T23:01:31.287Z" }, + { url = "https://files.pythonhosted.org/packages/d7/8b/e7f9dfde869825489382bc0d512c15e96d3964180c9499efcec72e85db7e/frozenlist-1.7.0-cp313-cp313-win32.whl", hash = "sha256:5fc4df05a6591c7768459caba1b342d9ec23fa16195e744939ba5914596ae3e1", size = 39169, upload-time = "2025-06-09T23:01:35.503Z" }, + { url = "https://files.pythonhosted.org/packages/35/89/a487a98d94205d85745080a37860ff5744b9820a2c9acbcdd9440bfddf98/frozenlist-1.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:52109052b9791a3e6b5d1b65f4b909703984b770694d3eb64fad124c835d7cba", size = 43219, upload-time = "2025-06-09T23:01:36.784Z" }, + { url = "https://files.pythonhosted.org/packages/56/d5/5c4cf2319a49eddd9dd7145e66c4866bdc6f3dbc67ca3d59685149c11e0d/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a6f86e4193bb0e235ef6ce3dde5cbabed887e0b11f516ce8a0f4d3b33078ec2d", size = 84345, upload-time = "2025-06-09T23:01:38.295Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/ec2c1e1dc16b85bc9d526009961953df9cec8481b6886debb36ec9107799/frozenlist-1.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:82d664628865abeb32d90ae497fb93df398a69bb3434463d172b80fc25b0dd7d", size = 48880, upload-time = "2025-06-09T23:01:39.887Z" }, + { url = "https://files.pythonhosted.org/packages/69/86/f9596807b03de126e11e7d42ac91e3d0b19a6599c714a1989a4e85eeefc4/frozenlist-1.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:912a7e8375a1c9a68325a902f3953191b7b292aa3c3fb0d71a216221deca460b", size = 48498, upload-time = "2025-06-09T23:01:41.318Z" }, + { url = "https://files.pythonhosted.org/packages/5e/cb/df6de220f5036001005f2d726b789b2c0b65f2363b104bbc16f5be8084f8/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9537c2777167488d539bc5de2ad262efc44388230e5118868e172dd4a552b146", size = 292296, upload-time = "2025-06-09T23:01:42.685Z" }, + { url = "https://files.pythonhosted.org/packages/83/1f/de84c642f17c8f851a2905cee2dae401e5e0daca9b5ef121e120e19aa825/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f34560fb1b4c3e30ba35fa9a13894ba39e5acfc5f60f57d8accde65f46cc5e74", size = 273103, upload-time = "2025-06-09T23:01:44.166Z" }, + { url = "https://files.pythonhosted.org/packages/88/3c/c840bfa474ba3fa13c772b93070893c6e9d5c0350885760376cbe3b6c1b3/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:acd03d224b0175f5a850edc104ac19040d35419eddad04e7cf2d5986d98427f1", size = 292869, upload-time = "2025-06-09T23:01:45.681Z" }, + { url = "https://files.pythonhosted.org/packages/a6/1c/3efa6e7d5a39a1d5ef0abeb51c48fb657765794a46cf124e5aca2c7a592c/frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2038310bc582f3d6a09b3816ab01737d60bf7b1ec70f5356b09e84fb7408ab1", size = 291467, upload-time = "2025-06-09T23:01:47.234Z" }, + { url = "https://files.pythonhosted.org/packages/4f/00/d5c5e09d4922c395e2f2f6b79b9a20dab4b67daaf78ab92e7729341f61f6/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8c05e4c8e5f36e5e088caa1bf78a687528f83c043706640a92cb76cd6999384", size = 266028, upload-time = "2025-06-09T23:01:48.819Z" }, + { url = "https://files.pythonhosted.org/packages/4e/27/72765be905619dfde25a7f33813ac0341eb6b076abede17a2e3fbfade0cb/frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:765bb588c86e47d0b68f23c1bee323d4b703218037765dcf3f25c838c6fecceb", size = 284294, upload-time = "2025-06-09T23:01:50.394Z" }, + { url = "https://files.pythonhosted.org/packages/88/67/c94103a23001b17808eb7dd1200c156bb69fb68e63fcf0693dde4cd6228c/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:32dc2e08c67d86d0969714dd484fd60ff08ff81d1a1e40a77dd34a387e6ebc0c", size = 281898, upload-time = "2025-06-09T23:01:52.234Z" }, + { url = "https://files.pythonhosted.org/packages/42/34/a3e2c00c00f9e2a9db5653bca3fec306349e71aff14ae45ecc6d0951dd24/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:c0303e597eb5a5321b4de9c68e9845ac8f290d2ab3f3e2c864437d3c5a30cd65", size = 290465, upload-time = "2025-06-09T23:01:53.788Z" }, + { url = "https://files.pythonhosted.org/packages/bb/73/f89b7fbce8b0b0c095d82b008afd0590f71ccb3dee6eee41791cf8cd25fd/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a47f2abb4e29b3a8d0b530f7c3598badc6b134562b1a5caee867f7c62fee51e3", size = 266385, upload-time = "2025-06-09T23:01:55.769Z" }, + { url = "https://files.pythonhosted.org/packages/cd/45/e365fdb554159462ca12df54bc59bfa7a9a273ecc21e99e72e597564d1ae/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3d688126c242a6fabbd92e02633414d40f50bb6002fa4cf995a1d18051525657", size = 288771, upload-time = "2025-06-09T23:01:57.4Z" }, + { url = "https://files.pythonhosted.org/packages/00/11/47b6117002a0e904f004d70ec5194fe9144f117c33c851e3d51c765962d0/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:4e7e9652b3d367c7bd449a727dc79d5043f48b88d0cbfd4f9f1060cf2b414104", size = 288206, upload-time = "2025-06-09T23:01:58.936Z" }, + { url = "https://files.pythonhosted.org/packages/40/37/5f9f3c3fd7f7746082ec67bcdc204db72dad081f4f83a503d33220a92973/frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1a85e345b4c43db8b842cab1feb41be5cc0b10a1830e6295b69d7310f99becaf", size = 282620, upload-time = "2025-06-09T23:02:00.493Z" }, + { url = "https://files.pythonhosted.org/packages/0b/31/8fbc5af2d183bff20f21aa743b4088eac4445d2bb1cdece449ae80e4e2d1/frozenlist-1.7.0-cp313-cp313t-win32.whl", hash = "sha256:3a14027124ddb70dfcee5148979998066897e79f89f64b13328595c4bdf77c81", size = 43059, upload-time = "2025-06-09T23:02:02.072Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ed/41956f52105b8dbc26e457c5705340c67c8cc2b79f394b79bffc09d0e938/frozenlist-1.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3bf8010d71d4507775f658e9823210b7427be36625b387221642725b515dcf3e", size = 47516, upload-time = "2025-06-09T23:02:03.779Z" }, + { url = "https://files.pythonhosted.org/packages/ee/45/b82e3c16be2182bff01179db177fe144d58b5dc787a7d4492c6ed8b9317f/frozenlist-1.7.0-py3-none-any.whl", hash = "sha256:9a5af342e34f7e97caf8c995864c7a396418ae2859cc6fdf1b1073020d516a7e", size = 13106, upload-time = "2025-06-09T23:02:34.204Z" }, ] [[package]] @@ -156,18 +331,18 @@ dependencies = [ { name = "pydantic" }, { name = "pyjwt" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fe/67/ae47f68daae1bbb56a9fbf960dfb7d08b3dec52a6ad1e96f69c2ba5b3116/gotrue-2.12.3.tar.gz", hash = "sha256:f874cf9d0b2f0335bfbd0d6e29e3f7aff79998cd1c14d2ad814db8c06cee3852", size = 38323 } +sdist = { url = "https://files.pythonhosted.org/packages/fe/67/ae47f68daae1bbb56a9fbf960dfb7d08b3dec52a6ad1e96f69c2ba5b3116/gotrue-2.12.3.tar.gz", hash = "sha256:f874cf9d0b2f0335bfbd0d6e29e3f7aff79998cd1c14d2ad814db8c06cee3852", size = 38323, upload-time = "2025-07-04T06:50:03.941Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/fa/4165d298ef89254c9f742faa3f99a61fe6fd3552b4ba44df6924f8d307d7/gotrue-2.12.3-py3-none-any.whl", hash = "sha256:b1a3c6a5fe3f92e854a026c4c19de58706a96fd5fbdcc3d620b2802f6a46a26b", size = 44022 }, + { url = "https://files.pythonhosted.org/packages/42/fa/4165d298ef89254c9f742faa3f99a61fe6fd3552b4ba44df6924f8d307d7/gotrue-2.12.3-py3-none-any.whl", hash = "sha256:b1a3c6a5fe3f92e854a026c4c19de58706a96fd5fbdcc3d620b2802f6a46a26b", size = 44022, upload-time = "2025-07-04T06:50:02.591Z" }, ] [[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 } +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 }, + { 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]] @@ -178,18 +353,18 @@ dependencies = [ { name = "hpack" }, { name = "hyperframe" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1b/38/d7f80fd13e6582fb8e0df8c9a653dcc02b03ca34f4d72f34869298c5baf8/h2-4.2.0.tar.gz", hash = "sha256:c8a52129695e88b1a0578d8d2cc6842bbd79128ac685463b887ee278126ad01f", size = 2150682 } +sdist = { url = "https://files.pythonhosted.org/packages/1b/38/d7f80fd13e6582fb8e0df8c9a653dcc02b03ca34f4d72f34869298c5baf8/h2-4.2.0.tar.gz", hash = "sha256:c8a52129695e88b1a0578d8d2cc6842bbd79128ac685463b887ee278126ad01f", size = 2150682, upload-time = "2025-02-02T07:43:51.815Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/9e/984486f2d0a0bd2b024bf4bc1c62688fcafa9e61991f041fb0e2def4a982/h2-4.2.0-py3-none-any.whl", hash = "sha256:479a53ad425bb29af087f3458a61d30780bc818e4ebcf01f0b536ba916462ed0", size = 60957 }, + { url = "https://files.pythonhosted.org/packages/d0/9e/984486f2d0a0bd2b024bf4bc1c62688fcafa9e61991f041fb0e2def4a982/h2-4.2.0-py3-none-any.whl", hash = "sha256:479a53ad425bb29af087f3458a61d30780bc818e4ebcf01f0b536ba916462ed0", size = 60957, upload-time = "2025-02-01T11:02:26.481Z" }, ] [[package]] name = "hpack" version = "4.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2c/48/71de9ed269fdae9c8057e5a4c0aa7402e8bb16f2c6e90b3aa53327b113f8/hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca", size = 51276 } +sdist = { url = "https://files.pythonhosted.org/packages/2c/48/71de9ed269fdae9c8057e5a4c0aa7402e8bb16f2c6e90b3aa53327b113f8/hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca", size = 51276, upload-time = "2025-01-22T21:44:58.347Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357 }, + { url = "https://files.pythonhosted.org/packages/07/c6/80c95b1b2b94682a72cbdbfb85b81ae2daffa4291fbfa1b1464502ede10d/hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496", size = 34357, upload-time = "2025-01-22T21:44:56.92Z" }, ] [[package]] @@ -200,9 +375,31 @@ dependencies = [ { name = "certifi" }, { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484 } +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784 }, + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httptools" +version = "0.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a7/9a/ce5e1f7e131522e6d3426e8e7a490b3a01f39a6696602e1c4f33f9e94277/httptools-0.6.4.tar.gz", hash = "sha256:4e93eee4add6493b59a5c514da98c939b244fce4a0d8879cd3f466562f4b7d5c", size = 240639, upload-time = "2024-10-16T19:45:08.902Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bb/0e/d0b71465c66b9185f90a091ab36389a7352985fe857e352801c39d6127c8/httptools-0.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:df017d6c780287d5c80601dafa31f17bddb170232d85c066604d8558683711a2", size = 200683, upload-time = "2024-10-16T19:44:30.175Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b8/412a9bb28d0a8988de3296e01efa0bd62068b33856cdda47fe1b5e890954/httptools-0.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:85071a1e8c2d051b507161f6c3e26155b5c790e4e28d7f236422dbacc2a9cc44", size = 104337, upload-time = "2024-10-16T19:44:31.786Z" }, + { url = "https://files.pythonhosted.org/packages/9b/01/6fb20be3196ffdc8eeec4e653bc2a275eca7f36634c86302242c4fbb2760/httptools-0.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69422b7f458c5af875922cdb5bd586cc1f1033295aa9ff63ee196a87519ac8e1", size = 508796, upload-time = "2024-10-16T19:44:32.825Z" }, + { url = "https://files.pythonhosted.org/packages/f7/d8/b644c44acc1368938317d76ac991c9bba1166311880bcc0ac297cb9d6bd7/httptools-0.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16e603a3bff50db08cd578d54f07032ca1631450ceb972c2f834c2b860c28ea2", size = 510837, upload-time = "2024-10-16T19:44:33.974Z" }, + { url = "https://files.pythonhosted.org/packages/52/d8/254d16a31d543073a0e57f1c329ca7378d8924e7e292eda72d0064987486/httptools-0.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec4f178901fa1834d4a060320d2f3abc5c9e39766953d038f1458cb885f47e81", size = 485289, upload-time = "2024-10-16T19:44:35.111Z" }, + { url = "https://files.pythonhosted.org/packages/5f/3c/4aee161b4b7a971660b8be71a92c24d6c64372c1ab3ae7f366b3680df20f/httptools-0.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb89ecf8b290f2e293325c646a211ff1c2493222798bb80a530c5e7502494f", size = 489779, upload-time = "2024-10-16T19:44:36.253Z" }, + { url = "https://files.pythonhosted.org/packages/12/b7/5cae71a8868e555f3f67a50ee7f673ce36eac970f029c0c5e9d584352961/httptools-0.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:db78cb9ca56b59b016e64b6031eda5653be0589dba2b1b43453f6e8b405a0970", size = 88634, upload-time = "2024-10-16T19:44:37.357Z" }, + { url = "https://files.pythonhosted.org/packages/94/a3/9fe9ad23fd35f7de6b91eeb60848986058bd8b5a5c1e256f5860a160cc3e/httptools-0.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ade273d7e767d5fae13fa637f4d53b6e961fb7fd93c7797562663f0171c26660", size = 197214, upload-time = "2024-10-16T19:44:38.738Z" }, + { url = "https://files.pythonhosted.org/packages/ea/d9/82d5e68bab783b632023f2fa31db20bebb4e89dfc4d2293945fd68484ee4/httptools-0.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:856f4bc0478ae143bad54a4242fccb1f3f86a6e1be5548fecfd4102061b3a083", size = 102431, upload-time = "2024-10-16T19:44:39.818Z" }, + { url = "https://files.pythonhosted.org/packages/96/c1/cb499655cbdbfb57b577734fde02f6fa0bbc3fe9fb4d87b742b512908dff/httptools-0.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:322d20ea9cdd1fa98bd6a74b77e2ec5b818abdc3d36695ab402a0de8ef2865a3", size = 473121, upload-time = "2024-10-16T19:44:41.189Z" }, + { url = "https://files.pythonhosted.org/packages/af/71/ee32fd358f8a3bb199b03261f10921716990808a675d8160b5383487a317/httptools-0.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d87b29bd4486c0093fc64dea80231f7c7f7eb4dc70ae394d70a495ab8436071", size = 473805, upload-time = "2024-10-16T19:44:42.384Z" }, + { url = "https://files.pythonhosted.org/packages/8a/0a/0d4df132bfca1507114198b766f1737d57580c9ad1cf93c1ff673e3387be/httptools-0.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:342dd6946aa6bda4b8f18c734576106b8a31f2fe31492881a9a160ec84ff4bd5", size = 448858, upload-time = "2024-10-16T19:44:43.959Z" }, + { url = "https://files.pythonhosted.org/packages/1e/6a/787004fdef2cabea27bad1073bf6a33f2437b4dbd3b6fb4a9d71172b1c7c/httptools-0.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b36913ba52008249223042dca46e69967985fb4051951f94357ea681e1f5dc0", size = 452042, upload-time = "2024-10-16T19:44:45.071Z" }, + { url = "https://files.pythonhosted.org/packages/4d/dc/7decab5c404d1d2cdc1bb330b1bf70e83d6af0396fd4fc76fc60c0d522bf/httptools-0.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:28908df1b9bb8187393d5b5db91435ccc9c8e891657f9cbb42a2541b44c82fc8", size = 87682, upload-time = "2024-10-16T19:44:46.46Z" }, ] [[package]] @@ -215,9 +412,9 @@ dependencies = [ { name = "httpcore" }, { name = "idna" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, ] [package.optional-dependencies] @@ -229,27 +426,36 @@ http2 = [ name = "hyperframe" version = "6.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566 } +sdist = { url = "https://files.pythonhosted.org/packages/02/e7/94f8232d4a74cc99514c13a9f995811485a6903d48e5d952771ef6322e30/hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08", size = 26566, upload-time = "2025-01-22T21:41:49.302Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007 }, + { url = "https://files.pythonhosted.org/packages/48/30/47d0bf6072f7252e6521f3447ccfa40b421b6824517f82854703d0f5a98b/hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5", size = 13007, upload-time = "2025-01-22T21:41:47.295Z" }, ] [[package]] name = "identify" version = "2.6.13" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/ca/ffbabe3635bb839aa36b3a893c91a9b0d368cb4d8073e03a12896970af82/identify-2.6.13.tar.gz", hash = "sha256:da8d6c828e773620e13bfa86ea601c5a5310ba4bcd65edf378198b56a1f9fb32", size = 99243 } +sdist = { url = "https://files.pythonhosted.org/packages/82/ca/ffbabe3635bb839aa36b3a893c91a9b0d368cb4d8073e03a12896970af82/identify-2.6.13.tar.gz", hash = "sha256:da8d6c828e773620e13bfa86ea601c5a5310ba4bcd65edf378198b56a1f9fb32", size = 99243, upload-time = "2025-08-09T19:35:00.6Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/ce/461b60a3ee109518c055953729bf9ed089a04db895d47e95444071dcdef2/identify-2.6.13-py2.py3-none-any.whl", hash = "sha256:60381139b3ae39447482ecc406944190f690d4a2997f2584062089848361b33b", size = 99153 }, + { url = "https://files.pythonhosted.org/packages/e7/ce/461b60a3ee109518c055953729bf9ed089a04db895d47e95444071dcdef2/identify-2.6.13-py2.py3-none-any.whl", hash = "sha256:60381139b3ae39447482ecc406944190f690d4a2997f2584062089848361b33b", size = 99153, upload-time = "2025-08-09T19:34:59.1Z" }, ] [[package]] name = "idna" version = "3.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "ifaddr" +version = "0.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/ac/fb4c578f4a3256561548cd825646680edcadb9440f3f68add95ade1eb791/ifaddr-0.2.0.tar.gz", hash = "sha256:cc0cbfcaabf765d44595825fb96a99bb12c79716b73b44330ea38ee2b0c4aed4", size = 10485, upload-time = "2022-06-15T21:40:27.561Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9c/1f/19ebc343cc71a7ffa78f17018535adc5cbdd87afb31d7c34874680148b32/ifaddr-0.2.0-py3-none-any.whl", hash = "sha256:085e0305cfe6f16ab12d72e2024030f5d52674afad6911bb1eee207177b8a748", size = 12314, upload-time = "2022-06-15T21:40:25.756Z" }, ] [[package]] @@ -271,31 +477,243 @@ dev = [ { name = "ruff", specifier = "~=0.12.2" }, ] +[[package]] +name = "itsdangerous" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, +] + +[[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 = "markdown2" +version = "2.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/42/f8/b2ae8bf5f28f9b510ae097415e6e4cb63226bb28d7ee01aec03a755ba03b/markdown2-2.5.4.tar.gz", hash = "sha256:a09873f0b3c23dbfae589b0080587df52ad75bb09a5fa6559147554736676889", size = 145652, upload-time = "2025-07-27T16:16:24.307Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/06/2697b5043c3ecb720ce0d243fc7cf5024c0b5b1e450506e9b21939019963/markdown2-2.5.4-py3-none-any.whl", hash = "sha256:3c4b2934e677be7fec0e6f2de4410e116681f4ad50ec8e5ba7557be506d3f439", size = 49954, upload-time = "2025-07-27T16:16:23.026Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, +] + +[[package]] +name = "multidict" +version = "6.6.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/69/7f/0652e6ed47ab288e3756ea9c0df8b14950781184d4bd7883f4d87dd41245/multidict-6.6.4.tar.gz", hash = "sha256:d2d4e4787672911b48350df02ed3fa3fffdc2f2e8ca06dd6afdf34189b76a9dd", size = 101843, upload-time = "2025-08-11T12:08:48.217Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/f6/512ffd8fd8b37fb2680e5ac35d788f1d71bbaf37789d21a820bdc441e565/multidict-6.6.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0ffb87be160942d56d7b87b0fdf098e81ed565add09eaa1294268c7f3caac4c8", size = 76516, upload-time = "2025-08-11T12:06:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/99/58/45c3e75deb8855c36bd66cc1658007589662ba584dbf423d01df478dd1c5/multidict-6.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d191de6cbab2aff5de6c5723101705fd044b3e4c7cfd587a1929b5028b9714b3", size = 45394, upload-time = "2025-08-11T12:06:54.555Z" }, + { url = "https://files.pythonhosted.org/packages/fd/ca/e8c4472a93a26e4507c0b8e1f0762c0d8a32de1328ef72fd704ef9cc5447/multidict-6.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:38a0956dd92d918ad5feff3db8fcb4a5eb7dba114da917e1a88475619781b57b", size = 43591, upload-time = "2025-08-11T12:06:55.672Z" }, + { url = "https://files.pythonhosted.org/packages/05/51/edf414f4df058574a7265034d04c935aa84a89e79ce90fcf4df211f47b16/multidict-6.6.4-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6865f6d3b7900ae020b495d599fcf3765653bc927951c1abb959017f81ae8287", size = 237215, upload-time = "2025-08-11T12:06:57.213Z" }, + { url = "https://files.pythonhosted.org/packages/c8/45/8b3d6dbad8cf3252553cc41abea09ad527b33ce47a5e199072620b296902/multidict-6.6.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a2088c126b6f72db6c9212ad827d0ba088c01d951cee25e758c450da732c138", size = 258299, upload-time = "2025-08-11T12:06:58.946Z" }, + { url = "https://files.pythonhosted.org/packages/3c/e8/8ca2e9a9f5a435fc6db40438a55730a4bf4956b554e487fa1b9ae920f825/multidict-6.6.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0f37bed7319b848097085d7d48116f545985db988e2256b2e6f00563a3416ee6", size = 242357, upload-time = "2025-08-11T12:07:00.301Z" }, + { url = "https://files.pythonhosted.org/packages/0f/84/80c77c99df05a75c28490b2af8f7cba2a12621186e0a8b0865d8e745c104/multidict-6.6.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:01368e3c94032ba6ca0b78e7ccb099643466cf24f8dc8eefcfdc0571d56e58f9", size = 268369, upload-time = "2025-08-11T12:07:01.638Z" }, + { url = "https://files.pythonhosted.org/packages/0d/e9/920bfa46c27b05fb3e1ad85121fd49f441492dca2449c5bcfe42e4565d8a/multidict-6.6.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fe323540c255db0bffee79ad7f048c909f2ab0edb87a597e1c17da6a54e493c", size = 269341, upload-time = "2025-08-11T12:07:02.943Z" }, + { url = "https://files.pythonhosted.org/packages/af/65/753a2d8b05daf496f4a9c367fe844e90a1b2cac78e2be2c844200d10cc4c/multidict-6.6.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8eb3025f17b0a4c3cd08cda49acf312a19ad6e8a4edd9dbd591e6506d999402", size = 256100, upload-time = "2025-08-11T12:07:04.564Z" }, + { url = "https://files.pythonhosted.org/packages/09/54/655be13ae324212bf0bc15d665a4e34844f34c206f78801be42f7a0a8aaa/multidict-6.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bbc14f0365534d35a06970d6a83478b249752e922d662dc24d489af1aa0d1be7", size = 253584, upload-time = "2025-08-11T12:07:05.914Z" }, + { url = "https://files.pythonhosted.org/packages/5c/74/ab2039ecc05264b5cec73eb018ce417af3ebb384ae9c0e9ed42cb33f8151/multidict-6.6.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:75aa52fba2d96bf972e85451b99d8e19cc37ce26fd016f6d4aa60da9ab2b005f", size = 251018, upload-time = "2025-08-11T12:07:08.301Z" }, + { url = "https://files.pythonhosted.org/packages/af/0a/ccbb244ac848e56c6427f2392741c06302bbfba49c0042f1eb3c5b606497/multidict-6.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4fefd4a815e362d4f011919d97d7b4a1e566f1dde83dc4ad8cfb5b41de1df68d", size = 251477, upload-time = "2025-08-11T12:07:10.248Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b0/0ed49bba775b135937f52fe13922bc64a7eaf0a3ead84a36e8e4e446e096/multidict-6.6.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:db9801fe021f59a5b375ab778973127ca0ac52429a26e2fd86aa9508f4d26eb7", size = 263575, upload-time = "2025-08-11T12:07:11.928Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d9/7fb85a85e14de2e44dfb6a24f03c41e2af8697a6df83daddb0e9b7569f73/multidict-6.6.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a650629970fa21ac1fb06ba25dabfc5b8a2054fcbf6ae97c758aa956b8dba802", size = 259649, upload-time = "2025-08-11T12:07:13.244Z" }, + { url = "https://files.pythonhosted.org/packages/03/9e/b3a459bcf9b6e74fa461a5222a10ff9b544cb1cd52fd482fb1b75ecda2a2/multidict-6.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:452ff5da78d4720d7516a3a2abd804957532dd69296cb77319c193e3ffb87e24", size = 251505, upload-time = "2025-08-11T12:07:14.57Z" }, + { url = "https://files.pythonhosted.org/packages/86/a2/8022f78f041dfe6d71e364001a5cf987c30edfc83c8a5fb7a3f0974cff39/multidict-6.6.4-cp312-cp312-win32.whl", hash = "sha256:8c2fcb12136530ed19572bbba61b407f655e3953ba669b96a35036a11a485793", size = 41888, upload-time = "2025-08-11T12:07:15.904Z" }, + { url = "https://files.pythonhosted.org/packages/c7/eb/d88b1780d43a56db2cba24289fa744a9d216c1a8546a0dc3956563fd53ea/multidict-6.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:047d9425860a8c9544fed1b9584f0c8bcd31bcde9568b047c5e567a1025ecd6e", size = 46072, upload-time = "2025-08-11T12:07:17.045Z" }, + { url = "https://files.pythonhosted.org/packages/9f/16/b929320bf5750e2d9d4931835a4c638a19d2494a5b519caaaa7492ebe105/multidict-6.6.4-cp312-cp312-win_arm64.whl", hash = "sha256:14754eb72feaa1e8ae528468f24250dd997b8e2188c3d2f593f9eba259e4b364", size = 43222, upload-time = "2025-08-11T12:07:18.328Z" }, + { url = "https://files.pythonhosted.org/packages/3a/5d/e1db626f64f60008320aab00fbe4f23fc3300d75892a3381275b3d284580/multidict-6.6.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f46a6e8597f9bd71b31cc708195d42b634c8527fecbcf93febf1052cacc1f16e", size = 75848, upload-time = "2025-08-11T12:07:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/4c/aa/8b6f548d839b6c13887253af4e29c939af22a18591bfb5d0ee6f1931dae8/multidict-6.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:22e38b2bc176c5eb9c0a0e379f9d188ae4cd8b28c0f53b52bce7ab0a9e534657", size = 45060, upload-time = "2025-08-11T12:07:21.163Z" }, + { url = "https://files.pythonhosted.org/packages/eb/c6/f5e97e5d99a729bc2aa58eb3ebfa9f1e56a9b517cc38c60537c81834a73f/multidict-6.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5df8afd26f162da59e218ac0eefaa01b01b2e6cd606cffa46608f699539246da", size = 43269, upload-time = "2025-08-11T12:07:22.392Z" }, + { url = "https://files.pythonhosted.org/packages/dc/31/d54eb0c62516776f36fe67f84a732f97e0b0e12f98d5685bebcc6d396910/multidict-6.6.4-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:49517449b58d043023720aa58e62b2f74ce9b28f740a0b5d33971149553d72aa", size = 237158, upload-time = "2025-08-11T12:07:23.636Z" }, + { url = "https://files.pythonhosted.org/packages/c4/1c/8a10c1c25b23156e63b12165a929d8eb49a6ed769fdbefb06e6f07c1e50d/multidict-6.6.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae9408439537c5afdca05edd128a63f56a62680f4b3c234301055d7a2000220f", size = 257076, upload-time = "2025-08-11T12:07:25.049Z" }, + { url = "https://files.pythonhosted.org/packages/ad/86/90e20b5771d6805a119e483fd3d1e8393e745a11511aebca41f0da38c3e2/multidict-6.6.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:87a32d20759dc52a9e850fe1061b6e41ab28e2998d44168a8a341b99ded1dba0", size = 240694, upload-time = "2025-08-11T12:07:26.458Z" }, + { url = "https://files.pythonhosted.org/packages/e7/49/484d3e6b535bc0555b52a0a26ba86e4d8d03fd5587d4936dc59ba7583221/multidict-6.6.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:52e3c8d43cdfff587ceedce9deb25e6ae77daba560b626e97a56ddcad3756879", size = 266350, upload-time = "2025-08-11T12:07:27.94Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b4/aa4c5c379b11895083d50021e229e90c408d7d875471cb3abf721e4670d6/multidict-6.6.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ad8850921d3a8d8ff6fbef790e773cecfc260bbfa0566998980d3fa8f520bc4a", size = 267250, upload-time = "2025-08-11T12:07:29.303Z" }, + { url = "https://files.pythonhosted.org/packages/80/e5/5e22c5bf96a64bdd43518b1834c6d95a4922cc2066b7d8e467dae9b6cee6/multidict-6.6.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:497a2954adc25c08daff36f795077f63ad33e13f19bfff7736e72c785391534f", size = 254900, upload-time = "2025-08-11T12:07:30.764Z" }, + { url = "https://files.pythonhosted.org/packages/17/38/58b27fed927c07035abc02befacab42491e7388ca105e087e6e0215ead64/multidict-6.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:024ce601f92d780ca1617ad4be5ac15b501cc2414970ffa2bb2bbc2bd5a68fa5", size = 252355, upload-time = "2025-08-11T12:07:32.205Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a1/dad75d23a90c29c02b5d6f3d7c10ab36c3197613be5d07ec49c7791e186c/multidict-6.6.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a693fc5ed9bdd1c9e898013e0da4dcc640de7963a371c0bd458e50e046bf6438", size = 250061, upload-time = "2025-08-11T12:07:33.623Z" }, + { url = "https://files.pythonhosted.org/packages/b8/1a/ac2216b61c7f116edab6dc3378cca6c70dc019c9a457ff0d754067c58b20/multidict-6.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:190766dac95aab54cae5b152a56520fd99298f32a1266d66d27fdd1b5ac00f4e", size = 249675, upload-time = "2025-08-11T12:07:34.958Z" }, + { url = "https://files.pythonhosted.org/packages/d4/79/1916af833b800d13883e452e8e0977c065c4ee3ab7a26941fbfdebc11895/multidict-6.6.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:34d8f2a5ffdceab9dcd97c7a016deb2308531d5f0fced2bb0c9e1df45b3363d7", size = 261247, upload-time = "2025-08-11T12:07:36.588Z" }, + { url = "https://files.pythonhosted.org/packages/c5/65/d1f84fe08ac44a5fc7391cbc20a7cedc433ea616b266284413fd86062f8c/multidict-6.6.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:59e8d40ab1f5a8597abcef00d04845155a5693b5da00d2c93dbe88f2050f2812", size = 257960, upload-time = "2025-08-11T12:07:39.735Z" }, + { url = "https://files.pythonhosted.org/packages/13/b5/29ec78057d377b195ac2c5248c773703a6b602e132a763e20ec0457e7440/multidict-6.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:467fe64138cfac771f0e949b938c2e1ada2b5af22f39692aa9258715e9ea613a", size = 250078, upload-time = "2025-08-11T12:07:41.525Z" }, + { url = "https://files.pythonhosted.org/packages/c4/0e/7e79d38f70a872cae32e29b0d77024bef7834b0afb406ddae6558d9e2414/multidict-6.6.4-cp313-cp313-win32.whl", hash = "sha256:14616a30fe6d0a48d0a48d1a633ab3b8bec4cf293aac65f32ed116f620adfd69", size = 41708, upload-time = "2025-08-11T12:07:43.405Z" }, + { url = "https://files.pythonhosted.org/packages/9d/34/746696dffff742e97cd6a23da953e55d0ea51fa601fa2ff387b3edcfaa2c/multidict-6.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:40cd05eaeb39e2bc8939451f033e57feaa2ac99e07dbca8afe2be450a4a3b6cf", size = 45912, upload-time = "2025-08-11T12:07:45.082Z" }, + { url = "https://files.pythonhosted.org/packages/c7/87/3bac136181e271e29170d8d71929cdeddeb77f3e8b6a0c08da3a8e9da114/multidict-6.6.4-cp313-cp313-win_arm64.whl", hash = "sha256:f6eb37d511bfae9e13e82cb4d1af36b91150466f24d9b2b8a9785816deb16605", size = 43076, upload-time = "2025-08-11T12:07:46.746Z" }, + { url = "https://files.pythonhosted.org/packages/64/94/0a8e63e36c049b571c9ae41ee301ada29c3fee9643d9c2548d7d558a1d99/multidict-6.6.4-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:6c84378acd4f37d1b507dfa0d459b449e2321b3ba5f2338f9b085cf7a7ba95eb", size = 82812, upload-time = "2025-08-11T12:07:48.402Z" }, + { url = "https://files.pythonhosted.org/packages/25/1a/be8e369dfcd260d2070a67e65dd3990dd635cbd735b98da31e00ea84cd4e/multidict-6.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0e0558693063c75f3d952abf645c78f3c5dfdd825a41d8c4d8156fc0b0da6e7e", size = 48313, upload-time = "2025-08-11T12:07:49.679Z" }, + { url = "https://files.pythonhosted.org/packages/26/5a/dd4ade298674b2f9a7b06a32c94ffbc0497354df8285f27317c66433ce3b/multidict-6.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3f8e2384cb83ebd23fd07e9eada8ba64afc4c759cd94817433ab8c81ee4b403f", size = 46777, upload-time = "2025-08-11T12:07:51.318Z" }, + { url = "https://files.pythonhosted.org/packages/89/db/98aa28bc7e071bfba611ac2ae803c24e96dd3a452b4118c587d3d872c64c/multidict-6.6.4-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:f996b87b420995a9174b2a7c1a8daf7db4750be6848b03eb5e639674f7963773", size = 229321, upload-time = "2025-08-11T12:07:52.965Z" }, + { url = "https://files.pythonhosted.org/packages/c7/bc/01ddda2a73dd9d167bd85d0e8ef4293836a8f82b786c63fb1a429bc3e678/multidict-6.6.4-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc356250cffd6e78416cf5b40dc6a74f1edf3be8e834cf8862d9ed5265cf9b0e", size = 249954, upload-time = "2025-08-11T12:07:54.423Z" }, + { url = "https://files.pythonhosted.org/packages/06/78/6b7c0f020f9aa0acf66d0ab4eb9f08375bac9a50ff5e3edb1c4ccd59eafc/multidict-6.6.4-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:dadf95aa862714ea468a49ad1e09fe00fcc9ec67d122f6596a8d40caf6cec7d0", size = 228612, upload-time = "2025-08-11T12:07:55.914Z" }, + { url = "https://files.pythonhosted.org/packages/00/44/3faa416f89b2d5d76e9d447296a81521e1c832ad6e40b92f990697b43192/multidict-6.6.4-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7dd57515bebffd8ebd714d101d4c434063322e4fe24042e90ced41f18b6d3395", size = 257528, upload-time = "2025-08-11T12:07:57.371Z" }, + { url = "https://files.pythonhosted.org/packages/05/5f/77c03b89af0fcb16f018f668207768191fb9dcfb5e3361a5e706a11db2c9/multidict-6.6.4-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:967af5f238ebc2eb1da4e77af5492219fbd9b4b812347da39a7b5f5c72c0fa45", size = 256329, upload-time = "2025-08-11T12:07:58.844Z" }, + { url = "https://files.pythonhosted.org/packages/cf/e9/ed750a2a9afb4f8dc6f13dc5b67b514832101b95714f1211cd42e0aafc26/multidict-6.6.4-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a4c6875c37aae9794308ec43e3530e4aa0d36579ce38d89979bbf89582002bb", size = 247928, upload-time = "2025-08-11T12:08:01.037Z" }, + { url = "https://files.pythonhosted.org/packages/1f/b5/e0571bc13cda277db7e6e8a532791d4403dacc9850006cb66d2556e649c0/multidict-6.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:7f683a551e92bdb7fac545b9c6f9fa2aebdeefa61d607510b3533286fcab67f5", size = 245228, upload-time = "2025-08-11T12:08:02.96Z" }, + { url = "https://files.pythonhosted.org/packages/f3/a3/69a84b0eccb9824491f06368f5b86e72e4af54c3067c37c39099b6687109/multidict-6.6.4-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:3ba5aaf600edaf2a868a391779f7a85d93bed147854925f34edd24cc70a3e141", size = 235869, upload-time = "2025-08-11T12:08:04.746Z" }, + { url = "https://files.pythonhosted.org/packages/a9/9d/28802e8f9121a6a0804fa009debf4e753d0a59969ea9f70be5f5fdfcb18f/multidict-6.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:580b643b7fd2c295d83cad90d78419081f53fd532d1f1eb67ceb7060f61cff0d", size = 243446, upload-time = "2025-08-11T12:08:06.332Z" }, + { url = "https://files.pythonhosted.org/packages/38/ea/6c98add069b4878c1d66428a5f5149ddb6d32b1f9836a826ac764b9940be/multidict-6.6.4-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:37b7187197da6af3ee0b044dbc9625afd0c885f2800815b228a0e70f9a7f473d", size = 252299, upload-time = "2025-08-11T12:08:07.931Z" }, + { url = "https://files.pythonhosted.org/packages/3a/09/8fe02d204473e14c0af3affd50af9078839dfca1742f025cca765435d6b4/multidict-6.6.4-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e1b93790ed0bc26feb72e2f08299691ceb6da5e9e14a0d13cc74f1869af327a0", size = 246926, upload-time = "2025-08-11T12:08:09.467Z" }, + { url = "https://files.pythonhosted.org/packages/37/3d/7b1e10d774a6df5175ecd3c92bff069e77bed9ec2a927fdd4ff5fe182f67/multidict-6.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a506a77ddee1efcca81ecbeae27ade3e09cdf21a8ae854d766c2bb4f14053f92", size = 243383, upload-time = "2025-08-11T12:08:10.981Z" }, + { url = "https://files.pythonhosted.org/packages/50/b0/a6fae46071b645ae98786ab738447de1ef53742eaad949f27e960864bb49/multidict-6.6.4-cp313-cp313t-win32.whl", hash = "sha256:f93b2b2279883d1d0a9e1bd01f312d6fc315c5e4c1f09e112e4736e2f650bc4e", size = 47775, upload-time = "2025-08-11T12:08:12.439Z" }, + { url = "https://files.pythonhosted.org/packages/b2/0a/2436550b1520091af0600dff547913cb2d66fbac27a8c33bc1b1bccd8d98/multidict-6.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:6d46a180acdf6e87cc41dc15d8f5c2986e1e8739dc25dbb7dac826731ef381a4", size = 53100, upload-time = "2025-08-11T12:08:13.823Z" }, + { url = "https://files.pythonhosted.org/packages/97/ea/43ac51faff934086db9c072a94d327d71b7d8b40cd5dcb47311330929ef0/multidict-6.6.4-cp313-cp313t-win_arm64.whl", hash = "sha256:756989334015e3335d087a27331659820d53ba432befdef6a718398b0a8493ad", size = 45501, upload-time = "2025-08-11T12:08:15.173Z" }, + { url = "https://files.pythonhosted.org/packages/fd/69/b547032297c7e63ba2af494edba695d781af8a0c6e89e4d06cf848b21d80/multidict-6.6.4-py3-none-any.whl", hash = "sha256:27d8f8e125c07cb954e54d75d04905a9bba8a439c1d84aca94949d4d03d8601c", size = 12313, upload-time = "2025-08-11T12:08:46.891Z" }, +] + +[[package]] +name = "nicegui" +version = "2.22.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "aiofiles" }, + { name = "aiohttp" }, + { name = "certifi" }, + { name = "docutils" }, + { name = "fastapi" }, + { name = "h11" }, + { name = "httpx" }, + { name = "ifaddr" }, + { name = "itsdangerous" }, + { name = "jinja2" }, + { name = "markdown2" }, + { name = "orjson", marker = "platform_machine != 'i386' and platform_machine != 'i686'" }, + { name = "pygments" }, + { name = "python-engineio" }, + { name = "python-multipart" }, + { name = "python-socketio", extra = ["asyncio-client"] }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "uvicorn", extra = ["standard"] }, + { name = "vbuild" }, + { name = "watchfiles" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cc/81/aaf1432abf54f25d62a3c346a087db39c4d7a38833795c3f1eb90feab5fd/nicegui-2.22.2.tar.gz", hash = "sha256:5c0aaf2d2365c665ae42955b17d6fa7ba19526d7aa9bd02ab547917e7bd1338c", size = 13107276, upload-time = "2025-08-09T15:31:08.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/2b/141c85335df3982ca9a54da95d0c8954efe9756da8f2edaba2afbd262014/nicegui-2.22.2-py3-none-any.whl", hash = "sha256:a0e371918419af5bae7b22e6b55a29065a7a4222908af66584fd599e391b5b5f", size = 13494497, upload-time = "2025-08-09T15:31:05.235Z" }, +] + [[package]] name = "nodeenv" version = "1.9.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, +] + +[[package]] +name = "orjson" +version = "3.11.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/1d/5e0ae38788bdf0721326695e65fdf41405ed535f633eb0df0f06f57552fa/orjson-3.11.2.tar.gz", hash = "sha256:91bdcf5e69a8fd8e8bdb3de32b31ff01d2bd60c1e8d5fe7d5afabdcf19920309", size = 5470739, upload-time = "2025-08-12T15:12:28.626Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 }, + { url = "https://files.pythonhosted.org/packages/40/02/46054ebe7996a8adee9640dcad7d39d76c2000dc0377efa38e55dc5cbf78/orjson-3.11.2-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:901d80d349d8452162b3aa1afb82cec5bee79a10550660bc21311cc61a4c5486", size = 226528, upload-time = "2025-08-12T15:11:03.317Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/6b6f0b4d8aea1137436546b990f71be2cd8bd870aa2f5aa14dba0fcc95dc/orjson-3.11.2-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:cf3bd3967a360e87ee14ed82cb258b7f18c710dacf3822fb0042a14313a673a1", size = 115931, upload-time = "2025-08-12T15:11:04.759Z" }, + { url = "https://files.pythonhosted.org/packages/ae/05/4205cc97c30e82a293dd0d149b1a89b138ebe76afeca66fc129fa2aa4e6a/orjson-3.11.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26693dde66910078229a943e80eeb99fdce6cd2c26277dc80ead9f3ab97d2131", size = 111382, upload-time = "2025-08-12T15:11:06.468Z" }, + { url = "https://files.pythonhosted.org/packages/50/c7/b8a951a93caa821f9272a7c917115d825ae2e4e8768f5ddf37968ec9de01/orjson-3.11.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ad4c8acb50a28211c33fc7ef85ddf5cb18d4636a5205fd3fa2dce0411a0e30c", size = 116271, upload-time = "2025-08-12T15:11:07.845Z" }, + { url = "https://files.pythonhosted.org/packages/17/03/1006c7f8782d5327439e26d9b0ec66500ea7b679d4bbb6b891d2834ab3ee/orjson-3.11.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:994181e7f1725bb5f2d481d7d228738e0743b16bf319ca85c29369c65913df14", size = 119086, upload-time = "2025-08-12T15:11:09.329Z" }, + { url = "https://files.pythonhosted.org/packages/44/61/57d22bc31f36a93878a6f772aea76b2184102c6993dea897656a66d18c74/orjson-3.11.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dbb79a0476393c07656b69c8e763c3cc925fa8e1d9e9b7d1f626901bb5025448", size = 120724, upload-time = "2025-08-12T15:11:10.674Z" }, + { url = "https://files.pythonhosted.org/packages/78/a9/4550e96b4c490c83aea697d5347b8f7eb188152cd7b5a38001055ca5b379/orjson-3.11.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:191ed27a1dddb305083d8716af413d7219f40ec1d4c9b0e977453b4db0d6fb6c", size = 123577, upload-time = "2025-08-12T15:11:12.015Z" }, + { url = "https://files.pythonhosted.org/packages/3a/86/09b8cb3ebd513d708ef0c92d36ac3eebda814c65c72137b0a82d6d688fc4/orjson-3.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0afb89f16f07220183fd00f5f297328ed0a68d8722ad1b0c8dcd95b12bc82804", size = 121195, upload-time = "2025-08-12T15:11:13.399Z" }, + { url = "https://files.pythonhosted.org/packages/37/68/7b40b39ac2c1c644d4644e706d0de6c9999764341cd85f2a9393cb387661/orjson-3.11.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6ab6e6b4e93b1573a026b6ec16fca9541354dd58e514b62c558b58554ae04307", size = 119234, upload-time = "2025-08-12T15:11:15.134Z" }, + { url = "https://files.pythonhosted.org/packages/40/7c/bb6e7267cd80c19023d44d8cbc4ea4ed5429fcd4a7eb9950f50305697a28/orjson-3.11.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9cb23527efb61fb75527df55d20ee47989c4ee34e01a9c98ee9ede232abf6219", size = 392250, upload-time = "2025-08-12T15:11:16.604Z" }, + { url = "https://files.pythonhosted.org/packages/64/f2/6730ace05583dbca7c1b406d59f4266e48cd0d360566e71482420fb849fc/orjson-3.11.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a4dd1268e4035af21b8a09e4adf2e61f87ee7bf63b86d7bb0a237ac03fad5b45", size = 134572, upload-time = "2025-08-12T15:11:18.205Z" }, + { url = "https://files.pythonhosted.org/packages/96/0f/7d3e03a30d5aac0432882b539a65b8c02cb6dd4221ddb893babf09c424cc/orjson-3.11.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff8b155b145eaf5a9d94d2c476fbe18d6021de93cf36c2ae2c8c5b775763f14e", size = 123869, upload-time = "2025-08-12T15:11:19.554Z" }, + { url = "https://files.pythonhosted.org/packages/45/80/1513265eba6d4a960f078f4b1d2bff94a571ab2d28c6f9835e03dfc65cc6/orjson-3.11.2-cp312-cp312-win32.whl", hash = "sha256:ae3bb10279d57872f9aba68c9931aa71ed3b295fa880f25e68da79e79453f46e", size = 124430, upload-time = "2025-08-12T15:11:20.914Z" }, + { url = "https://files.pythonhosted.org/packages/fb/61/eadf057b68a332351eeb3d89a4cc538d14f31cd8b5ec1b31a280426ccca2/orjson-3.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:d026e1967239ec11a2559b4146a61d13914504b396f74510a1c4d6b19dfd8732", size = 119598, upload-time = "2025-08-12T15:11:22.372Z" }, + { url = "https://files.pythonhosted.org/packages/6b/3f/7f4b783402143d965ab7e9a2fc116fdb887fe53bdce7d3523271cd106098/orjson-3.11.2-cp312-cp312-win_arm64.whl", hash = "sha256:59f8d5ad08602711af9589375be98477d70e1d102645430b5a7985fdbf613b36", size = 114052, upload-time = "2025-08-12T15:11:23.762Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f3/0dd6b4750eb556ae4e2c6a9cb3e219ec642e9c6d95f8ebe5dc9020c67204/orjson-3.11.2-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a079fdba7062ab396380eeedb589afb81dc6683f07f528a03b6f7aae420a0219", size = 226419, upload-time = "2025-08-12T15:11:25.517Z" }, + { url = "https://files.pythonhosted.org/packages/44/d5/e67f36277f78f2af8a4690e0c54da6b34169812f807fd1b4bfc4dbcf9558/orjson-3.11.2-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:6a5f62ebbc530bb8bb4b1ead103647b395ba523559149b91a6c545f7cd4110ad", size = 115803, upload-time = "2025-08-12T15:11:27.357Z" }, + { url = "https://files.pythonhosted.org/packages/24/37/ff8bc86e0dacc48f07c2b6e20852f230bf4435611bab65e3feae2b61f0ae/orjson-3.11.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7df6c7b8b0931feb3420b72838c3e2ba98c228f7aa60d461bc050cf4ca5f7b2", size = 111337, upload-time = "2025-08-12T15:11:28.805Z" }, + { url = "https://files.pythonhosted.org/packages/b9/25/37d4d3e8079ea9784ea1625029988e7f4594ce50d4738b0c1e2bf4a9e201/orjson-3.11.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6f59dfea7da1fced6e782bb3699718088b1036cb361f36c6e4dd843c5111aefe", size = 116222, upload-time = "2025-08-12T15:11:30.18Z" }, + { url = "https://files.pythonhosted.org/packages/b7/32/a63fd9c07fce3b4193dcc1afced5dd4b0f3a24e27556604e9482b32189c9/orjson-3.11.2-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edf49146520fef308c31aa4c45b9925fd9c7584645caca7c0c4217d7900214ae", size = 119020, upload-time = "2025-08-12T15:11:31.59Z" }, + { url = "https://files.pythonhosted.org/packages/b4/b6/400792b8adc3079a6b5d649264a3224d6342436d9fac9a0ed4abc9dc4596/orjson-3.11.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50995bbeb5d41a32ad15e023305807f561ac5dcd9bd41a12c8d8d1d2c83e44e6", size = 120721, upload-time = "2025-08-12T15:11:33.035Z" }, + { url = "https://files.pythonhosted.org/packages/40/f3/31ab8f8c699eb9e65af8907889a0b7fef74c1d2b23832719a35da7bb0c58/orjson-3.11.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2cc42960515076eb639b705f105712b658c525863d89a1704d984b929b0577d1", size = 123574, upload-time = "2025-08-12T15:11:34.433Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a6/ce4287c412dff81878f38d06d2c80845709c60012ca8daf861cb064b4574/orjson-3.11.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c56777cab2a7b2a8ea687fedafb84b3d7fdafae382165c31a2adf88634c432fa", size = 121225, upload-time = "2025-08-12T15:11:36.133Z" }, + { url = "https://files.pythonhosted.org/packages/69/b0/7a881b2aef4fed0287d2a4fbb029d01ed84fa52b4a68da82bdee5e50598e/orjson-3.11.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:07349e88025b9b5c783077bf7a9f401ffbfb07fd20e86ec6fc5b7432c28c2c5e", size = 119201, upload-time = "2025-08-12T15:11:37.642Z" }, + { url = "https://files.pythonhosted.org/packages/cf/98/a325726b37f7512ed6338e5e65035c3c6505f4e628b09a5daf0419f054ea/orjson-3.11.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:45841fbb79c96441a8c58aa29ffef570c5df9af91f0f7a9572e5505e12412f15", size = 392193, upload-time = "2025-08-12T15:11:39.153Z" }, + { url = "https://files.pythonhosted.org/packages/cb/4f/a7194f98b0ce1d28190e0c4caa6d091a3fc8d0107ad2209f75c8ba398984/orjson-3.11.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:13d8d8db6cd8d89d4d4e0f4161acbbb373a4d2a4929e862d1d2119de4aa324ac", size = 134548, upload-time = "2025-08-12T15:11:40.768Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/b84caa2986c3f472dc56343ddb0167797a708a8d5c3be043e1e2677b55df/orjson-3.11.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51da1ee2178ed09c00d09c1b953e45846bbc16b6420965eb7a913ba209f606d8", size = 123798, upload-time = "2025-08-12T15:11:42.164Z" }, + { url = "https://files.pythonhosted.org/packages/9c/5b/e398449080ce6b4c8fcadad57e51fa16f65768e1b142ba90b23ac5d10801/orjson-3.11.2-cp313-cp313-win32.whl", hash = "sha256:51dc033df2e4a4c91c0ba4f43247de99b3cbf42ee7a42ee2b2b2f76c8b2f2cb5", size = 124402, upload-time = "2025-08-12T15:11:44.036Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/429e4608e124debfc4790bfc37131f6958e59510ba3b542d5fc163be8e5f/orjson-3.11.2-cp313-cp313-win_amd64.whl", hash = "sha256:29d91d74942b7436f29b5d1ed9bcfc3f6ef2d4f7c4997616509004679936650d", size = 119498, upload-time = "2025-08-12T15:11:45.864Z" }, + { url = "https://files.pythonhosted.org/packages/7b/04/f8b5f317cce7ad3580a9ad12d7e2df0714dfa8a83328ecddd367af802f5b/orjson-3.11.2-cp313-cp313-win_arm64.whl", hash = "sha256:4ca4fb5ac21cd1e48028d4f708b1bb13e39c42d45614befd2ead004a8bba8535", size = 114051, upload-time = "2025-08-12T15:11:47.555Z" }, + { url = "https://files.pythonhosted.org/packages/74/83/2c363022b26c3c25b3708051a19d12f3374739bb81323f05b284392080c0/orjson-3.11.2-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:3dcba7101ea6a8d4ef060746c0f2e7aa8e2453a1012083e1ecce9726d7554cb7", size = 226406, upload-time = "2025-08-12T15:11:49.445Z" }, + { url = "https://files.pythonhosted.org/packages/b0/a7/aa3c973de0b33fc93b4bd71691665ffdfeae589ea9d0625584ab10a7d0f5/orjson-3.11.2-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:15d17bdb76a142e1f55d91913e012e6e6769659daa6bfef3ef93f11083137e81", size = 115788, upload-time = "2025-08-12T15:11:50.992Z" }, + { url = "https://files.pythonhosted.org/packages/ef/f2/e45f233dfd09fdbb052ec46352363dca3906618e1a2b264959c18f809d0b/orjson-3.11.2-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:53c9e81768c69d4b66b8876ec3c8e431c6e13477186d0db1089d82622bccd19f", size = 111318, upload-time = "2025-08-12T15:11:52.495Z" }, + { url = "https://files.pythonhosted.org/packages/3e/23/cf5a73c4da6987204cbbf93167f353ff0c5013f7c5e5ef845d4663a366da/orjson-3.11.2-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:d4f13af59a7b84c1ca6b8a7ab70d608f61f7c44f9740cd42409e6ae7b6c8d8b7", size = 121231, upload-time = "2025-08-12T15:11:53.941Z" }, + { url = "https://files.pythonhosted.org/packages/40/1d/47468a398ae68a60cc21e599144e786e035bb12829cb587299ecebc088f1/orjson-3.11.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bde64aa469b5ee46cc960ed241fae3721d6a8801dacb2ca3466547a2535951e4", size = 119204, upload-time = "2025-08-12T15:11:55.409Z" }, + { url = "https://files.pythonhosted.org/packages/4d/d9/f99433d89b288b5bc8836bffb32a643f805e673cf840ef8bab6e73ced0d1/orjson-3.11.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:b5ca86300aeb383c8fa759566aca065878d3d98c3389d769b43f0a2e84d52c5f", size = 392237, upload-time = "2025-08-12T15:11:57.18Z" }, + { url = "https://files.pythonhosted.org/packages/d4/dc/1b9d80d40cebef603325623405136a29fb7d08c877a728c0943dd066c29a/orjson-3.11.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:24e32a558ebed73a6a71c8f1cbc163a7dd5132da5270ff3d8eeb727f4b6d1bc7", size = 134578, upload-time = "2025-08-12T15:11:58.844Z" }, + { url = "https://files.pythonhosted.org/packages/45/b3/72e7a4c5b6485ef4e83ef6aba7f1dd041002bad3eb5d1d106ca5b0fc02c6/orjson-3.11.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e36319a5d15b97e4344110517450396845cc6789aed712b1fbf83c1bd95792f6", size = 123799, upload-time = "2025-08-12T15:12:00.352Z" }, + { url = "https://files.pythonhosted.org/packages/c8/3e/a3d76b392e7acf9b34dc277171aad85efd6accc75089bb35b4c614990ea9/orjson-3.11.2-cp314-cp314-win32.whl", hash = "sha256:40193ada63fab25e35703454d65b6afc71dbc65f20041cb46c6d91709141ef7f", size = 124461, upload-time = "2025-08-12T15:12:01.854Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e3/75c6a596ff8df9e4a5894813ff56695f0a218e6ea99420b4a645c4f7795d/orjson-3.11.2-cp314-cp314-win_amd64.whl", hash = "sha256:7c8ac5f6b682d3494217085cf04dadae66efee45349ad4ee2a1da3c97e2305a8", size = 119494, upload-time = "2025-08-12T15:12:03.337Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3d/9e74742fc261c5ca473c96bb3344d03995869e1dc6402772c60afb97736a/orjson-3.11.2-cp314-cp314-win_arm64.whl", hash = "sha256:21cf261e8e79284242e4cb1e5924df16ae28255184aafeff19be1405f6d33f67", size = 114046, upload-time = "2025-08-12T15:12:04.87Z" }, ] [[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 } +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 }, + { 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 = "platformdirs" version = "4.3.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362 } +sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567 }, + { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, ] [[package]] @@ -307,9 +725,9 @@ dependencies = [ { name = "httpx", extra = ["http2"] }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6e/3e/1b50568e1f5db0bdced4a82c7887e37326585faef7ca43ead86849cb4861/postgrest-1.1.1.tar.gz", hash = "sha256:f3bb3e8c4602775c75c844a31f565f5f3dd584df4d36d683f0b67d01a86be322", size = 15431 } +sdist = { url = "https://files.pythonhosted.org/packages/6e/3e/1b50568e1f5db0bdced4a82c7887e37326585faef7ca43ead86849cb4861/postgrest-1.1.1.tar.gz", hash = "sha256:f3bb3e8c4602775c75c844a31f565f5f3dd584df4d36d683f0b67d01a86be322", size = 15431, upload-time = "2025-06-23T19:21:34.742Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/71/188a50ea64c17f73ff4df5196ec1553a8f1723421eb2d1069c73bab47d78/postgrest-1.1.1-py3-none-any.whl", hash = "sha256:98a6035ee1d14288484bfe36235942c5fb2d26af6d8120dfe3efbe007859251a", size = 22366 }, + { url = "https://files.pythonhosted.org/packages/a4/71/188a50ea64c17f73ff4df5196ec1553a8f1723421eb2d1069c73bab47d78/postgrest-1.1.1-py3-none-any.whl", hash = "sha256:98a6035ee1d14288484bfe36235942c5fb2d26af6d8120dfe3efbe007859251a", size = 22366, upload-time = "2025-06-23T19:21:33.637Z" }, ] [[package]] @@ -323,9 +741,75 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424 } +sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707 }, + { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, +] + +[[package]] +name = "propcache" +version = "0.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/16/43264e4a779dd8588c21a70f0709665ee8f611211bdd2c87d952cfa7c776/propcache-0.3.2.tar.gz", hash = "sha256:20d7d62e4e7ef05f221e0db2856b979540686342e7dd9973b815599c7057e168", size = 44139, upload-time = "2025-06-09T22:56:06.081Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/42/9ca01b0a6f48e81615dca4765a8f1dd2c057e0540f6116a27dc5ee01dfb6/propcache-0.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8de106b6c84506b31c27168582cd3cb3000a6412c16df14a8628e5871ff83c10", size = 73674, upload-time = "2025-06-09T22:54:30.551Z" }, + { url = "https://files.pythonhosted.org/packages/af/6e/21293133beb550f9c901bbece755d582bfaf2176bee4774000bd4dd41884/propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154", size = 43570, upload-time = "2025-06-09T22:54:32.296Z" }, + { url = "https://files.pythonhosted.org/packages/0c/c8/0393a0a3a2b8760eb3bde3c147f62b20044f0ddac81e9d6ed7318ec0d852/propcache-0.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce26862344bdf836650ed2487c3d724b00fbfec4233a1013f597b78c1cb73615", size = 43094, upload-time = "2025-06-09T22:54:33.929Z" }, + { url = "https://files.pythonhosted.org/packages/37/2c/489afe311a690399d04a3e03b069225670c1d489eb7b044a566511c1c498/propcache-0.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca54bd347a253af2cf4544bbec232ab982f4868de0dd684246b67a51bc6b1db", size = 226958, upload-time = "2025-06-09T22:54:35.186Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ca/63b520d2f3d418c968bf596839ae26cf7f87bead026b6192d4da6a08c467/propcache-0.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55780d5e9a2ddc59711d727226bb1ba83a22dd32f64ee15594b9392b1f544eb1", size = 234894, upload-time = "2025-06-09T22:54:36.708Z" }, + { url = "https://files.pythonhosted.org/packages/11/60/1d0ed6fff455a028d678df30cc28dcee7af77fa2b0e6962ce1df95c9a2a9/propcache-0.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:035e631be25d6975ed87ab23153db6a73426a48db688070d925aa27e996fe93c", size = 233672, upload-time = "2025-06-09T22:54:38.062Z" }, + { url = "https://files.pythonhosted.org/packages/37/7c/54fd5301ef38505ab235d98827207176a5c9b2aa61939b10a460ca53e123/propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67", size = 224395, upload-time = "2025-06-09T22:54:39.634Z" }, + { url = "https://files.pythonhosted.org/packages/ee/1a/89a40e0846f5de05fdc6779883bf46ba980e6df4d2ff8fb02643de126592/propcache-0.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ca3aee1aa955438c4dba34fc20a9f390e4c79967257d830f137bd5a8a32ed3b", size = 212510, upload-time = "2025-06-09T22:54:41.565Z" }, + { url = "https://files.pythonhosted.org/packages/5e/33/ca98368586c9566a6b8d5ef66e30484f8da84c0aac3f2d9aec6d31a11bd5/propcache-0.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4f30862869fa2b68380d677cc1c5fcf1e0f2b9ea0cf665812895c75d0ca3b8", size = 222949, upload-time = "2025-06-09T22:54:43.038Z" }, + { url = "https://files.pythonhosted.org/packages/ba/11/ace870d0aafe443b33b2f0b7efdb872b7c3abd505bfb4890716ad7865e9d/propcache-0.3.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b77ec3c257d7816d9f3700013639db7491a434644c906a2578a11daf13176251", size = 217258, upload-time = "2025-06-09T22:54:44.376Z" }, + { url = "https://files.pythonhosted.org/packages/5b/d2/86fd6f7adffcfc74b42c10a6b7db721d1d9ca1055c45d39a1a8f2a740a21/propcache-0.3.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cab90ac9d3f14b2d5050928483d3d3b8fb6b4018893fc75710e6aa361ecb2474", size = 213036, upload-time = "2025-06-09T22:54:46.243Z" }, + { url = "https://files.pythonhosted.org/packages/07/94/2d7d1e328f45ff34a0a284cf5a2847013701e24c2a53117e7c280a4316b3/propcache-0.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0b504d29f3c47cf6b9e936c1852246c83d450e8e063d50562115a6be6d3a2535", size = 227684, upload-time = "2025-06-09T22:54:47.63Z" }, + { url = "https://files.pythonhosted.org/packages/b7/05/37ae63a0087677e90b1d14710e532ff104d44bc1efa3b3970fff99b891dc/propcache-0.3.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:ce2ac2675a6aa41ddb2a0c9cbff53780a617ac3d43e620f8fd77ba1c84dcfc06", size = 234562, upload-time = "2025-06-09T22:54:48.982Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7c/3f539fcae630408d0bd8bf3208b9a647ccad10976eda62402a80adf8fc34/propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1", size = 222142, upload-time = "2025-06-09T22:54:50.424Z" }, + { url = "https://files.pythonhosted.org/packages/7c/d2/34b9eac8c35f79f8a962546b3e97e9d4b990c420ee66ac8255d5d9611648/propcache-0.3.2-cp312-cp312-win32.whl", hash = "sha256:df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1", size = 37711, upload-time = "2025-06-09T22:54:52.072Z" }, + { url = "https://files.pythonhosted.org/packages/19/61/d582be5d226cf79071681d1b46b848d6cb03d7b70af7063e33a2787eaa03/propcache-0.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c", size = 41479, upload-time = "2025-06-09T22:54:53.234Z" }, + { url = "https://files.pythonhosted.org/packages/dc/d1/8c747fafa558c603c4ca19d8e20b288aa0c7cda74e9402f50f31eb65267e/propcache-0.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ca592ed634a73ca002967458187109265e980422116c0a107cf93d81f95af945", size = 71286, upload-time = "2025-06-09T22:54:54.369Z" }, + { url = "https://files.pythonhosted.org/packages/61/99/d606cb7986b60d89c36de8a85d58764323b3a5ff07770a99d8e993b3fa73/propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252", size = 42425, upload-time = "2025-06-09T22:54:55.642Z" }, + { url = "https://files.pythonhosted.org/packages/8c/96/ef98f91bbb42b79e9bb82bdd348b255eb9d65f14dbbe3b1594644c4073f7/propcache-0.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f08f1cc28bd2eade7a8a3d2954ccc673bb02062e3e7da09bc75d843386b342f", size = 41846, upload-time = "2025-06-09T22:54:57.246Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ad/3f0f9a705fb630d175146cd7b1d2bf5555c9beaed54e94132b21aac098a6/propcache-0.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1a342c834734edb4be5ecb1e9fb48cb64b1e2320fccbd8c54bf8da8f2a84c33", size = 208871, upload-time = "2025-06-09T22:54:58.975Z" }, + { url = "https://files.pythonhosted.org/packages/3a/38/2085cda93d2c8b6ec3e92af2c89489a36a5886b712a34ab25de9fbca7992/propcache-0.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a544caaae1ac73f1fecfae70ded3e93728831affebd017d53449e3ac052ac1e", size = 215720, upload-time = "2025-06-09T22:55:00.471Z" }, + { url = "https://files.pythonhosted.org/packages/61/c1/d72ea2dc83ac7f2c8e182786ab0fc2c7bd123a1ff9b7975bee671866fe5f/propcache-0.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310d11aa44635298397db47a3ebce7db99a4cc4b9bbdfcf6c98a60c8d5261cf1", size = 215203, upload-time = "2025-06-09T22:55:01.834Z" }, + { url = "https://files.pythonhosted.org/packages/af/81/b324c44ae60c56ef12007105f1460d5c304b0626ab0cc6b07c8f2a9aa0b8/propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3", size = 206365, upload-time = "2025-06-09T22:55:03.199Z" }, + { url = "https://files.pythonhosted.org/packages/09/73/88549128bb89e66d2aff242488f62869014ae092db63ccea53c1cc75a81d/propcache-0.3.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cabf5b5902272565e78197edb682017d21cf3b550ba0460ee473753f28d23c1", size = 196016, upload-time = "2025-06-09T22:55:04.518Z" }, + { url = "https://files.pythonhosted.org/packages/b9/3f/3bdd14e737d145114a5eb83cb172903afba7242f67c5877f9909a20d948d/propcache-0.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0a2f2235ac46a7aa25bdeb03a9e7060f6ecbd213b1f9101c43b3090ffb971ef6", size = 205596, upload-time = "2025-06-09T22:55:05.942Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ca/2f4aa819c357d3107c3763d7ef42c03980f9ed5c48c82e01e25945d437c1/propcache-0.3.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:92b69e12e34869a6970fd2f3da91669899994b47c98f5d430b781c26f1d9f387", size = 200977, upload-time = "2025-06-09T22:55:07.792Z" }, + { url = "https://files.pythonhosted.org/packages/cd/4a/e65276c7477533c59085251ae88505caf6831c0e85ff8b2e31ebcbb949b1/propcache-0.3.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:54e02207c79968ebbdffc169591009f4474dde3b4679e16634d34c9363ff56b4", size = 197220, upload-time = "2025-06-09T22:55:09.173Z" }, + { url = "https://files.pythonhosted.org/packages/7c/54/fc7152e517cf5578278b242396ce4d4b36795423988ef39bb8cd5bf274c8/propcache-0.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4adfb44cb588001f68c5466579d3f1157ca07f7504fc91ec87862e2b8e556b88", size = 210642, upload-time = "2025-06-09T22:55:10.62Z" }, + { url = "https://files.pythonhosted.org/packages/b9/80/abeb4a896d2767bf5f1ea7b92eb7be6a5330645bd7fb844049c0e4045d9d/propcache-0.3.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fd3e6019dc1261cd0291ee8919dd91fbab7b169bb76aeef6c716833a3f65d206", size = 212789, upload-time = "2025-06-09T22:55:12.029Z" }, + { url = "https://files.pythonhosted.org/packages/b3/db/ea12a49aa7b2b6d68a5da8293dcf50068d48d088100ac016ad92a6a780e6/propcache-0.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4c181cad81158d71c41a2bce88edce078458e2dd5ffee7eddd6b05da85079f43", size = 205880, upload-time = "2025-06-09T22:55:13.45Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e5/9076a0bbbfb65d1198007059c65639dfd56266cf8e477a9707e4b1999ff4/propcache-0.3.2-cp313-cp313-win32.whl", hash = "sha256:8a08154613f2249519e549de2330cf8e2071c2887309a7b07fb56098f5170a02", size = 37220, upload-time = "2025-06-09T22:55:15.284Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f5/b369e026b09a26cd77aa88d8fffd69141d2ae00a2abaaf5380d2603f4b7f/propcache-0.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e41671f1594fc4ab0a6dec1351864713cb3a279910ae8b58f884a88a0a632c05", size = 40678, upload-time = "2025-06-09T22:55:16.445Z" }, + { url = "https://files.pythonhosted.org/packages/a4/3a/6ece377b55544941a08d03581c7bc400a3c8cd3c2865900a68d5de79e21f/propcache-0.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9a3cf035bbaf035f109987d9d55dc90e4b0e36e04bbbb95af3055ef17194057b", size = 76560, upload-time = "2025-06-09T22:55:17.598Z" }, + { url = "https://files.pythonhosted.org/packages/0c/da/64a2bb16418740fa634b0e9c3d29edff1db07f56d3546ca2d86ddf0305e1/propcache-0.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:156c03d07dc1323d8dacaa221fbe028c5c70d16709cdd63502778e6c3ccca1b0", size = 44676, upload-time = "2025-06-09T22:55:18.922Z" }, + { url = "https://files.pythonhosted.org/packages/36/7b/f025e06ea51cb72c52fb87e9b395cced02786610b60a3ed51da8af017170/propcache-0.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74413c0ba02ba86f55cf60d18daab219f7e531620c15f1e23d95563f505efe7e", size = 44701, upload-time = "2025-06-09T22:55:20.106Z" }, + { url = "https://files.pythonhosted.org/packages/a4/00/faa1b1b7c3b74fc277f8642f32a4c72ba1d7b2de36d7cdfb676db7f4303e/propcache-0.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f066b437bb3fa39c58ff97ab2ca351db465157d68ed0440abecb21715eb24b28", size = 276934, upload-time = "2025-06-09T22:55:21.5Z" }, + { url = "https://files.pythonhosted.org/packages/74/ab/935beb6f1756e0476a4d5938ff44bf0d13a055fed880caf93859b4f1baf4/propcache-0.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1304b085c83067914721e7e9d9917d41ad87696bf70f0bc7dee450e9c71ad0a", size = 278316, upload-time = "2025-06-09T22:55:22.918Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9d/994a5c1ce4389610838d1caec74bdf0e98b306c70314d46dbe4fcf21a3e2/propcache-0.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab50cef01b372763a13333b4e54021bdcb291fc9a8e2ccb9c2df98be51bcde6c", size = 282619, upload-time = "2025-06-09T22:55:24.651Z" }, + { url = "https://files.pythonhosted.org/packages/2b/00/a10afce3d1ed0287cef2e09506d3be9822513f2c1e96457ee369adb9a6cd/propcache-0.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad3b2a085ec259ad2c2842666b2a0a49dea8463579c606426128925af1ed725", size = 265896, upload-time = "2025-06-09T22:55:26.049Z" }, + { url = "https://files.pythonhosted.org/packages/2e/a8/2aa6716ffa566ca57c749edb909ad27884680887d68517e4be41b02299f3/propcache-0.3.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:261fa020c1c14deafd54c76b014956e2f86991af198c51139faf41c4d5e83892", size = 252111, upload-time = "2025-06-09T22:55:27.381Z" }, + { url = "https://files.pythonhosted.org/packages/36/4f/345ca9183b85ac29c8694b0941f7484bf419c7f0fea2d1e386b4f7893eed/propcache-0.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:46d7f8aa79c927e5f987ee3a80205c987717d3659f035c85cf0c3680526bdb44", size = 268334, upload-time = "2025-06-09T22:55:28.747Z" }, + { url = "https://files.pythonhosted.org/packages/3e/ca/fcd54f78b59e3f97b3b9715501e3147f5340167733d27db423aa321e7148/propcache-0.3.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:6d8f3f0eebf73e3c0ff0e7853f68be638b4043c65a70517bb575eff54edd8dbe", size = 255026, upload-time = "2025-06-09T22:55:30.184Z" }, + { url = "https://files.pythonhosted.org/packages/8b/95/8e6a6bbbd78ac89c30c225210a5c687790e532ba4088afb8c0445b77ef37/propcache-0.3.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:03c89c1b14a5452cf15403e291c0ccd7751d5b9736ecb2c5bab977ad6c5bcd81", size = 250724, upload-time = "2025-06-09T22:55:31.646Z" }, + { url = "https://files.pythonhosted.org/packages/ee/b0/0dd03616142baba28e8b2d14ce5df6631b4673850a3d4f9c0f9dd714a404/propcache-0.3.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cc17efde71e12bbaad086d679ce575268d70bc123a5a71ea7ad76f70ba30bba", size = 268868, upload-time = "2025-06-09T22:55:33.209Z" }, + { url = "https://files.pythonhosted.org/packages/c5/98/2c12407a7e4fbacd94ddd32f3b1e3d5231e77c30ef7162b12a60e2dd5ce3/propcache-0.3.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:acdf05d00696bc0447e278bb53cb04ca72354e562cf88ea6f9107df8e7fd9770", size = 271322, upload-time = "2025-06-09T22:55:35.065Z" }, + { url = "https://files.pythonhosted.org/packages/35/91/9cb56efbb428b006bb85db28591e40b7736847b8331d43fe335acf95f6c8/propcache-0.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4445542398bd0b5d32df908031cb1b30d43ac848e20470a878b770ec2dcc6330", size = 265778, upload-time = "2025-06-09T22:55:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4c/b0fe775a2bdd01e176b14b574be679d84fc83958335790f7c9a686c1f468/propcache-0.3.2-cp313-cp313t-win32.whl", hash = "sha256:f86e5d7cd03afb3a1db8e9f9f6eff15794e79e791350ac48a8c924e6f439f394", size = 41175, upload-time = "2025-06-09T22:55:38.436Z" }, + { url = "https://files.pythonhosted.org/packages/a4/ff/47f08595e3d9b5e149c150f88d9714574f1a7cbd89fe2817158a952674bf/propcache-0.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9704bedf6e7cbe3c65eca4379a9b53ee6a83749f047808cbb5044d40d7d72198", size = 44857, upload-time = "2025-06-09T22:55:39.687Z" }, + { url = "https://files.pythonhosted.org/packages/cc/35/cc0aaecf278bb4575b8555f2b137de5ab821595ddae9da9d3cd1da4072c7/propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f", size = 12663, upload-time = "2025-06-09T22:56:04.484Z" }, +] + +[[package]] +name = "pscript" +version = "0.7.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/59/68/f918702e270eddc5f7c54108f6a2f2afc2d299985820dbb0db9beb77d66d/pscript-0.7.7.tar.gz", hash = "sha256:8632f7a4483f235514aadee110edee82eb6d67336bf68744a7b18d76e50442f8", size = 176138, upload-time = "2022-01-10T10:55:02.559Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/bc/980e2ebd442d2a8f1d22780f73db76f2a1df3bf79b3fb501b054b4b4dd03/pscript-0.7.7-py3-none-any.whl", hash = "sha256:b0fdac0df0393a4d7497153fea6a82e6429f32327c4c0a4817f1cd68adc08083", size = 126689, upload-time = "2022-01-10T10:55:00.793Z" }, ] [[package]] @@ -338,9 +822,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350 } +sdist = { url = "https://files.pythonhosted.org/packages/00/dd/4325abf92c39ba8623b5af936ddb36ffcfe0beae70405d456ab1fb2f5b8c/pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", size = 788350, upload-time = "2025-06-14T08:33:17.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782 }, + { url = "https://files.pythonhosted.org/packages/6a/c0/ec2b1c8712ca690e5d61979dee872603e92b8a32f94cc1b72d53beab008a/pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b", size = 444782, upload-time = "2025-06-14T08:33:14.905Z" }, ] [[package]] @@ -350,48 +834,57 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000 }, - { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996 }, - { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957 }, - { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199 }, - { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296 }, - { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109 }, - { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028 }, - { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044 }, - { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881 }, - { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034 }, - { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187 }, - { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628 }, - { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866 }, - { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894 }, - { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688 }, - { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808 }, - { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580 }, - { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859 }, - { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810 }, - { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498 }, - { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611 }, - { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924 }, - { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196 }, - { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389 }, - { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223 }, - { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473 }, - { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269 }, - { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921 }, - { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162 }, - { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560 }, - { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777 }, +sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" }, + { url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" }, + { url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" }, + { url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" }, + { url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" }, + { url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" }, + { url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" }, + { url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" }, + { url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" }, + { url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" }, + { url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" }, + { url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" }, + { url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" }, + { url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" }, + { url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" }, + { url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" }, + { url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" }, + { url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" }, + { url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" }, + { url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" }, + { url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" }, + { url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" }, + { url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" }, + { url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" }, + { url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" }, + { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" }, +] + +[[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 = "pyjwt" version = "2.10.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785 } +sdist = { url = "https://files.pythonhosted.org/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785, upload-time = "2024-11-28T03:43:29.933Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997 }, + { url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" }, ] [[package]] @@ -401,35 +894,83 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "six" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, +] + +[[package]] +name = "python-engineio" +version = "4.12.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "simple-websocket" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ba/0b/67295279b66835f9fa7a491650efcd78b20321c127036eef62c11a31e028/python_engineio-4.12.2.tar.gz", hash = "sha256:e7e712ffe1be1f6a05ee5f951e72d434854a32fcfc7f6e4d9d3cae24ec70defa", size = 91677, upload-time = "2025-06-04T19:22:18.789Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/fa/df59acedf7bbb937f69174d00f921a7b93aa5a5f5c17d05296c814fff6fc/python_engineio-4.12.2-py3-none-any.whl", hash = "sha256:8218ab66950e179dfec4b4bbb30aecf3f5d86f5e58e6fc1aa7fde2c698b2804f", size = 59536, upload-time = "2025-06-04T19:22:16.916Z" }, +] + +[[package]] +name = "python-multipart" +version = "0.0.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158, upload-time = "2024-12-16T19:45:46.972Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, + { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546, upload-time = "2024-12-16T19:45:44.423Z" }, +] + +[[package]] +name = "python-socketio" +version = "5.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "bidict" }, + { name = "python-engineio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/21/1a/396d50ccf06ee539fa758ce5623b59a9cb27637fc4b2dc07ed08bf495e77/python_socketio-5.13.0.tar.gz", hash = "sha256:ac4e19a0302ae812e23b712ec8b6427ca0521f7c582d6abb096e36e24a263029", size = 121125, upload-time = "2025-04-12T15:46:59.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/32/b4fb8585d1be0f68bde7e110dffbcf354915f77ad8c778563f0ad9655c02/python_socketio-5.13.0-py3-none-any.whl", hash = "sha256:51f68d6499f2df8524668c24bcec13ba1414117cfb3a90115c559b601ab10caf", size = 77800, upload-time = "2025-04-12T15:46:58.412Z" }, +] + +[package.optional-dependencies] +asyncio-client = [ + { name = "aiohttp" }, ] [[package]] name = "pyyaml" version = "6.0.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 }, - { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 }, - { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 }, - { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 }, - { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 }, - { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 }, - { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 }, - { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, - { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, - { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 }, - { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 }, - { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 }, - { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 }, - { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 }, - { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 }, - { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 }, - { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, - { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, ] [[package]] @@ -441,52 +982,64 @@ dependencies = [ { name = "typing-extensions" }, { name = "websockets" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d3/ca/e408fbdb6b344bf529c7e8bf020372d21114fe538392c72089462edd26e5/realtime-2.7.0.tar.gz", hash = "sha256:6b9434eeba8d756c8faf94fc0a32081d09f250d14d82b90341170602adbb019f", size = 18860 } +sdist = { url = "https://files.pythonhosted.org/packages/d3/ca/e408fbdb6b344bf529c7e8bf020372d21114fe538392c72089462edd26e5/realtime-2.7.0.tar.gz", hash = "sha256:6b9434eeba8d756c8faf94fc0a32081d09f250d14d82b90341170602adbb019f", size = 18860, upload-time = "2025-07-28T18:54:22.949Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/07/a5c7aef12f9a3497f5ad77157a37915645861e8b23b89b2ad4b0f11b48ad/realtime-2.7.0-py3-none-any.whl", hash = "sha256:d55a278803529a69d61c7174f16563a9cfa5bacc1664f656959694481903d99c", size = 22409 }, + { url = "https://files.pythonhosted.org/packages/d2/07/a5c7aef12f9a3497f5ad77157a37915645861e8b23b89b2ad4b0f11b48ad/realtime-2.7.0-py3-none-any.whl", hash = "sha256:d55a278803529a69d61c7174f16563a9cfa5bacc1664f656959694481903d99c", size = 22409, upload-time = "2025-07-28T18:54:21.383Z" }, ] [[package]] name = "ruff" version = "0.12.8" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4b/da/5bd7565be729e86e1442dad2c9a364ceeff82227c2dece7c29697a9795eb/ruff-0.12.8.tar.gz", hash = "sha256:4cb3a45525176e1009b2b64126acf5f9444ea59066262791febf55e40493a033", size = 5242373 } +sdist = { url = "https://files.pythonhosted.org/packages/4b/da/5bd7565be729e86e1442dad2c9a364ceeff82227c2dece7c29697a9795eb/ruff-0.12.8.tar.gz", hash = "sha256:4cb3a45525176e1009b2b64126acf5f9444ea59066262791febf55e40493a033", size = 5242373, upload-time = "2025-08-07T19:05:47.268Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c9/1e/c843bfa8ad1114fab3eb2b78235dda76acd66384c663a4e0415ecc13aa1e/ruff-0.12.8-py3-none-linux_armv6l.whl", hash = "sha256:63cb5a5e933fc913e5823a0dfdc3c99add73f52d139d6cd5cc8639d0e0465513", size = 11675315 }, - { url = "https://files.pythonhosted.org/packages/24/ee/af6e5c2a8ca3a81676d5480a1025494fd104b8896266502bb4de2a0e8388/ruff-0.12.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a9bbe28f9f551accf84a24c366c1aa8774d6748438b47174f8e8565ab9dedbc", size = 12456653 }, - { url = "https://files.pythonhosted.org/packages/99/9d/e91f84dfe3866fa648c10512904991ecc326fd0b66578b324ee6ecb8f725/ruff-0.12.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2fae54e752a3150f7ee0e09bce2e133caf10ce9d971510a9b925392dc98d2fec", size = 11659690 }, - { url = "https://files.pythonhosted.org/packages/fe/ac/a363d25ec53040408ebdd4efcee929d48547665858ede0505d1d8041b2e5/ruff-0.12.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0acbcf01206df963d9331b5838fb31f3b44fa979ee7fa368b9b9057d89f4a53", size = 11896923 }, - { url = "https://files.pythonhosted.org/packages/58/9f/ea356cd87c395f6ade9bb81365bd909ff60860975ca1bc39f0e59de3da37/ruff-0.12.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae3e7504666ad4c62f9ac8eedb52a93f9ebdeb34742b8b71cd3cccd24912719f", size = 11477612 }, - { url = "https://files.pythonhosted.org/packages/1a/46/92e8fa3c9dcfd49175225c09053916cb97bb7204f9f899c2f2baca69e450/ruff-0.12.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb82efb5d35d07497813a1c5647867390a7d83304562607f3579602fa3d7d46f", size = 13182745 }, - { url = "https://files.pythonhosted.org/packages/5e/c4/f2176a310f26e6160deaf661ef60db6c3bb62b7a35e57ae28f27a09a7d63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dbea798fc0065ad0b84a2947b0aff4233f0cb30f226f00a2c5850ca4393de609", size = 14206885 }, - { url = "https://files.pythonhosted.org/packages/87/9d/98e162f3eeeb6689acbedbae5050b4b3220754554526c50c292b611d3a63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49ebcaccc2bdad86fd51b7864e3d808aad404aab8df33d469b6e65584656263a", size = 13639381 }, - { url = "https://files.pythonhosted.org/packages/81/4e/1b7478b072fcde5161b48f64774d6edd59d6d198e4ba8918d9f4702b8043/ruff-0.12.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ac9c570634b98c71c88cb17badd90f13fc076a472ba6ef1d113d8ed3df109fb", size = 12613271 }, - { url = "https://files.pythonhosted.org/packages/e8/67/0c3c9179a3ad19791ef1b8f7138aa27d4578c78700551c60d9260b2c660d/ruff-0.12.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:560e0cd641e45591a3e42cb50ef61ce07162b9c233786663fdce2d8557d99818", size = 12847783 }, - { url = "https://files.pythonhosted.org/packages/4e/2a/0b6ac3dd045acf8aa229b12c9c17bb35508191b71a14904baf99573a21bd/ruff-0.12.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:71c83121512e7743fba5a8848c261dcc454cafb3ef2934a43f1b7a4eb5a447ea", size = 11702672 }, - { url = "https://files.pythonhosted.org/packages/9d/ee/f9fdc9f341b0430110de8b39a6ee5fa68c5706dc7c0aa940817947d6937e/ruff-0.12.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:de4429ef2ba091ecddedd300f4c3f24bca875d3d8b23340728c3cb0da81072c3", size = 11440626 }, - { url = "https://files.pythonhosted.org/packages/89/fb/b3aa2d482d05f44e4d197d1de5e3863feb13067b22c571b9561085c999dc/ruff-0.12.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a2cab5f60d5b65b50fba39a8950c8746df1627d54ba1197f970763917184b161", size = 12462162 }, - { url = "https://files.pythonhosted.org/packages/18/9f/5c5d93e1d00d854d5013c96e1a92c33b703a0332707a7cdbd0a4880a84fb/ruff-0.12.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:45c32487e14f60b88aad6be9fd5da5093dbefb0e3e1224131cb1d441d7cb7d46", size = 12913212 }, - { url = "https://files.pythonhosted.org/packages/71/13/ab9120add1c0e4604c71bfc2e4ef7d63bebece0cfe617013da289539cef8/ruff-0.12.8-py3-none-win32.whl", hash = "sha256:daf3475060a617fd5bc80638aeaf2f5937f10af3ec44464e280a9d2218e720d3", size = 11694382 }, - { url = "https://files.pythonhosted.org/packages/f6/dc/a2873b7c5001c62f46266685863bee2888caf469d1edac84bf3242074be2/ruff-0.12.8-py3-none-win_amd64.whl", hash = "sha256:7209531f1a1fcfbe8e46bcd7ab30e2f43604d8ba1c49029bb420b103d0b5f76e", size = 12740482 }, - { url = "https://files.pythonhosted.org/packages/cb/5c/799a1efb8b5abab56e8a9f2a0b72d12bd64bb55815e9476c7d0a2887d2f7/ruff-0.12.8-py3-none-win_arm64.whl", hash = "sha256:c90e1a334683ce41b0e7a04f41790c429bf5073b62c1ae701c9dc5b3d14f0749", size = 11884718 }, + { url = "https://files.pythonhosted.org/packages/c9/1e/c843bfa8ad1114fab3eb2b78235dda76acd66384c663a4e0415ecc13aa1e/ruff-0.12.8-py3-none-linux_armv6l.whl", hash = "sha256:63cb5a5e933fc913e5823a0dfdc3c99add73f52d139d6cd5cc8639d0e0465513", size = 11675315, upload-time = "2025-08-07T19:05:06.15Z" }, + { url = "https://files.pythonhosted.org/packages/24/ee/af6e5c2a8ca3a81676d5480a1025494fd104b8896266502bb4de2a0e8388/ruff-0.12.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a9bbe28f9f551accf84a24c366c1aa8774d6748438b47174f8e8565ab9dedbc", size = 12456653, upload-time = "2025-08-07T19:05:09.759Z" }, + { url = "https://files.pythonhosted.org/packages/99/9d/e91f84dfe3866fa648c10512904991ecc326fd0b66578b324ee6ecb8f725/ruff-0.12.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2fae54e752a3150f7ee0e09bce2e133caf10ce9d971510a9b925392dc98d2fec", size = 11659690, upload-time = "2025-08-07T19:05:12.551Z" }, + { url = "https://files.pythonhosted.org/packages/fe/ac/a363d25ec53040408ebdd4efcee929d48547665858ede0505d1d8041b2e5/ruff-0.12.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0acbcf01206df963d9331b5838fb31f3b44fa979ee7fa368b9b9057d89f4a53", size = 11896923, upload-time = "2025-08-07T19:05:14.821Z" }, + { url = "https://files.pythonhosted.org/packages/58/9f/ea356cd87c395f6ade9bb81365bd909ff60860975ca1bc39f0e59de3da37/ruff-0.12.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae3e7504666ad4c62f9ac8eedb52a93f9ebdeb34742b8b71cd3cccd24912719f", size = 11477612, upload-time = "2025-08-07T19:05:16.712Z" }, + { url = "https://files.pythonhosted.org/packages/1a/46/92e8fa3c9dcfd49175225c09053916cb97bb7204f9f899c2f2baca69e450/ruff-0.12.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb82efb5d35d07497813a1c5647867390a7d83304562607f3579602fa3d7d46f", size = 13182745, upload-time = "2025-08-07T19:05:18.709Z" }, + { url = "https://files.pythonhosted.org/packages/5e/c4/f2176a310f26e6160deaf661ef60db6c3bb62b7a35e57ae28f27a09a7d63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dbea798fc0065ad0b84a2947b0aff4233f0cb30f226f00a2c5850ca4393de609", size = 14206885, upload-time = "2025-08-07T19:05:21.025Z" }, + { url = "https://files.pythonhosted.org/packages/87/9d/98e162f3eeeb6689acbedbae5050b4b3220754554526c50c292b611d3a63/ruff-0.12.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49ebcaccc2bdad86fd51b7864e3d808aad404aab8df33d469b6e65584656263a", size = 13639381, upload-time = "2025-08-07T19:05:23.423Z" }, + { url = "https://files.pythonhosted.org/packages/81/4e/1b7478b072fcde5161b48f64774d6edd59d6d198e4ba8918d9f4702b8043/ruff-0.12.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ac9c570634b98c71c88cb17badd90f13fc076a472ba6ef1d113d8ed3df109fb", size = 12613271, upload-time = "2025-08-07T19:05:25.507Z" }, + { url = "https://files.pythonhosted.org/packages/e8/67/0c3c9179a3ad19791ef1b8f7138aa27d4578c78700551c60d9260b2c660d/ruff-0.12.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:560e0cd641e45591a3e42cb50ef61ce07162b9c233786663fdce2d8557d99818", size = 12847783, upload-time = "2025-08-07T19:05:28.14Z" }, + { url = "https://files.pythonhosted.org/packages/4e/2a/0b6ac3dd045acf8aa229b12c9c17bb35508191b71a14904baf99573a21bd/ruff-0.12.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:71c83121512e7743fba5a8848c261dcc454cafb3ef2934a43f1b7a4eb5a447ea", size = 11702672, upload-time = "2025-08-07T19:05:30.413Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ee/f9fdc9f341b0430110de8b39a6ee5fa68c5706dc7c0aa940817947d6937e/ruff-0.12.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:de4429ef2ba091ecddedd300f4c3f24bca875d3d8b23340728c3cb0da81072c3", size = 11440626, upload-time = "2025-08-07T19:05:32.492Z" }, + { url = "https://files.pythonhosted.org/packages/89/fb/b3aa2d482d05f44e4d197d1de5e3863feb13067b22c571b9561085c999dc/ruff-0.12.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a2cab5f60d5b65b50fba39a8950c8746df1627d54ba1197f970763917184b161", size = 12462162, upload-time = "2025-08-07T19:05:34.449Z" }, + { url = "https://files.pythonhosted.org/packages/18/9f/5c5d93e1d00d854d5013c96e1a92c33b703a0332707a7cdbd0a4880a84fb/ruff-0.12.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:45c32487e14f60b88aad6be9fd5da5093dbefb0e3e1224131cb1d441d7cb7d46", size = 12913212, upload-time = "2025-08-07T19:05:36.541Z" }, + { url = "https://files.pythonhosted.org/packages/71/13/ab9120add1c0e4604c71bfc2e4ef7d63bebece0cfe617013da289539cef8/ruff-0.12.8-py3-none-win32.whl", hash = "sha256:daf3475060a617fd5bc80638aeaf2f5937f10af3ec44464e280a9d2218e720d3", size = 11694382, upload-time = "2025-08-07T19:05:38.468Z" }, + { url = "https://files.pythonhosted.org/packages/f6/dc/a2873b7c5001c62f46266685863bee2888caf469d1edac84bf3242074be2/ruff-0.12.8-py3-none-win_amd64.whl", hash = "sha256:7209531f1a1fcfbe8e46bcd7ab30e2f43604d8ba1c49029bb420b103d0b5f76e", size = 12740482, upload-time = "2025-08-07T19:05:40.391Z" }, + { url = "https://files.pythonhosted.org/packages/cb/5c/799a1efb8b5abab56e8a9f2a0b72d12bd64bb55815e9476c7d0a2887d2f7/ruff-0.12.8-py3-none-win_arm64.whl", hash = "sha256:c90e1a334683ce41b0e7a04f41790c429bf5073b62c1ae701c9dc5b3d14f0749", size = 11884718, upload-time = "2025-08-07T19:05:42.866Z" }, +] + +[[package]] +name = "simple-websocket" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wsproto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b0/d4/bfa032f961103eba93de583b161f0e6a5b63cebb8f2c7d0c6e6efe1e3d2e/simple_websocket-1.1.0.tar.gz", hash = "sha256:7939234e7aa067c534abdab3a9ed933ec9ce4691b0713c78acb195560aa52ae4", size = 17300, upload-time = "2024-10-10T22:39:31.412Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl", hash = "sha256:4af6069630a38ed6c561010f0e11a5bc0d4ca569b36306eb257cd9a192497c8c", size = 13842, upload-time = "2024-10-10T22:39:29.645Z" }, ] [[package]] name = "six" version = "1.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] [[package]] name = "sniffio" version = "1.3.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, ] [[package]] @@ -497,9 +1050,9 @@ dependencies = [ { name = "anyio" }, { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/57/d062573f391d062710d4088fa1369428c38d51460ab6fedff920efef932e/starlette-0.47.2.tar.gz", hash = "sha256:6ae9aa5db235e4846decc1e7b79c4f346adf41e9777aebeb49dfd09bbd7023d8", size = 2583948 } +sdist = { url = "https://files.pythonhosted.org/packages/04/57/d062573f391d062710d4088fa1369428c38d51460ab6fedff920efef932e/starlette-0.47.2.tar.gz", hash = "sha256:6ae9aa5db235e4846decc1e7b79c4f346adf41e9777aebeb49dfd09bbd7023d8", size = 2583948, upload-time = "2025-07-20T17:31:58.522Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/1f/b876b1f83aef204198a42dc101613fefccb32258e5428b5f9259677864b4/starlette-0.47.2-py3-none-any.whl", hash = "sha256:c5847e96134e5c5371ee9fac6fdf1a67336d5815e09eb2a01fdb57a351ef915b", size = 72984 }, + { url = "https://files.pythonhosted.org/packages/f7/1f/b876b1f83aef204198a42dc101613fefccb32258e5428b5f9259677864b4/starlette-0.47.2-py3-none-any.whl", hash = "sha256:c5847e96134e5c5371ee9fac6fdf1a67336d5815e09eb2a01fdb57a351ef915b", size = 72984, upload-time = "2025-07-20T17:31:56.738Z" }, ] [[package]] @@ -511,18 +1064,18 @@ dependencies = [ { name = "httpx", extra = ["http2"] }, { name = "python-dateutil" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/e2/280fe75f65e7a3ca680b7843acfc572a63aa41230e3d3c54c66568809c85/storage3-0.12.1.tar.gz", hash = "sha256:32ea8f5eb2f7185c2114a4f6ae66d577722e32503f0a30b56e7ed5c7f13e6b48", size = 10198 } +sdist = { url = "https://files.pythonhosted.org/packages/b9/e2/280fe75f65e7a3ca680b7843acfc572a63aa41230e3d3c54c66568809c85/storage3-0.12.1.tar.gz", hash = "sha256:32ea8f5eb2f7185c2114a4f6ae66d577722e32503f0a30b56e7ed5c7f13e6b48", size = 10198, upload-time = "2025-08-05T18:09:11.989Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/3b/c5f8709fc5349928e591fee47592eeff78d29a7d75b097f96a4e01de028d/storage3-0.12.1-py3-none-any.whl", hash = "sha256:9da77fd4f406b019fdcba201e9916aefbf615ef87f551253ce427d8136459a34", size = 18420 }, + { url = "https://files.pythonhosted.org/packages/7f/3b/c5f8709fc5349928e591fee47592eeff78d29a7d75b097f96a4e01de028d/storage3-0.12.1-py3-none-any.whl", hash = "sha256:9da77fd4f406b019fdcba201e9916aefbf615ef87f551253ce427d8136459a34", size = 18420, upload-time = "2025-08-05T18:09:10.365Z" }, ] [[package]] name = "strenum" version = "0.4.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/85/ad/430fb60d90e1d112a62ff57bdd1f286ec73a2a0331272febfddd21f330e1/StrEnum-0.4.15.tar.gz", hash = "sha256:878fb5ab705442070e4dd1929bb5e2249511c0bcf2b0eeacf3bcd80875c82eff", size = 23384 } +sdist = { url = "https://files.pythonhosted.org/packages/85/ad/430fb60d90e1d112a62ff57bdd1f286ec73a2a0331272febfddd21f330e1/StrEnum-0.4.15.tar.gz", hash = "sha256:878fb5ab705442070e4dd1929bb5e2249511c0bcf2b0eeacf3bcd80875c82eff", size = 23384, upload-time = "2023-06-29T22:02:58.399Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/81/69/297302c5f5f59c862faa31e6cb9a4cd74721cd1e052b38e464c5b402df8b/StrEnum-0.4.15-py3-none-any.whl", hash = "sha256:a30cda4af7cc6b5bf52c8055bc4bf4b2b6b14a93b574626da33df53cf7740659", size = 8851 }, + { url = "https://files.pythonhosted.org/packages/81/69/297302c5f5f59c862faa31e6cb9a4cd74721cd1e052b38e464c5b402df8b/StrEnum-0.4.15-py3-none-any.whl", hash = "sha256:a30cda4af7cc6b5bf52c8055bc4bf4b2b6b14a93b574626da33df53cf7740659", size = 8851, upload-time = "2023-06-29T22:02:56.947Z" }, ] [[package]] @@ -537,9 +1090,9 @@ dependencies = [ { name = "storage3" }, { name = "supafunc" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5c/e1/511411018596cfecfac99d9091630606e9a03cb07bd5dec2f15621d38b84/supabase-2.18.0.tar.gz", hash = "sha256:b1e98f0faff6e041e5347393a82524d9d5c2ddb87cb844e7557f967f23d8bc70", size = 11521 } +sdist = { url = "https://files.pythonhosted.org/packages/5c/e1/511411018596cfecfac99d9091630606e9a03cb07bd5dec2f15621d38b84/supabase-2.18.0.tar.gz", hash = "sha256:b1e98f0faff6e041e5347393a82524d9d5c2ddb87cb844e7557f967f23d8bc70", size = 11521, upload-time = "2025-08-05T18:30:25.218Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/78/67238701e0253fdfef222a39df32f9883de2a8b046fa68d1ae47f3e52979/supabase-2.18.0-py3-none-any.whl", hash = "sha256:73774e6edd5ffd02653a99e2e98f92191c4ffb5089dcff3ed93f5d7c18ddaeb3", size = 18677 }, + { url = "https://files.pythonhosted.org/packages/f7/78/67238701e0253fdfef222a39df32f9883de2a8b046fa68d1ae47f3e52979/supabase-2.18.0-py3-none-any.whl", hash = "sha256:73774e6edd5ffd02653a99e2e98f92191c4ffb5089dcff3ed93f5d7c18ddaeb3", size = 18677, upload-time = "2025-08-05T18:30:23.641Z" }, ] [[package]] @@ -550,18 +1103,18 @@ dependencies = [ { name = "httpx", extra = ["http2"] }, { name = "strenum" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e8/4b/16f94bcae8a49f5e09544a4fb0e6ad1c2288038036cefdeedb72fcffd92c/supafunc-0.10.1.tar.gz", hash = "sha256:a5b33c8baecb6b5297d25da29a2503e2ec67ee6986f3d44c137e651b8a59a17d", size = 5036 } +sdist = { url = "https://files.pythonhosted.org/packages/e8/4b/16f94bcae8a49f5e09544a4fb0e6ad1c2288038036cefdeedb72fcffd92c/supafunc-0.10.1.tar.gz", hash = "sha256:a5b33c8baecb6b5297d25da29a2503e2ec67ee6986f3d44c137e651b8a59a17d", size = 5036, upload-time = "2025-06-23T18:26:50.327Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/76/4a/9cbea12d86a741d4e73a6e278c2b1d6479fb03d1002efb00e8e71aea76db/supafunc-0.10.1-py3-none-any.whl", hash = "sha256:26df9bd25ff2ef56cb5bfb8962de98f43331f7f8ff69572bac3ed9c3a9672040", size = 8028 }, + { url = "https://files.pythonhosted.org/packages/76/4a/9cbea12d86a741d4e73a6e278c2b1d6479fb03d1002efb00e8e71aea76db/supafunc-0.10.1-py3-none-any.whl", hash = "sha256:26df9bd25ff2ef56cb5bfb8962de98f43331f7f8ff69572bac3ed9c3a9672040", size = 8028, upload-time = "2025-06-23T18:26:49.176Z" }, ] [[package]] name = "typing-extensions" version = "4.14.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673 } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906 }, + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, ] [[package]] @@ -571,9 +1124,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726 } +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552 }, + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, ] [[package]] @@ -584,9 +1137,52 @@ dependencies = [ { name = "click" }, { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473 } +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473, upload-time = "2025-06-28T16:15:46.058Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406 }, + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406, upload-time = "2025-06-28T16:15:44.816Z" }, +] + +[package.optional-dependencies] +standard = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "httptools" }, + { name = "python-dotenv" }, + { name = "pyyaml" }, + { name = "uvloop", marker = "platform_python_implementation != 'PyPy' and sys_platform != 'cygwin' and sys_platform != 'win32'" }, + { name = "watchfiles" }, + { name = "websockets" }, +] + +[[package]] +name = "uvloop" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/c0/854216d09d33c543f12a44b393c402e89a920b1a0a7dc634c42de91b9cf6/uvloop-0.21.0.tar.gz", hash = "sha256:3bf12b0fda68447806a7ad847bfa591613177275d35b6724b1ee573faa3704e3", size = 2492741, upload-time = "2024-10-14T23:38:35.489Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/4c/03f93178830dc7ce8b4cdee1d36770d2f5ebb6f3d37d354e061eefc73545/uvloop-0.21.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:359ec2c888397b9e592a889c4d72ba3d6befba8b2bb01743f72fffbde663b59c", size = 1471284, upload-time = "2024-10-14T23:37:47.833Z" }, + { url = "https://files.pythonhosted.org/packages/43/3e/92c03f4d05e50f09251bd8b2b2b584a2a7f8fe600008bcc4523337abe676/uvloop-0.21.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7089d2dc73179ce5ac255bdf37c236a9f914b264825fdaacaded6990a7fb4c2", size = 821349, upload-time = "2024-10-14T23:37:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/a6/ef/a02ec5da49909dbbfb1fd205a9a1ac4e88ea92dcae885e7c961847cd51e2/uvloop-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baa4dcdbd9ae0a372f2167a207cd98c9f9a1ea1188a8a526431eef2f8116cc8d", size = 4580089, upload-time = "2024-10-14T23:37:51.703Z" }, + { url = "https://files.pythonhosted.org/packages/06/a7/b4e6a19925c900be9f98bec0a75e6e8f79bb53bdeb891916609ab3958967/uvloop-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86975dca1c773a2c9864f4c52c5a55631038e387b47eaf56210f873887b6c8dc", size = 4693770, upload-time = "2024-10-14T23:37:54.122Z" }, + { url = "https://files.pythonhosted.org/packages/ce/0c/f07435a18a4b94ce6bd0677d8319cd3de61f3a9eeb1e5f8ab4e8b5edfcb3/uvloop-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:461d9ae6660fbbafedd07559c6a2e57cd553b34b0065b6550685f6653a98c1cb", size = 4451321, upload-time = "2024-10-14T23:37:55.766Z" }, + { url = "https://files.pythonhosted.org/packages/8f/eb/f7032be105877bcf924709c97b1bf3b90255b4ec251f9340cef912559f28/uvloop-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:183aef7c8730e54c9a3ee3227464daed66e37ba13040bb3f350bc2ddc040f22f", size = 4659022, upload-time = "2024-10-14T23:37:58.195Z" }, + { url = "https://files.pythonhosted.org/packages/3f/8d/2cbef610ca21539f0f36e2b34da49302029e7c9f09acef0b1c3b5839412b/uvloop-0.21.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bfd55dfcc2a512316e65f16e503e9e450cab148ef11df4e4e679b5e8253a5281", size = 1468123, upload-time = "2024-10-14T23:38:00.688Z" }, + { url = "https://files.pythonhosted.org/packages/93/0d/b0038d5a469f94ed8f2b2fce2434a18396d8fbfb5da85a0a9781ebbdec14/uvloop-0.21.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:787ae31ad8a2856fc4e7c095341cccc7209bd657d0e71ad0dc2ea83c4a6fa8af", size = 819325, upload-time = "2024-10-14T23:38:02.309Z" }, + { url = "https://files.pythonhosted.org/packages/50/94/0a687f39e78c4c1e02e3272c6b2ccdb4e0085fda3b8352fecd0410ccf915/uvloop-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ee4d4ef48036ff6e5cfffb09dd192c7a5027153948d85b8da7ff705065bacc6", size = 4582806, upload-time = "2024-10-14T23:38:04.711Z" }, + { url = "https://files.pythonhosted.org/packages/d2/19/f5b78616566ea68edd42aacaf645adbf71fbd83fc52281fba555dc27e3f1/uvloop-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3df876acd7ec037a3d005b3ab85a7e4110422e4d9c1571d4fc89b0fc41b6816", size = 4701068, upload-time = "2024-10-14T23:38:06.385Z" }, + { url = "https://files.pythonhosted.org/packages/47/57/66f061ee118f413cd22a656de622925097170b9380b30091b78ea0c6ea75/uvloop-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd53ecc9a0f3d87ab847503c2e1552b690362e005ab54e8a48ba97da3924c0dc", size = 4454428, upload-time = "2024-10-14T23:38:08.416Z" }, + { url = "https://files.pythonhosted.org/packages/63/9a/0962b05b308494e3202d3f794a6e85abe471fe3cafdbcf95c2e8c713aabd/uvloop-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a5c39f217ab3c663dc699c04cbd50c13813e31d917642d459fdcec07555cc553", size = 4660018, upload-time = "2024-10-14T23:38:10.888Z" }, +] + +[[package]] +name = "vbuild" +version = "0.8.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pscript" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/be/f0c6204a36440bbcc086bfa25964d009b7391c5a3c74d6e73188efd47adb/vbuild-0.8.2.tar.gz", hash = "sha256:270cd9078349d907dfae6c0e6364a5a5e74cb86183bb5093613f12a18b435fa9", size = 8937, upload-time = "2023-08-03T09:26:36.196Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/3d/7b22abbdb059d551507275a2815bc2b1974e3b9f6a13781c1eac9e858965/vbuild-0.8.2-py2.py3-none-any.whl", hash = "sha256:d76bcc976a1c53b6a5776ac947606f9e7786c25df33a587ebe33ed09dd8a1076", size = 9371, upload-time = "2023-08-03T09:26:35.023Z" }, ] [[package]] @@ -598,38 +1194,182 @@ dependencies = [ { name = "filelock" }, { name = "platformdirs" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/60/4f20960df6c7b363a18a55ab034c8f2bcd5d9770d1f94f9370ec104c1855/virtualenv-20.33.1.tar.gz", hash = "sha256:1b44478d9e261b3fb8baa5e74a0ca3bc0e05f21aa36167bf9cbf850e542765b8", size = 6082160 } +sdist = { url = "https://files.pythonhosted.org/packages/8b/60/4f20960df6c7b363a18a55ab034c8f2bcd5d9770d1f94f9370ec104c1855/virtualenv-20.33.1.tar.gz", hash = "sha256:1b44478d9e261b3fb8baa5e74a0ca3bc0e05f21aa36167bf9cbf850e542765b8", size = 6082160, upload-time = "2025-08-05T16:10:55.605Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/ff/ded57ac5ff40a09e6e198550bab075d780941e0b0f83cbeabd087c59383a/virtualenv-20.33.1-py3-none-any.whl", hash = "sha256:07c19bc66c11acab6a5958b815cbcee30891cd1c2ccf53785a28651a0d8d8a67", size = 6060362 }, + { url = "https://files.pythonhosted.org/packages/ca/ff/ded57ac5ff40a09e6e198550bab075d780941e0b0f83cbeabd087c59383a/virtualenv-20.33.1-py3-none-any.whl", hash = "sha256:07c19bc66c11acab6a5958b815cbcee30891cd1c2ccf53785a28651a0d8d8a67", size = 6060362, upload-time = "2025-08-05T16:10:52.81Z" }, +] + +[[package]] +name = "watchfiles" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2a/9a/d451fcc97d029f5812e898fd30a53fd8c15c7bbd058fd75cfc6beb9bd761/watchfiles-1.1.0.tar.gz", hash = "sha256:693ed7ec72cbfcee399e92c895362b6e66d63dac6b91e2c11ae03d10d503e575", size = 94406, upload-time = "2025-06-15T19:06:59.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/b8/858957045a38a4079203a33aaa7d23ea9269ca7761c8a074af3524fbb240/watchfiles-1.1.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9dc001c3e10de4725c749d4c2f2bdc6ae24de5a88a339c4bce32300a31ede179", size = 402339, upload-time = "2025-06-15T19:05:24.516Z" }, + { url = "https://files.pythonhosted.org/packages/80/28/98b222cca751ba68e88521fabd79a4fab64005fc5976ea49b53fa205d1fa/watchfiles-1.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d9ba68ec283153dead62cbe81872d28e053745f12335d037de9cbd14bd1877f5", size = 394409, upload-time = "2025-06-15T19:05:25.469Z" }, + { url = "https://files.pythonhosted.org/packages/86/50/dee79968566c03190677c26f7f47960aff738d32087087bdf63a5473e7df/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:130fc497b8ee68dce163e4254d9b0356411d1490e868bd8790028bc46c5cc297", size = 450939, upload-time = "2025-06-15T19:05:26.494Z" }, + { url = "https://files.pythonhosted.org/packages/40/45/a7b56fb129700f3cfe2594a01aa38d033b92a33dddce86c8dfdfc1247b72/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50a51a90610d0845a5931a780d8e51d7bd7f309ebc25132ba975aca016b576a0", size = 457270, upload-time = "2025-06-15T19:05:27.466Z" }, + { url = "https://files.pythonhosted.org/packages/b5/c8/fa5ef9476b1d02dc6b5e258f515fcaaecf559037edf8b6feffcbc097c4b8/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc44678a72ac0910bac46fa6a0de6af9ba1355669b3dfaf1ce5f05ca7a74364e", size = 483370, upload-time = "2025-06-15T19:05:28.548Z" }, + { url = "https://files.pythonhosted.org/packages/98/68/42cfcdd6533ec94f0a7aab83f759ec11280f70b11bfba0b0f885e298f9bd/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a543492513a93b001975ae283a51f4b67973662a375a403ae82f420d2c7205ee", size = 598654, upload-time = "2025-06-15T19:05:29.997Z" }, + { url = "https://files.pythonhosted.org/packages/d3/74/b2a1544224118cc28df7e59008a929e711f9c68ce7d554e171b2dc531352/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ac164e20d17cc285f2b94dc31c384bc3aa3dd5e7490473b3db043dd70fbccfd", size = 478667, upload-time = "2025-06-15T19:05:31.172Z" }, + { url = "https://files.pythonhosted.org/packages/8c/77/e3362fe308358dc9f8588102481e599c83e1b91c2ae843780a7ded939a35/watchfiles-1.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7590d5a455321e53857892ab8879dce62d1f4b04748769f5adf2e707afb9d4f", size = 452213, upload-time = "2025-06-15T19:05:32.299Z" }, + { url = "https://files.pythonhosted.org/packages/6e/17/c8f1a36540c9a1558d4faf08e909399e8133599fa359bf52ec8fcee5be6f/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:37d3d3f7defb13f62ece99e9be912afe9dd8a0077b7c45ee5a57c74811d581a4", size = 626718, upload-time = "2025-06-15T19:05:33.415Z" }, + { url = "https://files.pythonhosted.org/packages/26/45/fb599be38b4bd38032643783d7496a26a6f9ae05dea1a42e58229a20ac13/watchfiles-1.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7080c4bb3efd70a07b1cc2df99a7aa51d98685be56be6038c3169199d0a1c69f", size = 623098, upload-time = "2025-06-15T19:05:34.534Z" }, + { url = "https://files.pythonhosted.org/packages/a1/e7/fdf40e038475498e160cd167333c946e45d8563ae4dd65caf757e9ffe6b4/watchfiles-1.1.0-cp312-cp312-win32.whl", hash = "sha256:cbcf8630ef4afb05dc30107bfa17f16c0896bb30ee48fc24bf64c1f970f3b1fd", size = 279209, upload-time = "2025-06-15T19:05:35.577Z" }, + { url = "https://files.pythonhosted.org/packages/3f/d3/3ae9d5124ec75143bdf088d436cba39812122edc47709cd2caafeac3266f/watchfiles-1.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:cbd949bdd87567b0ad183d7676feb98136cde5bb9025403794a4c0db28ed3a47", size = 292786, upload-time = "2025-06-15T19:05:36.559Z" }, + { url = "https://files.pythonhosted.org/packages/26/2f/7dd4fc8b5f2b34b545e19629b4a018bfb1de23b3a496766a2c1165ca890d/watchfiles-1.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:0a7d40b77f07be87c6faa93d0951a0fcd8cbca1ddff60a1b65d741bac6f3a9f6", size = 284343, upload-time = "2025-06-15T19:05:37.5Z" }, + { url = "https://files.pythonhosted.org/packages/d3/42/fae874df96595556a9089ade83be34a2e04f0f11eb53a8dbf8a8a5e562b4/watchfiles-1.1.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5007f860c7f1f8df471e4e04aaa8c43673429047d63205d1630880f7637bca30", size = 402004, upload-time = "2025-06-15T19:05:38.499Z" }, + { url = "https://files.pythonhosted.org/packages/fa/55/a77e533e59c3003d9803c09c44c3651224067cbe7fb5d574ddbaa31e11ca/watchfiles-1.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:20ecc8abbd957046f1fe9562757903f5eaf57c3bce70929fda6c7711bb58074a", size = 393671, upload-time = "2025-06-15T19:05:39.52Z" }, + { url = "https://files.pythonhosted.org/packages/05/68/b0afb3f79c8e832e6571022611adbdc36e35a44e14f129ba09709aa4bb7a/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2f0498b7d2a3c072766dba3274fe22a183dbea1f99d188f1c6c72209a1063dc", size = 449772, upload-time = "2025-06-15T19:05:40.897Z" }, + { url = "https://files.pythonhosted.org/packages/ff/05/46dd1f6879bc40e1e74c6c39a1b9ab9e790bf1f5a2fe6c08b463d9a807f4/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:239736577e848678e13b201bba14e89718f5c2133dfd6b1f7846fa1b58a8532b", size = 456789, upload-time = "2025-06-15T19:05:42.045Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ca/0eeb2c06227ca7f12e50a47a3679df0cd1ba487ea19cf844a905920f8e95/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eff4b8d89f444f7e49136dc695599a591ff769300734446c0a86cba2eb2f9895", size = 482551, upload-time = "2025-06-15T19:05:43.781Z" }, + { url = "https://files.pythonhosted.org/packages/31/47/2cecbd8694095647406645f822781008cc524320466ea393f55fe70eed3b/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12b0a02a91762c08f7264e2e79542f76870c3040bbc847fb67410ab81474932a", size = 597420, upload-time = "2025-06-15T19:05:45.244Z" }, + { url = "https://files.pythonhosted.org/packages/d9/7e/82abc4240e0806846548559d70f0b1a6dfdca75c1b4f9fa62b504ae9b083/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:29e7bc2eee15cbb339c68445959108803dc14ee0c7b4eea556400131a8de462b", size = 477950, upload-time = "2025-06-15T19:05:46.332Z" }, + { url = "https://files.pythonhosted.org/packages/25/0d/4d564798a49bf5482a4fa9416dea6b6c0733a3b5700cb8a5a503c4b15853/watchfiles-1.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9481174d3ed982e269c090f780122fb59cee6c3796f74efe74e70f7780ed94c", size = 451706, upload-time = "2025-06-15T19:05:47.459Z" }, + { url = "https://files.pythonhosted.org/packages/81/b5/5516cf46b033192d544102ea07c65b6f770f10ed1d0a6d388f5d3874f6e4/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:80f811146831c8c86ab17b640801c25dc0a88c630e855e2bef3568f30434d52b", size = 625814, upload-time = "2025-06-15T19:05:48.654Z" }, + { url = "https://files.pythonhosted.org/packages/0c/dd/7c1331f902f30669ac3e754680b6edb9a0dd06dea5438e61128111fadd2c/watchfiles-1.1.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:60022527e71d1d1fda67a33150ee42869042bce3d0fcc9cc49be009a9cded3fb", size = 622820, upload-time = "2025-06-15T19:05:50.088Z" }, + { url = "https://files.pythonhosted.org/packages/1b/14/36d7a8e27cd128d7b1009e7715a7c02f6c131be9d4ce1e5c3b73d0e342d8/watchfiles-1.1.0-cp313-cp313-win32.whl", hash = "sha256:32d6d4e583593cb8576e129879ea0991660b935177c0f93c6681359b3654bfa9", size = 279194, upload-time = "2025-06-15T19:05:51.186Z" }, + { url = "https://files.pythonhosted.org/packages/25/41/2dd88054b849aa546dbeef5696019c58f8e0774f4d1c42123273304cdb2e/watchfiles-1.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:f21af781a4a6fbad54f03c598ab620e3a77032c5878f3d780448421a6e1818c7", size = 292349, upload-time = "2025-06-15T19:05:52.201Z" }, + { url = "https://files.pythonhosted.org/packages/c8/cf/421d659de88285eb13941cf11a81f875c176f76a6d99342599be88e08d03/watchfiles-1.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:5366164391873ed76bfdf618818c82084c9db7fac82b64a20c44d335eec9ced5", size = 283836, upload-time = "2025-06-15T19:05:53.265Z" }, + { url = "https://files.pythonhosted.org/packages/45/10/6faf6858d527e3599cc50ec9fcae73590fbddc1420bd4fdccfebffeedbc6/watchfiles-1.1.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:17ab167cca6339c2b830b744eaf10803d2a5b6683be4d79d8475d88b4a8a4be1", size = 400343, upload-time = "2025-06-15T19:05:54.252Z" }, + { url = "https://files.pythonhosted.org/packages/03/20/5cb7d3966f5e8c718006d0e97dfe379a82f16fecd3caa7810f634412047a/watchfiles-1.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:328dbc9bff7205c215a7807da7c18dce37da7da718e798356212d22696404339", size = 392916, upload-time = "2025-06-15T19:05:55.264Z" }, + { url = "https://files.pythonhosted.org/packages/8c/07/d8f1176328fa9e9581b6f120b017e286d2a2d22ae3f554efd9515c8e1b49/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7208ab6e009c627b7557ce55c465c98967e8caa8b11833531fdf95799372633", size = 449582, upload-time = "2025-06-15T19:05:56.317Z" }, + { url = "https://files.pythonhosted.org/packages/66/e8/80a14a453cf6038e81d072a86c05276692a1826471fef91df7537dba8b46/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a8f6f72974a19efead54195bc9bed4d850fc047bb7aa971268fd9a8387c89011", size = 456752, upload-time = "2025-06-15T19:05:57.359Z" }, + { url = "https://files.pythonhosted.org/packages/5a/25/0853b3fe0e3c2f5af9ea60eb2e781eade939760239a72c2d38fc4cc335f6/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d181ef50923c29cf0450c3cd47e2f0557b62218c50b2ab8ce2ecaa02bd97e670", size = 481436, upload-time = "2025-06-15T19:05:58.447Z" }, + { url = "https://files.pythonhosted.org/packages/fe/9e/4af0056c258b861fbb29dcb36258de1e2b857be4a9509e6298abcf31e5c9/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adb4167043d3a78280d5d05ce0ba22055c266cf8655ce942f2fb881262ff3cdf", size = 596016, upload-time = "2025-06-15T19:05:59.59Z" }, + { url = "https://files.pythonhosted.org/packages/c5/fa/95d604b58aa375e781daf350897aaaa089cff59d84147e9ccff2447c8294/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5701dc474b041e2934a26d31d39f90fac8a3dee2322b39f7729867f932b1d4", size = 476727, upload-time = "2025-06-15T19:06:01.086Z" }, + { url = "https://files.pythonhosted.org/packages/65/95/fe479b2664f19be4cf5ceeb21be05afd491d95f142e72d26a42f41b7c4f8/watchfiles-1.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b067915e3c3936966a8607f6fe5487df0c9c4afb85226613b520890049deea20", size = 451864, upload-time = "2025-06-15T19:06:02.144Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8a/3c4af14b93a15ce55901cd7a92e1a4701910f1768c78fb30f61d2b79785b/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:9c733cda03b6d636b4219625a4acb5c6ffb10803338e437fb614fef9516825ef", size = 625626, upload-time = "2025-06-15T19:06:03.578Z" }, + { url = "https://files.pythonhosted.org/packages/da/f5/cf6aa047d4d9e128f4b7cde615236a915673775ef171ff85971d698f3c2c/watchfiles-1.1.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:cc08ef8b90d78bfac66f0def80240b0197008e4852c9f285907377b2947ffdcb", size = 622744, upload-time = "2025-06-15T19:06:05.066Z" }, + { url = "https://files.pythonhosted.org/packages/2c/00/70f75c47f05dea6fd30df90f047765f6fc2d6eb8b5a3921379b0b04defa2/watchfiles-1.1.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:9974d2f7dc561cce3bb88dfa8eb309dab64c729de85fba32e98d75cf24b66297", size = 402114, upload-time = "2025-06-15T19:06:06.186Z" }, + { url = "https://files.pythonhosted.org/packages/53/03/acd69c48db4a1ed1de26b349d94077cca2238ff98fd64393f3e97484cae6/watchfiles-1.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c68e9f1fcb4d43798ad8814c4c1b61547b014b667216cb754e606bfade587018", size = 393879, upload-time = "2025-06-15T19:06:07.369Z" }, + { url = "https://files.pythonhosted.org/packages/2f/c8/a9a2a6f9c8baa4eceae5887fecd421e1b7ce86802bcfc8b6a942e2add834/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95ab1594377effac17110e1352989bdd7bdfca9ff0e5eeccd8c69c5389b826d0", size = 450026, upload-time = "2025-06-15T19:06:08.476Z" }, + { url = "https://files.pythonhosted.org/packages/fe/51/d572260d98388e6e2b967425c985e07d47ee6f62e6455cefb46a6e06eda5/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fba9b62da882c1be1280a7584ec4515d0a6006a94d6e5819730ec2eab60ffe12", size = 457917, upload-time = "2025-06-15T19:06:09.988Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2d/4258e52917bf9f12909b6ec314ff9636276f3542f9d3807d143f27309104/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3434e401f3ce0ed6b42569128b3d1e3af773d7ec18751b918b89cd49c14eaafb", size = 483602, upload-time = "2025-06-15T19:06:11.088Z" }, + { url = "https://files.pythonhosted.org/packages/84/99/bee17a5f341a4345fe7b7972a475809af9e528deba056f8963d61ea49f75/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa257a4d0d21fcbca5b5fcba9dca5a78011cb93c0323fb8855c6d2dfbc76eb77", size = 596758, upload-time = "2025-06-15T19:06:12.197Z" }, + { url = "https://files.pythonhosted.org/packages/40/76/e4bec1d59b25b89d2b0716b41b461ed655a9a53c60dc78ad5771fda5b3e6/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fd1b3879a578a8ec2076c7961076df540b9af317123f84569f5a9ddee64ce92", size = 477601, upload-time = "2025-06-15T19:06:13.391Z" }, + { url = "https://files.pythonhosted.org/packages/1f/fa/a514292956f4a9ce3c567ec0c13cce427c158e9f272062685a8a727d08fc/watchfiles-1.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62cc7a30eeb0e20ecc5f4bd113cd69dcdb745a07c68c0370cea919f373f65d9e", size = 451936, upload-time = "2025-06-15T19:06:14.656Z" }, + { url = "https://files.pythonhosted.org/packages/32/5d/c3bf927ec3bbeb4566984eba8dd7a8eb69569400f5509904545576741f88/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:891c69e027748b4a73847335d208e374ce54ca3c335907d381fde4e41661b13b", size = 626243, upload-time = "2025-06-15T19:06:16.232Z" }, + { url = "https://files.pythonhosted.org/packages/e6/65/6e12c042f1a68c556802a84d54bb06d35577c81e29fba14019562479159c/watchfiles-1.1.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:12fe8eaffaf0faa7906895b4f8bb88264035b3f0243275e0bf24af0436b27259", size = 623073, upload-time = "2025-06-15T19:06:17.457Z" }, + { url = "https://files.pythonhosted.org/packages/89/ab/7f79d9bf57329e7cbb0a6fd4c7bd7d0cee1e4a8ef0041459f5409da3506c/watchfiles-1.1.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:bfe3c517c283e484843cb2e357dd57ba009cff351edf45fb455b5fbd1f45b15f", size = 400872, upload-time = "2025-06-15T19:06:18.57Z" }, + { url = "https://files.pythonhosted.org/packages/df/d5/3f7bf9912798e9e6c516094db6b8932df53b223660c781ee37607030b6d3/watchfiles-1.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a9ccbf1f129480ed3044f540c0fdbc4ee556f7175e5ab40fe077ff6baf286d4e", size = 392877, upload-time = "2025-06-15T19:06:19.55Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c5/54ec7601a2798604e01c75294770dbee8150e81c6e471445d7601610b495/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba0e3255b0396cac3cc7bbace76404dd72b5438bf0d8e7cefa2f79a7f3649caa", size = 449645, upload-time = "2025-06-15T19:06:20.66Z" }, + { url = "https://files.pythonhosted.org/packages/0a/04/c2f44afc3b2fce21ca0b7802cbd37ed90a29874f96069ed30a36dfe57c2b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4281cd9fce9fc0a9dbf0fc1217f39bf9cf2b4d315d9626ef1d4e87b84699e7e8", size = 457424, upload-time = "2025-06-15T19:06:21.712Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b0/eec32cb6c14d248095261a04f290636da3df3119d4040ef91a4a50b29fa5/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d2404af8db1329f9a3c9b79ff63e0ae7131986446901582067d9304ae8aaf7f", size = 481584, upload-time = "2025-06-15T19:06:22.777Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e2/ca4bb71c68a937d7145aa25709e4f5d68eb7698a25ce266e84b55d591bbd/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e78b6ed8165996013165eeabd875c5dfc19d41b54f94b40e9fff0eb3193e5e8e", size = 596675, upload-time = "2025-06-15T19:06:24.226Z" }, + { url = "https://files.pythonhosted.org/packages/a1/dd/b0e4b7fb5acf783816bc950180a6cd7c6c1d2cf7e9372c0ea634e722712b/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:249590eb75ccc117f488e2fabd1bfa33c580e24b96f00658ad88e38844a040bb", size = 477363, upload-time = "2025-06-15T19:06:25.42Z" }, + { url = "https://files.pythonhosted.org/packages/69/c4/088825b75489cb5b6a761a4542645718893d395d8c530b38734f19da44d2/watchfiles-1.1.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05686b5487cfa2e2c28ff1aa370ea3e6c5accfe6435944ddea1e10d93872147", size = 452240, upload-time = "2025-06-15T19:06:26.552Z" }, + { url = "https://files.pythonhosted.org/packages/10/8c/22b074814970eeef43b7c44df98c3e9667c1f7bf5b83e0ff0201b0bd43f9/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d0e10e6f8f6dc5762adee7dece33b722282e1f59aa6a55da5d493a97282fedd8", size = 625607, upload-time = "2025-06-15T19:06:27.606Z" }, + { url = "https://files.pythonhosted.org/packages/32/fa/a4f5c2046385492b2273213ef815bf71a0d4c1943b784fb904e184e30201/watchfiles-1.1.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:af06c863f152005c7592df1d6a7009c836a247c9d8adb78fef8575a5a98699db", size = 623315, upload-time = "2025-06-15T19:06:29.076Z" }, ] [[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 } -wheels = [ - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { url = "https://files.pythonhosted.org/packages/ff/83/de1f7709376dc3ca9b7eeb4b9a07b4526b14876b6d372a4dc62312bebee0/websockets-15.0.1-cp312-cp312-win32.whl", hash = "sha256:c338ffa0520bdb12fbc527265235639fb76e7bc7faafbb93f6ba80d9c06578a9", size = 176395 }, - { url = "https://files.pythonhosted.org/packages/7d/71/abf2ebc3bbfa40f391ce1428c7168fb20582d0ff57019b69ea20fa698043/websockets-15.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:fcd5cf9e305d7b8338754470cf69cf81f420459dbae8a3b40cee57417f4614a7", size = 176841 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { 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 }, - { url = "https://files.pythonhosted.org/packages/86/eb/20b6cdf273913d0ad05a6a14aed4b9a85591c18a987a3d47f20fa13dcc47/websockets-15.0.1-cp313-cp313-win32.whl", hash = "sha256:ba9e56e8ceeeedb2e080147ba85ffcd5cd0711b89576b83784d8605a7df455fa", size = 176393 }, - { url = "https://files.pythonhosted.org/packages/1b/6c/c65773d6cab416a64d191d6ee8a8b1c68a09970ea6909d16965d26bfed1e/websockets-15.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:e09473f095a819042ecb2ab9465aee615bd9c2028e4ef7d933600a8401c79561", size = 176837 }, - { url = "https://files.pythonhosted.org/packages/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743 }, +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/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/fa/a8/5b41e0da817d64113292ab1f8247140aac61cbf6cfd085d6a0fa77f4984f/websockets-15.0.1-py3-none-any.whl", hash = "sha256:f7a866fbc1e97b5c617ee4116daaa09b722101d4a3c170c787450ba409f9736f", size = 169743, upload-time = "2025-03-05T20:03:39.41Z" }, +] + +[[package]] +name = "wsproto" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425, upload-time = "2022-08-23T19:58:21.447Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226, upload-time = "2022-08-23T19:58:19.96Z" }, +] + +[[package]] +name = "yarl" +version = "1.20.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "multidict" }, + { name = "propcache" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3c/fb/efaa23fa4e45537b827620f04cf8f3cd658b76642205162e072703a5b963/yarl-1.20.1.tar.gz", hash = "sha256:d017a4997ee50c91fd5466cef416231bb82177b93b029906cefc542ce14c35ac", size = 186428, upload-time = "2025-06-10T00:46:09.923Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/9a/cb7fad7d73c69f296eda6815e4a2c7ed53fc70c2f136479a91c8e5fbdb6d/yarl-1.20.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdcc4cd244e58593a4379fe60fdee5ac0331f8eb70320a24d591a3be197b94a9", size = 133667, upload-time = "2025-06-10T00:43:44.369Z" }, + { url = "https://files.pythonhosted.org/packages/67/38/688577a1cb1e656e3971fb66a3492501c5a5df56d99722e57c98249e5b8a/yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a", size = 91025, upload-time = "2025-06-10T00:43:46.295Z" }, + { url = "https://files.pythonhosted.org/packages/50/ec/72991ae51febeb11a42813fc259f0d4c8e0507f2b74b5514618d8b640365/yarl-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1112ae8154186dfe2de4732197f59c05a83dc814849a5ced892b708033f40dc2", size = 89709, upload-time = "2025-06-10T00:43:48.22Z" }, + { url = "https://files.pythonhosted.org/packages/99/da/4d798025490e89426e9f976702e5f9482005c548c579bdae792a4c37769e/yarl-1.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90bbd29c4fe234233f7fa2b9b121fb63c321830e5d05b45153a2ca68f7d310ee", size = 352287, upload-time = "2025-06-10T00:43:49.924Z" }, + { url = "https://files.pythonhosted.org/packages/1a/26/54a15c6a567aac1c61b18aa0f4b8aa2e285a52d547d1be8bf48abe2b3991/yarl-1.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:680e19c7ce3710ac4cd964e90dad99bf9b5029372ba0c7cbfcd55e54d90ea819", size = 345429, upload-time = "2025-06-10T00:43:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/d6/95/9dcf2386cb875b234353b93ec43e40219e14900e046bf6ac118f94b1e353/yarl-1.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a979218c1fdb4246a05efc2cc23859d47c89af463a90b99b7c56094daf25a16", size = 365429, upload-time = "2025-06-10T00:43:53.494Z" }, + { url = "https://files.pythonhosted.org/packages/91/b2/33a8750f6a4bc224242a635f5f2cff6d6ad5ba651f6edcccf721992c21a0/yarl-1.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255b468adf57b4a7b65d8aad5b5138dce6a0752c139965711bdcb81bc370e1b6", size = 363862, upload-time = "2025-06-10T00:43:55.766Z" }, + { url = "https://files.pythonhosted.org/packages/98/28/3ab7acc5b51f4434b181b0cee8f1f4b77a65919700a355fb3617f9488874/yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd", size = 355616, upload-time = "2025-06-10T00:43:58.056Z" }, + { url = "https://files.pythonhosted.org/packages/36/a3/f666894aa947a371724ec7cd2e5daa78ee8a777b21509b4252dd7bd15e29/yarl-1.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8570d998db4ddbfb9a590b185a0a33dbf8aafb831d07a5257b4ec9948df9cb0a", size = 339954, upload-time = "2025-06-10T00:43:59.773Z" }, + { url = "https://files.pythonhosted.org/packages/f1/81/5f466427e09773c04219d3450d7a1256138a010b6c9f0af2d48565e9ad13/yarl-1.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:97c75596019baae7c71ccf1d8cc4738bc08134060d0adfcbe5642f778d1dca38", size = 365575, upload-time = "2025-06-10T00:44:02.051Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e3/e4b0ad8403e97e6c9972dd587388940a032f030ebec196ab81a3b8e94d31/yarl-1.20.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c48912653e63aef91ff988c5432832692ac5a1d8f0fb8a33091520b5bbe19ef", size = 365061, upload-time = "2025-06-10T00:44:04.196Z" }, + { url = "https://files.pythonhosted.org/packages/ac/99/b8a142e79eb86c926f9f06452eb13ecb1bb5713bd01dc0038faf5452e544/yarl-1.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4c3ae28f3ae1563c50f3d37f064ddb1511ecc1d5584e88c6b7c63cf7702a6d5f", size = 364142, upload-time = "2025-06-10T00:44:06.527Z" }, + { url = "https://files.pythonhosted.org/packages/34/f2/08ed34a4a506d82a1a3e5bab99ccd930a040f9b6449e9fd050320e45845c/yarl-1.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e9642f27036283550f5f57dc6156c51084b458570b9d0d96100c8bebb186a8", size = 381894, upload-time = "2025-06-10T00:44:08.379Z" }, + { url = "https://files.pythonhosted.org/packages/92/f8/9a3fbf0968eac704f681726eff595dce9b49c8a25cd92bf83df209668285/yarl-1.20.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2c26b0c49220d5799f7b22c6838409ee9bc58ee5c95361a4d7831f03cc225b5a", size = 383378, upload-time = "2025-06-10T00:44:10.51Z" }, + { url = "https://files.pythonhosted.org/packages/af/85/9363f77bdfa1e4d690957cd39d192c4cacd1c58965df0470a4905253b54f/yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004", size = 374069, upload-time = "2025-06-10T00:44:12.834Z" }, + { url = "https://files.pythonhosted.org/packages/35/99/9918c8739ba271dcd935400cff8b32e3cd319eaf02fcd023d5dcd487a7c8/yarl-1.20.1-cp312-cp312-win32.whl", hash = "sha256:daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5", size = 81249, upload-time = "2025-06-10T00:44:14.731Z" }, + { url = "https://files.pythonhosted.org/packages/eb/83/5d9092950565481b413b31a23e75dd3418ff0a277d6e0abf3729d4d1ce25/yarl-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698", size = 86710, upload-time = "2025-06-10T00:44:16.716Z" }, + { url = "https://files.pythonhosted.org/packages/8a/e1/2411b6d7f769a07687acee88a062af5833cf1966b7266f3d8dfb3d3dc7d3/yarl-1.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0b5ff0fbb7c9f1b1b5ab53330acbfc5247893069e7716840c8e7d5bb7355038a", size = 131811, upload-time = "2025-06-10T00:44:18.933Z" }, + { url = "https://files.pythonhosted.org/packages/b2/27/584394e1cb76fb771371770eccad35de400e7b434ce3142c2dd27392c968/yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3", size = 90078, upload-time = "2025-06-10T00:44:20.635Z" }, + { url = "https://files.pythonhosted.org/packages/bf/9a/3246ae92d4049099f52d9b0fe3486e3b500e29b7ea872d0f152966fc209d/yarl-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f60e4ad5db23f0b96e49c018596707c3ae89f5d0bd97f0ad3684bcbad899f1e7", size = 88748, upload-time = "2025-06-10T00:44:22.34Z" }, + { url = "https://files.pythonhosted.org/packages/a3/25/35afe384e31115a1a801fbcf84012d7a066d89035befae7c5d4284df1e03/yarl-1.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49bdd1b8e00ce57e68ba51916e4bb04461746e794e7c4d4bbc42ba2f18297691", size = 349595, upload-time = "2025-06-10T00:44:24.314Z" }, + { url = "https://files.pythonhosted.org/packages/28/2d/8aca6cb2cabc8f12efcb82749b9cefecbccfc7b0384e56cd71058ccee433/yarl-1.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:66252d780b45189975abfed839616e8fd2dbacbdc262105ad7742c6ae58f3e31", size = 342616, upload-time = "2025-06-10T00:44:26.167Z" }, + { url = "https://files.pythonhosted.org/packages/0b/e9/1312633d16b31acf0098d30440ca855e3492d66623dafb8e25b03d00c3da/yarl-1.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59174e7332f5d153d8f7452a102b103e2e74035ad085f404df2e40e663a22b28", size = 361324, upload-time = "2025-06-10T00:44:27.915Z" }, + { url = "https://files.pythonhosted.org/packages/bc/a0/688cc99463f12f7669eec7c8acc71ef56a1521b99eab7cd3abb75af887b0/yarl-1.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3968ec7d92a0c0f9ac34d5ecfd03869ec0cab0697c91a45db3fbbd95fe1b653", size = 359676, upload-time = "2025-06-10T00:44:30.041Z" }, + { url = "https://files.pythonhosted.org/packages/af/44/46407d7f7a56e9a85a4c207724c9f2c545c060380718eea9088f222ba697/yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5", size = 352614, upload-time = "2025-06-10T00:44:32.171Z" }, + { url = "https://files.pythonhosted.org/packages/b1/91/31163295e82b8d5485d31d9cf7754d973d41915cadce070491778d9c9825/yarl-1.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a62c839c3a8eac2410e951301309426f368388ff2f33799052787035793b02", size = 336766, upload-time = "2025-06-10T00:44:34.494Z" }, + { url = "https://files.pythonhosted.org/packages/b4/8e/c41a5bc482121f51c083c4c2bcd16b9e01e1cf8729e380273a952513a21f/yarl-1.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:041eaa14f73ff5a8986b4388ac6bb43a77f2ea09bf1913df7a35d4646db69e53", size = 364615, upload-time = "2025-06-10T00:44:36.856Z" }, + { url = "https://files.pythonhosted.org/packages/e3/5b/61a3b054238d33d70ea06ebba7e58597891b71c699e247df35cc984ab393/yarl-1.20.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:377fae2fef158e8fd9d60b4c8751387b8d1fb121d3d0b8e9b0be07d1b41e83dc", size = 360982, upload-time = "2025-06-10T00:44:39.141Z" }, + { url = "https://files.pythonhosted.org/packages/df/a3/6a72fb83f8d478cb201d14927bc8040af901811a88e0ff2da7842dd0ed19/yarl-1.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1c92f4390e407513f619d49319023664643d3339bd5e5a56a3bebe01bc67ec04", size = 369792, upload-time = "2025-06-10T00:44:40.934Z" }, + { url = "https://files.pythonhosted.org/packages/7c/af/4cc3c36dfc7c077f8dedb561eb21f69e1e9f2456b91b593882b0b18c19dc/yarl-1.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d25ddcf954df1754ab0f86bb696af765c5bfaba39b74095f27eececa049ef9a4", size = 382049, upload-time = "2025-06-10T00:44:42.854Z" }, + { url = "https://files.pythonhosted.org/packages/19/3a/e54e2c4752160115183a66dc9ee75a153f81f3ab2ba4bf79c3c53b33de34/yarl-1.20.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:909313577e9619dcff8c31a0ea2aa0a2a828341d92673015456b3ae492e7317b", size = 384774, upload-time = "2025-06-10T00:44:45.275Z" }, + { url = "https://files.pythonhosted.org/packages/9c/20/200ae86dabfca89060ec6447649f219b4cbd94531e425e50d57e5f5ac330/yarl-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:793fd0580cb9664548c6b83c63b43c477212c0260891ddf86809e1c06c8b08f1", size = 374252, upload-time = "2025-06-10T00:44:47.31Z" }, + { url = "https://files.pythonhosted.org/packages/83/75/11ee332f2f516b3d094e89448da73d557687f7d137d5a0f48c40ff211487/yarl-1.20.1-cp313-cp313-win32.whl", hash = "sha256:468f6e40285de5a5b3c44981ca3a319a4b208ccc07d526b20b12aeedcfa654b7", size = 81198, upload-time = "2025-06-10T00:44:49.164Z" }, + { url = "https://files.pythonhosted.org/packages/ba/ba/39b1ecbf51620b40ab402b0fc817f0ff750f6d92712b44689c2c215be89d/yarl-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:495b4ef2fea40596bfc0affe3837411d6aa3371abcf31aac0ccc4bdd64d4ef5c", size = 86346, upload-time = "2025-06-10T00:44:51.182Z" }, + { url = "https://files.pythonhosted.org/packages/43/c7/669c52519dca4c95153c8ad96dd123c79f354a376346b198f438e56ffeb4/yarl-1.20.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f60233b98423aab21d249a30eb27c389c14929f47be8430efa7dbd91493a729d", size = 138826, upload-time = "2025-06-10T00:44:52.883Z" }, + { url = "https://files.pythonhosted.org/packages/6a/42/fc0053719b44f6ad04a75d7f05e0e9674d45ef62f2d9ad2c1163e5c05827/yarl-1.20.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6f3eff4cc3f03d650d8755c6eefc844edde99d641d0dcf4da3ab27141a5f8ddf", size = 93217, upload-time = "2025-06-10T00:44:54.658Z" }, + { url = "https://files.pythonhosted.org/packages/4f/7f/fa59c4c27e2a076bba0d959386e26eba77eb52ea4a0aac48e3515c186b4c/yarl-1.20.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:69ff8439d8ba832d6bed88af2c2b3445977eba9a4588b787b32945871c2444e3", size = 92700, upload-time = "2025-06-10T00:44:56.784Z" }, + { url = "https://files.pythonhosted.org/packages/2f/d4/062b2f48e7c93481e88eff97a6312dca15ea200e959f23e96d8ab898c5b8/yarl-1.20.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf34efa60eb81dd2645a2e13e00bb98b76c35ab5061a3989c7a70f78c85006d", size = 347644, upload-time = "2025-06-10T00:44:59.071Z" }, + { url = "https://files.pythonhosted.org/packages/89/47/78b7f40d13c8f62b499cc702fdf69e090455518ae544c00a3bf4afc9fc77/yarl-1.20.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8e0fe9364ad0fddab2688ce72cb7a8e61ea42eff3c7caeeb83874a5d479c896c", size = 323452, upload-time = "2025-06-10T00:45:01.605Z" }, + { url = "https://files.pythonhosted.org/packages/eb/2b/490d3b2dc66f52987d4ee0d3090a147ea67732ce6b4d61e362c1846d0d32/yarl-1.20.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f64fbf81878ba914562c672024089e3401974a39767747691c65080a67b18c1", size = 346378, upload-time = "2025-06-10T00:45:03.946Z" }, + { url = "https://files.pythonhosted.org/packages/66/ad/775da9c8a94ce925d1537f939a4f17d782efef1f973039d821cbe4bcc211/yarl-1.20.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6342d643bf9a1de97e512e45e4b9560a043347e779a173250824f8b254bd5ce", size = 353261, upload-time = "2025-06-10T00:45:05.992Z" }, + { url = "https://files.pythonhosted.org/packages/4b/23/0ed0922b47a4f5c6eb9065d5ff1e459747226ddce5c6a4c111e728c9f701/yarl-1.20.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56dac5f452ed25eef0f6e3c6a066c6ab68971d96a9fb441791cad0efba6140d3", size = 335987, upload-time = "2025-06-10T00:45:08.227Z" }, + { url = "https://files.pythonhosted.org/packages/3e/49/bc728a7fe7d0e9336e2b78f0958a2d6b288ba89f25a1762407a222bf53c3/yarl-1.20.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7d7f497126d65e2cad8dc5f97d34c27b19199b6414a40cb36b52f41b79014be", size = 329361, upload-time = "2025-06-10T00:45:10.11Z" }, + { url = "https://files.pythonhosted.org/packages/93/8f/b811b9d1f617c83c907e7082a76e2b92b655400e61730cd61a1f67178393/yarl-1.20.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:67e708dfb8e78d8a19169818eeb5c7a80717562de9051bf2413aca8e3696bf16", size = 346460, upload-time = "2025-06-10T00:45:12.055Z" }, + { url = "https://files.pythonhosted.org/packages/70/fd/af94f04f275f95da2c3b8b5e1d49e3e79f1ed8b6ceb0f1664cbd902773ff/yarl-1.20.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:595c07bc79af2494365cc96ddeb772f76272364ef7c80fb892ef9d0649586513", size = 334486, upload-time = "2025-06-10T00:45:13.995Z" }, + { url = "https://files.pythonhosted.org/packages/84/65/04c62e82704e7dd0a9b3f61dbaa8447f8507655fd16c51da0637b39b2910/yarl-1.20.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7bdd2f80f4a7df852ab9ab49484a4dee8030023aa536df41f2d922fd57bf023f", size = 342219, upload-time = "2025-06-10T00:45:16.479Z" }, + { url = "https://files.pythonhosted.org/packages/91/95/459ca62eb958381b342d94ab9a4b6aec1ddec1f7057c487e926f03c06d30/yarl-1.20.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c03bfebc4ae8d862f853a9757199677ab74ec25424d0ebd68a0027e9c639a390", size = 350693, upload-time = "2025-06-10T00:45:18.399Z" }, + { url = "https://files.pythonhosted.org/packages/a6/00/d393e82dd955ad20617abc546a8f1aee40534d599ff555ea053d0ec9bf03/yarl-1.20.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:344d1103e9c1523f32a5ed704d576172d2cabed3122ea90b1d4e11fe17c66458", size = 355803, upload-time = "2025-06-10T00:45:20.677Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ed/c5fb04869b99b717985e244fd93029c7a8e8febdfcffa06093e32d7d44e7/yarl-1.20.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88cab98aa4e13e1ade8c141daeedd300a4603b7132819c484841bb7af3edce9e", size = 341709, upload-time = "2025-06-10T00:45:23.221Z" }, + { url = "https://files.pythonhosted.org/packages/24/fd/725b8e73ac2a50e78a4534ac43c6addf5c1c2d65380dd48a9169cc6739a9/yarl-1.20.1-cp313-cp313t-win32.whl", hash = "sha256:b121ff6a7cbd4abc28985b6028235491941b9fe8fe226e6fdc539c977ea1739d", size = 86591, upload-time = "2025-06-10T00:45:25.793Z" }, + { url = "https://files.pythonhosted.org/packages/94/c3/b2e9f38bc3e11191981d57ea08cab2166e74ea770024a646617c9cddd9f6/yarl-1.20.1-cp313-cp313t-win_amd64.whl", hash = "sha256:541d050a355bbbc27e55d906bc91cb6fe42f96c01413dd0f4ed5a5240513874f", size = 93003, upload-time = "2025-06-10T00:45:27.752Z" }, + { url = "https://files.pythonhosted.org/packages/b4/2d/2345fce04cfd4bee161bf1e7d9cdc702e3e16109021035dbb24db654a622/yarl-1.20.1-py3-none-any.whl", hash = "sha256:83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77", size = 46542, upload-time = "2025-06-10T00:46:07.521Z" }, ] From 73792bcb41c1f076bcddd8732eccdc53a4d93578 Mon Sep 17 00:00:00 2001 From: PiLogic Date: Fri, 15 Aug 2025 10:45:05 +0100 Subject: [PATCH 079/198] Fixed text movement feature --- packages/editor/scripts/editor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index acdf91a0..e9885dd6 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -158,7 +158,7 @@ def show_action_icon(x: float, y: float) -> bool: if ctx.moving_image: buffer_ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) return True - if ctx.writing_text: + if not(ctx.text_placed): text_dimensions = ctx.measureText(ctx.text_value) buffer_ctx.fillText( ctx.text_value, From 5acc6dbd9427e2174e9a49474615126706e60386 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 14:07:06 +0100 Subject: [PATCH 080/198] Fix formatting --- packages/editor/main.py | 22 ++-- packages/editor/scripts/canvas_ctx.py | 165 +++++++++++++------------- packages/editor/scripts/editor.py | 1 + 3 files changed, 98 insertions(+), 90 deletions(-) diff --git a/packages/editor/main.py b/packages/editor/main.py index f1ec6455..25198a54 100644 --- a/packages/editor/main.py +++ b/packages/editor/main.py @@ -166,9 +166,9 @@ def upload_image(e: UploadEventArguments) -> None: def switch_action(e: ValueChangeEventArguments) -> None: """Fire switch action event.""" - if type_toggle.value == "pixel" and e.value == "smudge": + if type_toggle.value == "pixel" and e.value in ("smudge", "clip"): action_toggle.value = "pen" - ui.notify("You cannot select the smudge action while in pixel mode.", type="negative") + ui.notify("You cannot select the smudge or select action while in pixel mode.", type="negative") return ui.run_javascript(f""" const event = new Event('change'); @@ -187,14 +187,18 @@ def switch_action(e: ValueChangeEventArguments) -> None: ui.switch("Dark mode").bind_value(dark) ui.button("Clear Canvas", on_click=reset_confirmation).props("color='red'") ui.button("Download").props("id='download-button'") - file_uploader = ui.upload( - label="Upload file", - auto_upload=True, - on_upload=upload_image, - on_rejected=lambda _: ui.notify("There was an issue with the upload."), - ).props("accept='image/*' id='file-input'") + file_uploader = ( + ui.upload( + label="Upload file", + auto_upload=True, + on_upload=upload_image, + on_rejected=lambda _: ui.notify("There was an issue with the upload."), + ) + .props("accept='image/*' id='file-input'") + .style("width: 100%;") + ) type_toggle = ui.toggle( - {"smooth": "✍️", "pixel": "👾"}, + {"smooth": "✍️", "pixel": "👾", "clip": "📎"}, value="smooth", on_change=lambda e: change_type(mode_value=e.value), ).props("id='type-select'") diff --git a/packages/editor/scripts/canvas_ctx.py b/packages/editor/scripts/canvas_ctx.py index 0313d257..6163cf65 100644 --- a/packages/editor/scripts/canvas_ctx.py +++ b/packages/editor/scripts/canvas_ctx.py @@ -24,17 +24,17 @@ class DOMRect: class TextMetrics: """TextMetrics typehint.""" - actualBoundingBoxAscent: float - actualBoundingBoxDescent: float - actualBoundingBoxLeft: float - actualBoundingBoxRight: float - alphabeticBaseline: float - emHeightAscent: float - emHeightDescent: float - fontBoundingBoxAscent: float - fontBoundingBoxDescent: float - hangingBaseline: float - ideographicBaseline: float + actualBoundingBoxAscent: float # noqa: N815 + actualBoundingBoxDescent: float # noqa: N815 + actualBoundingBoxLeft: float # noqa: N815 + actualBoundingBoxRight: float # noqa: N815 + alphabeticBaseline: float # noqa: N815 + emHeightAscent: float # noqa: N815 + emHeightDescent: float # noqa: N815 + fontBoundingBoxAscent: float # noqa: N815 + fontBoundingBoxDescent: float # noqa: N815 + hangingBaseline: float # noqa: N815 + ideographicBaseline: float # noqa: N815 width: float @@ -94,18 +94,19 @@ class CanvasContext: history: list[Any] history_index: int text_placed: bool + clipping: bool # Builtin attributes canvas: Any direction: Any - fillStyle: Any + fillStyle: Any # noqa: N815 filter: Any font: Any - fontKerning: Any - fontStretch: Any - fontVariantCaps: Any - globalAlpha: Any - globalCompositeOperation: Literal[ + fontKerning: Any # noqa: N815 + fontStretch: Any # noqa: N815 + fontVariantCaps: Any # noqa: N815 + globalAlpha: Any # noqa: N815 + globalCompositeOperation: Literal[ # noqa: N815 "source-over", "source-in", "source-out", @@ -134,24 +135,24 @@ class CanvasContext: "luminosity", ] = "source-over" - imageSmoothingEnabled: bool - imageSmoothingQuality: Any - langExperimental: Any - letterSpacing: Any - lineCap: str = "round" - lineDashOffset: Any - lineJoin: str = "round" - lineWidth: float - miterLimit: Any - shadowBlur: Any - shadowColor: Any - shadowOffsetX: Any - shadowOffsetY: Any - strokeStyle: str - textAlign: Any - textBaseline: Any - textRendering: Any - wordSpacing: Any + imageSmoothingEnabled: bool # noqa: N815 + imageSmoothingQuality: Any # noqa: N815 + langExperimental: Any # noqa: N815 + letterSpacing: Any # noqa: N815 + lineCap: str = "round" # noqa: N815 + lineDashOffset: Any # noqa: N815 + lineJoin: str = "round" # noqa: N815 + lineWidth: float # noqa: N815 + miterLimit: Any # noqa: N815 + shadowBlur: Any # noqa: N815 + shadowColor: Any # noqa: N815 + shadowOffsetX: Any # noqa: N815 + shadowOffsetY: Any # noqa: N815 + strokeStyle: str # noqa: N815 + textAlign: Any # noqa: N815 + textBaseline: Any # noqa: N815 + textRendering: Any # noqa: N815 + wordSpacing: Any # noqa: N815 def __init__( self, @@ -187,7 +188,7 @@ def rect_bottom(self) -> float: ########################################################################### # Cutstom Methods ########################################################################### - def getBoundingClientRect(self) -> DOMRect: + def getBoundingClientRect(self) -> DOMRect: # noqa: N802 """Get the canvas getBoundingClientRect.""" return self.canvas.getBoundingClientRect() @@ -199,6 +200,7 @@ def get_canvas_coords(self, event: MouseEvent) -> tuple[float, float]: Returns: tuple[float, float]: The x and y coordinates + """ x = (event.pageX - self.rect_left) * self.scaled_by y = (event.pageY - self.rect_top) * self.scaled_by @@ -212,27 +214,27 @@ def arc( # noqa: PLR0913 This method has this many arguments. x: float, y: float, radius: float, - startAngle: float, - endAngle: float, + startAngle: float, # noqa: N803 + endAngle: float, # noqa: N803 *, counterclockwise: bool = False, ) -> None: """Add arc.""" self.ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise) - def arcTo(self) -> None: + def arcTo(self) -> None: # noqa: N802 """Add arcTo.""" self.ctx.arcTo() - def beginPath(self) -> None: + def beginPath(self) -> None: # noqa: N802 """Add beginPath.""" self.ctx.beginPath() - def bezierCurveTo(self) -> None: + def bezierCurveTo(self) -> None: # noqa: N802 """Add bezierCurveTo.""" self.ctx.bezierCurveTo() - def clearRect(self, x: float, y: float, width: float, height: float) -> None: + def clearRect(self, x: float, y: float, width: float, height: float) -> None: # noqa: N802 """Add clearRect.""" self.ctx.clearRect(x, y, width, height) @@ -240,41 +242,41 @@ def clip(self) -> None: """Add clip.""" self.ctx.clip() - def closePath(self) -> None: + def closePath(self) -> None: # noqa: N802 """Add closePath.""" self.ctx.closePath() - def createConicGradient(self) -> None: + def createConicGradient(self) -> None: # noqa: N802 """Add createConicGradient.""" self.ctx.createConicGradient() - def createImageData(self) -> None: + def createImageData(self) -> None: # noqa: N802 """Add createImageData.""" self.ctx.createImageData() - def createLinearGradient(self) -> None: + def createLinearGradient(self) -> None: # noqa: N802 """Add createLinearGradient.""" self.ctx.createLinearGradient() - def createPattern(self) -> None: + def createPattern(self) -> None: # noqa: N802 """Add createPattern.""" self.ctx.createPattern() - def createRadialGradient(self) -> None: + def createRadialGradient(self) -> None: # noqa: N802 """Add createRadialGradient.""" self.ctx.createRadialGradient() - def drawFocusIfNeeded(self) -> None: + def drawFocusIfNeeded(self) -> None: # noqa: N802 """Add drawFocusIfNeeded.""" self.ctx.drawFocusIfNeeded() - def drawImage( + def drawImage( # noqa: N802 self, image: JsProxy, dx: float, dy: float, - dWidth: float | None = None, - dHeight: float | None = None, + dWidth: float | None = None, # noqa: N803 + dHeight: float | None = None, # noqa: N803 ) -> None: """Add drawImage.""" self.ctx.drawImage(image, dx, dy, dWidth, dHeight) @@ -283,11 +285,11 @@ def ellipse( # noqa: PLR0913 This method has this many arguments. self, x: float, y: float, - radiusX: float, - radiusY: float, + radiusX: float, # noqa: N803 + radiusY: float, # noqa: N803 rotation: float, - startAngle: float, - endAngle: float, + startAngle: float, # noqa: N803 + endAngle: float, # noqa: N803 *, counterclockwise: bool = False, ) -> None: @@ -298,63 +300,63 @@ def fill(self) -> None: """Add fill.""" self.ctx.fill() - def fillRect(self, x: float, y: float, width: float, height: float) -> None: + def fillRect(self, x: float, y: float, width: float, height: float) -> None: # noqa: N802 """Add fillRect.""" self.ctx.fillRect(x, y, width, height) - def fillText(self, text: str, x: float, y: float) -> None: + def fillText(self, text: str, x: float, y: float) -> None: # noqa: N802 """Add fillText.""" self.ctx.fillText(text, x, y) - def getContextAttributes(self) -> None: + def getContextAttributes(self) -> None: # noqa: N802 """Add getContextAttributes.""" self.ctx.getContextAttributes() - def getImageData(self, sx: float, sy: float, sw: float, sh: float) -> ImageData: + def getImageData(self, sx: float, sy: float, sw: float, sh: float) -> ImageData: # noqa: N802 """Get the image data from the canvas.""" return self.ctx.getImageData(sx, sy, sw, sh) - def getLineDash(self) -> None: + def getLineDash(self) -> None: # noqa: N802 """Add getLineDash.""" self.ctx.getLineDash() - def getTransform(self) -> None: + def getTransform(self) -> None: # noqa: N802 """Add getTransform.""" self.ctx.getTransform() - def isContextLost(self) -> None: + def isContextLost(self) -> None: # noqa: N802 """Add isContextLost.""" self.ctx.isContextLost() - def isPointInPath(self) -> None: + def isPointInPath(self) -> None: # noqa: N802 """Add isPointInPath.""" self.ctx.isPointInPath() - def isPointInStroke(self) -> None: + def isPointInStroke(self) -> None: # noqa: N802 """Add isPointInStroke.""" self.ctx.isPointInStroke() - def lineTo(self, x: float, y: float) -> None: + def lineTo(self, x: float, y: float) -> None: # noqa: N802 """Make a line to the x, y given.""" self.ctx.lineTo(x, y) - def measureText(self, text: str) -> TextMetrics: + def measureText(self, text: str) -> TextMetrics: # noqa: N802 """Add measureText.""" return self.ctx.measureText(text) - def moveTo(self, x: float, y: float) -> None: + def moveTo(self, x: float, y: float) -> None: # noqa: N802 """Move to the x, y given.""" self.ctx.moveTo(x, y) - def putImageData( # noqa: PLR0913 This method has this many arguments. + def putImageData( # # noqa: N802, PLR0913 This method has this many arguments. self, - imageData: ImageData, + imageData: ImageData, # noqa: N803 dx: float, dy: float, - dirtyX: float | None = None, - dirtyY: float | None = None, - dirtyWidth: float | None = None, - dirtyHeight: float | None = None, + dirtyX: float | None = None, # noqa: N803 + dirtyY: float | None = None, # noqa: N803 + dirtyWidth: float | None = None, # noqa: N803 + dirtyHeight: float | None = None, # noqa: N803 ) -> None: """Paint rectangle onto canvas. @@ -389,6 +391,7 @@ def putImageData( # noqa: PLR0913 This method has this many arguments. dirtyHeight: float | None = None Height of the rectangle to be painted. Defaults to the height of the image data. + """ self.ctx.putImageData( imageData, @@ -400,7 +403,7 @@ def putImageData( # noqa: PLR0913 This method has this many arguments. dirtyHeight, ) - def quadraticCurveTo(self) -> None: + def quadraticCurveTo(self) -> None: # noqa: N802 """Add quadraticCurveTo.""" self.ctx.quadraticCurveTo() @@ -412,7 +415,7 @@ def reset(self) -> None: """Add reset.""" self.ctx.reset() - def resetTransform(self) -> None: + def resetTransform(self) -> None: # noqa: N802 """Add resetTransform.""" self.ctx.resetTransform() @@ -424,7 +427,7 @@ def rotate(self) -> None: """Add rotate.""" self.ctx.rotate() - def roundRect(self) -> None: + def roundRect(self) -> None: # noqa: N802 """Add roundRect.""" self.ctx.roundRect() @@ -436,11 +439,11 @@ def scale(self, x: float, y: float) -> None: """Add scale.""" self.ctx.scale(x, y) - def setLineDash(self) -> None: + def setLineDash(self) -> None: # noqa: N802 """Add setLineDash.""" self.ctx.setLineDash() - def setTransform(self) -> None: + def setTransform(self) -> None: # noqa: N802 """Add setTransform.""" self.ctx.setTransform() @@ -448,11 +451,11 @@ def stroke(self) -> None: """Add stroke.""" self.ctx.stroke() - def strokeRect(self) -> None: + def strokeRect(self) -> None: # noqa: N802 """Add strokeRect.""" self.ctx.strokeRect() - def strokeText(self) -> None: + def strokeText(self) -> None: # noqa: N802 """Add strokeText.""" self.ctx.strokeText() diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index acdf91a0..8b5bd6ed 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -73,6 +73,7 @@ ctx.text_placed = True ctx.prev_operation = "source-over" ctx.text_settings = {"bold": False, "italics": False, "size": 50, "font-family": "Arial"} +ctx.clipping = False buffer_ctx.imageSmoothingEnabled = False From 2c8abc642582d78543bd76b1cbfe734d989e14c7 Mon Sep 17 00:00:00 2001 From: PiLogic Date: Fri, 15 Aug 2025 16:21:54 +0100 Subject: [PATCH 081/198] Undo + Redo Shortcuts --- packages/editor/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor/main.py b/packages/editor/main.py index f1ec6455..a9fb2f80 100644 --- a/packages/editor/main.py +++ b/packages/editor/main.py @@ -210,8 +210,8 @@ def switch_action(e: ValueChangeEventArguments) -> None: # Canvas controls with ui.column().style("flex-grow: 1; flex-basis: 0;"): with ui.row(): - ui.button("Undo").props("id='undo-button'") - ui.button("Redo").props("id='redo-button'") + ui.button("Undo").props("id='undo-button'").props("class='keyboard-shortcuts' shortcut_data='btn,u'") + ui.button("Redo").props("id='redo-button'").props("class='keyboard-shortcuts' shortcut_data='btn,r'") action_options = { "pen": "🖊️", "eraser": "🧽", From 57692b776b25602c6fb5e6f12716d43617e81a73 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 16:53:24 +0100 Subject: [PATCH 082/198] Add clip feature --- packages/editor/main.py | 12 +- packages/editor/scripts/canvas_ctx.py | 25 ++++- packages/editor/scripts/editor.py | 151 +++++++++++++++++++++++--- 3 files changed, 156 insertions(+), 32 deletions(-) diff --git a/packages/editor/main.py b/packages/editor/main.py index 25198a54..70a1312f 100644 --- a/packages/editor/main.py +++ b/packages/editor/main.py @@ -198,7 +198,7 @@ def switch_action(e: ValueChangeEventArguments) -> None: .style("width: 100%;") ) type_toggle = ui.toggle( - {"smooth": "✍️", "pixel": "👾", "clip": "📎"}, + {"smooth": "✍️", "pixel": "👾"}, value="smooth", on_change=lambda e: change_type(mode_value=e.value), ).props("id='type-select'") @@ -216,18 +216,14 @@ def switch_action(e: ValueChangeEventArguments) -> None: with ui.row(): ui.button("Undo").props("id='undo-button'") ui.button("Redo").props("id='redo-button'") - action_options = { - "pen": "🖊️", - "eraser": "🧽", - "smudge": "💨", - } + action_options = {"pen": "🖊️", "eraser": "🧽", "smudge": "💨", "clip": "📎"} action_toggle = ui.toggle( action_options, value="pen", on_change=switch_action, ).props( - "id='action-select' class='keyboard-shortcuts' shortcut_data='toggle,p:🖊️,e:🧽,s:💨'", + "id='action-select' class='keyboard-shortcuts' shortcut_data='toggle,p:🖊️,e:🧽,s:💨,c:📎'", ) ui.separator().classes("w-full") with ui.row(): @@ -237,7 +233,7 @@ def switch_action(e: ValueChangeEventArguments) -> None: ui.label(colour) colour_label = ui.label("00") colour_values.append(colour_label) - ui.button("Spin", on_click=spin).props("class='keyboard-shortcuts' shortcut_data='btn,c'") + ui.button("Spin", on_click=spin).props("class='keyboard-shortcuts' shortcut_data='btn,z'") ui.separator().classes("w-full") width_input = ui.number(label="Line Width", min=1, max=50, step=1) width_slider = ui.slider( diff --git a/packages/editor/scripts/canvas_ctx.py b/packages/editor/scripts/canvas_ctx.py index 6163cf65..7ef23328 100644 --- a/packages/editor/scripts/canvas_ctx.py +++ b/packages/editor/scripts/canvas_ctx.py @@ -1,3 +1,5 @@ +# There are a lot of NOQAs in this file as these are typehints based on JS classes/methods. + from typing import Any, Literal from js import ( # pyright: ignore[reportMissingImports] @@ -21,6 +23,13 @@ class DOMRect: y: float +class ImageBitmap: + """Image bitmap typehint.""" + + height: float + width: float + + class TextMetrics: """TextMetrics typehint.""" @@ -95,6 +104,10 @@ class CanvasContext: history_index: int text_placed: bool clipping: bool + moving_clip: bool + start_coords: list[float] + prev_stroke_style: str + prev_line_width: int # Builtin attributes canvas: Any @@ -407,9 +420,9 @@ def quadraticCurveTo(self) -> None: # noqa: N802 """Add quadraticCurveTo.""" self.ctx.quadraticCurveTo() - def rect(self, *_: list) -> None: + def rect(self, x: float, y: float, width: float, height: float) -> None: """Set the rect.""" - self.ctx.rect() + self.ctx.rect(x, y, width, height) def reset(self) -> None: """Add reset.""" @@ -439,9 +452,9 @@ def scale(self, x: float, y: float) -> None: """Add scale.""" self.ctx.scale(x, y) - def setLineDash(self) -> None: # noqa: N802 + def setLineDash(self, segments: list[float]) -> None: # noqa: N802 """Add setLineDash.""" - self.ctx.setLineDash() + self.ctx.setLineDash(segments) def setTransform(self) -> None: # noqa: N802 """Add setTransform.""" @@ -451,9 +464,9 @@ def stroke(self) -> None: """Add stroke.""" self.ctx.stroke() - def strokeRect(self) -> None: # noqa: N802 + def strokeRect(self, x: float, y: float, width: float, height: float) -> None: # noqa: N802 """Add strokeRect.""" - self.ctx.strokeRect() + self.ctx.strokeRect(x, y, width, height) def strokeText(self) -> None: # noqa: N802 """Add strokeText.""" diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index 8b5bd6ed..41c5ff9c 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -1,5 +1,5 @@ # This should be under the other imports but because it isn't imported in the traditional way, it's above them. -from canvas_ctx import CanvasContext # pyright: ignore[reportMissingImports] # +from canvas_ctx import CanvasContext, ImageBitmap # pyright: ignore[reportMissingImports] # # Following imports have the ignore flag as they are not pip installed from js import ( # pyright: ignore[reportMissingImports] @@ -74,6 +74,10 @@ ctx.prev_operation = "source-over" ctx.text_settings = {"bold": False, "italics": False, "size": 50, "font-family": "Arial"} ctx.clipping = False +ctx.moving_clip = False +ctx.start_coords = [0, 0] +ctx.prev_stroke_style = "black" +ctx.prev_line_width = 5 buffer_ctx.imageSmoothingEnabled = False @@ -155,6 +159,21 @@ def show_action_icon(x: float, y: float) -> bool: bool: If True is returned mousemove doesn't do anything else """ + + def draw_clip(img_bitmap: ImageBitmap) -> None: + buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + + buffer_ctx.strokeRect( + x - img_bitmap.width / 2, + y - img_bitmap.height / 2, + img_bitmap.width, + img_bitmap.height, + ) + buffer_ctx.drawImage(img_bitmap, x - img_bitmap.width / 2, y - img_bitmap.height / 2) + + if ctx.moving_clip: + createImageBitmap(ctx.prev_data).then(draw_clip) + return True buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) if ctx.moving_image: buffer_ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) @@ -167,6 +186,15 @@ def show_action_icon(x: float, y: float) -> bool: y + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, ) return True + if ctx.clipping: + ctx.beginPath() + buffer_ctx.strokeRect( + ctx.start_coords[0], + ctx.start_coords[1], + x - ctx.start_coords[0], + y - ctx.start_coords[1], + ) + return True if ctx.type == "smooth": buffer_ctx.beginPath() buffer_ctx.arc(x, y, ctx.lineWidth / 2, 0, 2 * Math.PI) # Put a dot here @@ -283,7 +311,7 @@ def mouse_tracker(event: MouseEvent) -> None: if show_action_icon(x, y): return - if not (ctx.text_placed): + if not ctx.text_placed: text_dimensions = ctx.measureText(ctx.text_value) buffer_ctx.fillText( ctx.text_value, @@ -294,16 +322,25 @@ def mouse_tracker(event: MouseEvent) -> None: return if not ctx.drawing: return + draw_action(event, x, y) + +def draw_action(event: MouseEvent, x: float, y: float) -> None: + """Draw the event on the screen. + + Args: + event (MouseEvent): Mouse event + x (float): X coordinate + y (float): Y coordinate + + """ match ctx.type: case "smooth": if ctx.action == "smudge": draw_smudge(event) - - else: # this is "pen" or "eraser" + elif ctx.action in ("pen", "eraser"): # this is "pen" or "eraser" ctx.lineTo(x, y) ctx.stroke() - case "pixel": if ctx.action == "pen": draw_pixel(x, y) @@ -319,13 +356,39 @@ def stop_path(_: MouseEvent) -> None: event (MouseEvent): The mouse event """ - if ctx.text_placed: - ctx.writing_text = False if ctx.drawing: ctx.drawing = False save_history() +@when("mouseup", "#image-canvas") +def drop_media(event: MouseEvent) -> None: + """Place text or clipping. + + Args: + event (MouseEvent): Mouse event + + """ + if ctx.text_placed: + ctx.writing_text = False + if ctx.clipping: + ctx.clipping = False + ctx.moving_clip = True + x, y = get_canvas_coords(event) + ctx.prev_data = ctx.getImageData( + ctx.start_coords[0], + ctx.start_coords[1], + x - ctx.start_coords[0], + y - ctx.start_coords[1], + ) + ctx.clearRect( + ctx.start_coords[0], + ctx.start_coords[1], + x - ctx.start_coords[0], + y - ctx.start_coords[1], + ) + + @when("mouseenter", "#image-canvas") def start_reentry_path(event: MouseEvent) -> None: """Start a new path from the edge upon canvas entry. @@ -371,13 +434,52 @@ def canvas_click(event: MouseEvent) -> None: if event.button != 0: return x, y = get_canvas_coords(event) + if special_actions(x, y): + return + if ctx.type == "smooth": + if ctx.action == "clip" and not ctx.moving_clip: + ctx.clipping = True + ctx.start_coords = [x, y] + ctx.setLineDash([2, 10]) + buffer_ctx.setLineDash([2, 10]) + ctx.prev_stroke_style = ctx.strokeStyle + ctx.prev_line_width = ctx.lineWidth + + ctx.strokeStyle = "black" + ctx.lineWidth = 5 + buffer_ctx.strokeStyle = "black" + buffer_ctx.lineWidth = 5 + else: + ctx.beginPath() + ctx.ellipse(x, y, ctx.lineWidth / 100, ctx.lineWidth / 100, 0, 0, 2 * Math.PI) # Put a dot here + if ctx.action in ("pen", "eraser"): + ctx.stroke() + elif ctx.type == "pixel": + if ctx.action == "pen": + draw_pixel(x, y) + elif ctx.action == "eraser": + ctx.clearRect(x - PIXEL_SIZE // 2, y - PIXEL_SIZE // 2, PIXEL_SIZE, PIXEL_SIZE) + + +def special_actions(x: float, y: float) -> bool: + """Draw special action on canvas. + + Args: + x (float): X coordinate + y (float): Y coordinate + + Returns: + bool: Whether to skip the regular drawing process or not + + """ if ctx.moving_image: ctx.moving_image = False buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) ctx.globalCompositeOperation = ctx.prev_operation save_history() - elif ctx.writing_text: + return True + if ctx.writing_text: ctx.text_placed = True buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) text_dimensions = ctx.measureText(ctx.text_value) @@ -387,16 +489,26 @@ def canvas_click(event: MouseEvent) -> None: y + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, ) ctx.globalCompositeOperation = ctx.prev_operation - elif ctx.type == "smooth": - ctx.beginPath() - ctx.ellipse(x, y, ctx.lineWidth / 100, ctx.lineWidth / 100, 0, 0, 2 * Math.PI) # Put a dot here - if ctx.action in ("pen", "eraser"): - ctx.stroke() - elif ctx.type == "pixel": - if ctx.action == "pen": - draw_pixel(x, y) - elif ctx.action == "eraser": - ctx.clearRect(x - PIXEL_SIZE // 2, y - PIXEL_SIZE // 2, PIXEL_SIZE, PIXEL_SIZE) + return True + + if ctx.moving_clip: + ctx.moving_clip = False + + def draw_clip(img_bitmap: ImageBitmap) -> None: + buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + ctx.drawImage(img_bitmap, x - img_bitmap.width / 2, y - img_bitmap.height / 2) + + createImageBitmap(ctx.prev_data).then(draw_clip) + ctx.setLineDash([]) + buffer_ctx.setLineDash([]) + ctx.strokeStyle = ctx.prev_stroke_style + ctx.lineWidth = ctx.prev_line_width + + buffer_ctx.strokeStyle = ctx.prev_stroke_style + buffer_ctx.lineWidth = ctx.prev_line_width + save_history() + return True + return False @when("colourChange", "body") @@ -441,6 +553,8 @@ def action_change(event: Event) -> None: ctx.globalCompositeOperation = "destination-out" case "smudge": ctx.globalCompositeOperation = "source-over" + case "clip": + ctx.globalCompositeOperation = "source-over" @when("addText", "#text-input") @@ -487,6 +601,7 @@ def type_change(event: Event) -> None: # As far as I know there's no way to check when we change from pixel to smooth in the history so there's # no way to switch the modes in the UI. Hence I've decided to just clear the history instead. ctx.history.clear() + ctx.history_index = 0 save_history() From c926c2ea28258503226c2bf6d03e5c94bfeb78cf Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 17:22:30 +0100 Subject: [PATCH 083/198] Fix undo/redo button while in erase mode --- packages/editor/scripts/editor.py | 34 ++++++++++++++++++------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index bdc27dda..fa422457 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -113,12 +113,14 @@ def undo(_: Event) -> None: return ctx.history_index -= 1 - createImageBitmap(ctx.history[ctx.history_index]).then( - lambda img_bitmap: ( - ctx.clearRect(0, 0, canvas.width, canvas.height), - ctx.drawImage(img_bitmap, 0, 0, canvas.width, canvas.height), - ), - ) + def place_history(img_bitmap: ImageBitmap) -> None: + ctx.clearRect(0, 0, canvas.width, canvas.height) + ctx.prev_operation = ctx.globalCompositeOperation + ctx.globalCompositeOperation = "source-over" + ctx.drawImage(img_bitmap, 0, 0, canvas.width, canvas.height) + ctx.globalCompositeOperation = ctx.prev_operation + + createImageBitmap(ctx.history[ctx.history_index]).then(place_history) @when("click", "#redo-button") @@ -128,12 +130,14 @@ def redo(_: Event) -> None: return ctx.history_index += 1 - createImageBitmap(ctx.history[ctx.history_index]).then( - lambda img_bitmap: ( - ctx.clearRect(0, 0, canvas.width, canvas.height), - ctx.drawImage(img_bitmap, 0, 0, canvas.width, canvas.height), - ), - ) + def place_history(img_bitmap: ImageBitmap) -> None: + ctx.clearRect(0, 0, canvas.width, canvas.height) + ctx.prev_operation = ctx.globalCompositeOperation + ctx.globalCompositeOperation = "source-over" + ctx.drawImage(img_bitmap, 0, 0, canvas.width, canvas.height) + ctx.globalCompositeOperation = ctx.prev_operation + + createImageBitmap(ctx.history[ctx.history_index]).then(place_history) def draw_pixel(x: float, y: float) -> None: @@ -178,7 +182,7 @@ def draw_clip(img_bitmap: ImageBitmap) -> None: if ctx.moving_image: buffer_ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) return True - if not(ctx.text_placed): + if ctx.writing_text: text_dimensions = ctx.measureText(ctx.text_value) buffer_ctx.fillText( ctx.text_value, @@ -478,6 +482,7 @@ def special_actions(x: float, y: float) -> bool: ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) ctx.globalCompositeOperation = ctx.prev_operation save_history() + return True if ctx.writing_text: ctx.text_placed = True @@ -497,6 +502,7 @@ def special_actions(x: float, y: float) -> bool: def draw_clip(img_bitmap: ImageBitmap) -> None: buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.drawImage(img_bitmap, x - img_bitmap.width / 2, y - img_bitmap.height / 2) + save_history() createImageBitmap(ctx.prev_data).then(draw_clip) ctx.setLineDash([]) @@ -506,7 +512,7 @@ def draw_clip(img_bitmap: ImageBitmap) -> None: buffer_ctx.strokeStyle = ctx.prev_stroke_style buffer_ctx.lineWidth = ctx.prev_line_width - save_history() + return True return False From 0bc285d2323bb23072815ad521f3afd1a1149cfe Mon Sep 17 00:00:00 2001 From: Aadil Goyal Date: Fri, 15 Aug 2025 21:54:54 +0530 Subject: [PATCH 084/198] Collision detection pretty much done --- packages/gallery/main.py | 52 ++++++++++++++++++++++++++++++---------- packages/tips.txt | 5 ++++ 2 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 packages/tips.txt diff --git a/packages/gallery/main.py b/packages/gallery/main.py index f3883199..55375b50 100644 --- a/packages/gallery/main.py +++ b/packages/gallery/main.py @@ -9,8 +9,8 @@ from js import ( # pyright: ignore[reportMissingImports] Math, THREE, - LineSegments2, - LineMaterial, + # LineSegments2, + # LineMaterial, Object, console, GLTFLoader, @@ -53,6 +53,22 @@ def convert_dict_to_js_object(my_dict: dict): MODULAR_GROUP = THREE.Object3D.new() SCENE.add(MODULAR_GROUP) +CUBES: list[THREE.Mesh] = [] # a list of all cubes in the scene +OFFSET = 0.1 # distance which we maintain from walls + +""" +BOUNDING_BOXES = list() # a list of all bounding boxes +OBJECTS = list() # a list of objs who have a bb + +def create_bounding_box(obj): + box = THREE.Box3.new().setFromObject(obj) + BOUNDING_BOXES.append(box) + OBJECTS.append(obj) + return box + +CAMERA_BOUNDING_BOX = create_bounding_box(CAMERA) +SCENE.add(THREE.Box3Helper.new(CAMERA_BOUNDING_BOX, "#ff00ff")) +""" # Camera controls and mouse lock CONTROLS = PointerLockControls.new(CAMERA, document.body) @@ -154,7 +170,18 @@ def move_character(delta_time: float): VELOCITY.setLength(max_speed) VELOCITY.multiplyScalar(1 - min(damping * delta_time, 1)) - CAMERA.position.addScaledVector(VELOCITY, delta_time) + return VELOCITY + + +def check_collision(velocity: THREE.Vector3, delta_time: float): + raycaster = THREE.Raycaster.new() + direction = velocity.clone().normalize() + raycaster.set(CAMERA.position, direction) + + intersections = raycaster.intersectObjects(CUBES) + if not intersections: + return True + return intersections[0].distance > velocity.length() * delta_time + OFFSET MOUSE = THREE.Vector2.new() @@ -192,12 +219,6 @@ def generate_lights() -> None: def load_image(image_loc: str): textureLoader = THREE.TextureLoader.new() texture = textureLoader.load(image_loc) - # texture = textureLoader.load( - # image_loc, - # create_proxy(lambda e: create_photoframe(texture)), - # create_proxy(log), - # create_proxy(log), - # ) return texture @@ -205,9 +226,7 @@ def create_plane(texture): perms = convert_dict_to_js_object( { "map": texture, - "transparent": True, # removes the black bg - # the color makes it look wierd so commented it - # "color": "#A6D32B", + "transparent": True, } ) @@ -294,6 +313,7 @@ def inner_loader(gltf): # Backface culling assert obj.children[0].name == "Cube" for v in obj.children[0].children: + CUBES.append(v) v.material.side = THREE.FrontSide for v in obj.children[1:]: @@ -336,7 +356,13 @@ def inner_error(error): async def main(): clock = THREE.Clock.new() while True: - move_character(clock.getDelta()) + delta = clock.getDelta() + velocity = move_character(delta) + if check_collision(velocity, delta): + CAMERA.position.addScaledVector(velocity, delta) + # else: + # print("COLLISION DETECTED") + RENDERER.render(SCENE, CAMERA) await asyncio.sleep(0.02) diff --git a/packages/tips.txt b/packages/tips.txt new file mode 100644 index 00000000..8e5fa33d --- /dev/null +++ b/packages/tips.txt @@ -0,0 +1,5 @@ +This is just a list of "tips" we can display to the user with the loading scene + +1) "z" toggles run +2) "shift" is used to go down + From a099a4059028a1c66454f406134bcf092d807827 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 18:20:22 +0100 Subject: [PATCH 085/198] Text resizing --- packages/editor/scripts/editor.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index fa422457..4a87749d 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -90,6 +90,8 @@ ctx.history = [] ctx.history_index = -1 MAX_HISTORY = 50 +MIN_TEXT_SIZE = 20 +MAX_TEXT_SIZE = 200 PIXEL_SIZE = 8 SMUDGE_BLEND_FACTOR = 0.5 @@ -317,6 +319,7 @@ def mouse_tracker(event: MouseEvent) -> None: return if not ctx.text_placed: text_dimensions = ctx.measureText(ctx.text_value) + buffer_ctx.fillText( ctx.text_value, x - text_dimensions.width / 2, @@ -488,6 +491,7 @@ def special_actions(x: float, y: float) -> bool: ctx.text_placed = True buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) text_dimensions = ctx.measureText(ctx.text_value) + ctx.fillText( ctx.text_value, x - text_dimensions.width / 2, @@ -723,7 +727,16 @@ def handle_scroll(e: Event) -> None: """ e.preventDefault() - print(e.deltaY) + x, y = get_canvas_coords(e) + if ctx.writing_text: + # ctx.text_settings["size"] is an int + if e.deltaY > 0 and ctx.text_settings["size"] > MIN_TEXT_SIZE: # pyright: ignore[reportOperatorIssue] + ctx.text_settings["size"] -= 5 # pyright: ignore[reportOperatorIssue] + elif e.deltaY < 0 and ctx.text_settings["size"] < MAX_TEXT_SIZE: # pyright: ignore[reportOperatorIssue] + ctx.text_settings["size"] += 5 # pyright: ignore[reportOperatorIssue] + ctx.font = f"{ctx.text_settings['italics']} {ctx.text_settings['bold']} {ctx.text_settings['size']}px {ctx.text_settings['font-family']}" # noqa: E501 + buffer_ctx.font = f"{ctx.text_settings['italics']} {ctx.text_settings['bold']} {ctx.text_settings['size']}px {ctx.text_settings['font-family']}" # noqa: E501 + show_action_icon(x, y) window.addEventListener("resize", resize) From 7774a0926273290d8a651f738d26ab310b2e7208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Fri, 15 Aug 2025 19:33:30 +0200 Subject: [PATCH 086/198] Updated pyproject description and added support for local imports --- packages/gallery/pyproject.toml | 2 +- packages/gallery/pyscript.toml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/gallery/pyproject.toml b/packages/gallery/pyproject.toml index cd7c12f5..58768172 100644 --- a/packages/gallery/pyproject.toml +++ b/packages/gallery/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "gallery" version = "0.1.0" -description = "Add your description here" +description = "An online Image Gallery rendered through Three.js and WebGL and programmed in PyScript." readme = "README.md" requires-python = ">=3.12" dependencies = [] diff --git a/packages/gallery/pyscript.toml b/packages/gallery/pyscript.toml index e1d89c68..4384c8d3 100644 --- a/packages/gallery/pyscript.toml +++ b/packages/gallery/pyscript.toml @@ -1,3 +1,5 @@ name = "Image Gallery" description = "An online Image Gallery rendered through Three.js and WebGL and programmed in PyScript." - +[[fetch]] +files = [] +from = '.' From 4e0c263aacd3f028364bb4efaac170c333d3c20b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Fri, 15 Aug 2025 19:33:47 +0200 Subject: [PATCH 087/198] Added automatic fetching of images from GitHub --- .../gallery/assets/test-image-listing.json | 11 +++++++++ packages/gallery/main.py | 24 +++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 packages/gallery/assets/test-image-listing.json diff --git a/packages/gallery/assets/test-image-listing.json b/packages/gallery/assets/test-image-listing.json new file mode 100644 index 00000000..43450429 --- /dev/null +++ b/packages/gallery/assets/test-image-listing.json @@ -0,0 +1,11 @@ +[ +"test-image.webp", +"tree-test-image.avif", +"test-image-nobg.png", +"tree-test-image.avif", +"test-image.webp", +"tree-test-image.avif", +"tree-test-image.avif", +"test-image.webp", +"test-image.webp" +] diff --git a/packages/gallery/main.py b/packages/gallery/main.py index f3883199..ae0a8cc9 100644 --- a/packages/gallery/main.py +++ b/packages/gallery/main.py @@ -5,6 +5,7 @@ ## https:#threejs.org/docs/ from pyodide.ffi import to_js, create_proxy # pyright: ignore[reportMissingImports] +from pyodide.http import pyfetch # pyright: ignore[reportMissingImports] from pyscript import when, window, document # pyright: ignore[reportMissingImports] from js import ( # pyright: ignore[reportMissingImports] Math, @@ -21,6 +22,7 @@ from collections import defaultdict from enum import Enum import asyncio +import json def log(*msgs): @@ -189,9 +191,16 @@ def generate_lights() -> None: SCENE.add(ambientLight) +REPO_URL = ( + r"https://cdn.jsdelivr.net/gh/" + r"Matiiss/pydis-cj12-heavenly-hostas@dev/" + r"packages/gallery/assets/images/" +) + + def load_image(image_loc: str): textureLoader = THREE.TextureLoader.new() - texture = textureLoader.load(image_loc) + texture = textureLoader.load(REPO_URL + image_loc) # texture = textureLoader.load( # image_loc, # create_proxy(lambda e: create_photoframe(texture)), @@ -333,6 +342,14 @@ def inner_error(error): ) +async def load_images_from_listing() -> None: + r = await pyfetch(REPO_URL + "../" + "test-image-listing.json") + data = await r.text() + images = json.loads(data) + for idx, img in enumerate(images): + asyncio.ensure_future(create_photoframe(img, idx)) + + async def main(): clock = THREE.Clock.new() while True: @@ -344,9 +361,6 @@ async def main(): if __name__ == "__main__": generate_lights() load_gallery() - asyncio.ensure_future(create_photoframe("assets/images/tree-test-image.avif", 0)) - asyncio.ensure_future(create_photoframe("assets/images/test-image-nobg.png", 1)) - for i in range(2, 12): - asyncio.ensure_future(create_photoframe("assets/images/test-image.webp", i)) + asyncio.ensure_future(load_images_from_listing()) asyncio.ensure_future(main()) From ff18c1414c65040af1a9eaa03ab26f5d75c7aa89 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 19:39:15 +0100 Subject: [PATCH 088/198] Implement image upload resize --- packages/editor/main.py | 54 +++++++++++++------------- packages/editor/scripts/canvas_ctx.py | 1 + packages/editor/scripts/editor.py | 55 +++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 29 deletions(-) diff --git a/packages/editor/main.py b/packages/editor/main.py index c15955d2..6fb12b35 100644 --- a/packages/editor/main.py +++ b/packages/editor/main.py @@ -251,32 +251,34 @@ def switch_action(e: ValueChangeEventArguments) -> None: label="Text", placeholder="Start typing", ).props("id='text-input'") - bold_checkbox = ui.checkbox("Bold").props("id='bold-text'") - italics_checkbox = ui.checkbox("Italics").props("id='italics-text'") - font_family = ui.select( - [ - "Arial", - "Verdana", - "Tahoma", - "Trebuchet MS", - "Times New Roman", - "Georgia", - "Garamond", - "Courier New", - "Brush Script MT", - ], - value="Arial", - ).props("id='text-font-family'") - add_text_button = ui.button( - "Add to canvas", - on_click=lambda: ( - ui.run_javascript(""" - const event = new Event("addText"); - document.querySelector("#text-input").dispatchEvent(event); - """), - text_input.set_value(""), - ), - ) + with ui.row(): + bold_checkbox = ui.checkbox("Bold").props("id='bold-text'") + italics_checkbox = ui.checkbox("Italics").props("id='italics-text'") + with ui.row(): + font_family = ui.select( + [ + "Arial", + "Verdana", + "Tahoma", + "Trebuchet MS", + "Times New Roman", + "Georgia", + "Garamond", + "Courier New", + "Brush Script MT", + ], + value="Arial", + ).props("id='text-font-family'") + add_text_button = ui.button( + "Add to canvas", + on_click=lambda: ( + ui.run_javascript(""" + const event = new Event("addText"); + document.querySelector("#text-input").dispatchEvent(event); + """), + text_input.set_value(""), + ), + ) ui.add_body_html(""" diff --git a/packages/editor/scripts/canvas_ctx.py b/packages/editor/scripts/canvas_ctx.py index 7ef23328..7694362b 100644 --- a/packages/editor/scripts/canvas_ctx.py +++ b/packages/editor/scripts/canvas_ctx.py @@ -108,6 +108,7 @@ class CanvasContext: start_coords: list[float] prev_stroke_style: str prev_line_width: int + size_change: int # Builtin attributes canvas: Any diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index 4a87749d..88dd8c71 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -78,6 +78,7 @@ ctx.start_coords = [0, 0] ctx.prev_stroke_style = "black" ctx.prev_line_width = 5 +ctx.size_change = 0 buffer_ctx.imageSmoothingEnabled = False @@ -182,9 +183,25 @@ def draw_clip(img_bitmap: ImageBitmap) -> None: return True buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) if ctx.moving_image: - buffer_ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) + ratio = ctx.current_img.width / ctx.current_img.height + if ctx.current_img.width < ctx.current_img.height: + buffer_ctx.drawImage( + ctx.current_img, + x - (ctx.current_img.width + ctx.size_change) / 2, + y - (ctx.current_img.height + ctx.size_change * ratio) / 2, + ctx.current_img.width + ctx.size_change, + ctx.current_img.height + ctx.size_change * ratio, + ) + else: + buffer_ctx.drawImage( + ctx.current_img, + x - (ctx.current_img.width + ctx.size_change * ratio) / 2, + y - (ctx.current_img.height + ctx.size_change) / 2, + ctx.current_img.width + ctx.size_change * ratio, + ctx.current_img.height + ctx.size_change, + ) return True - if ctx.writing_text: + if ctx.writing_text and not ctx.text_placed: text_dimensions = ctx.measureText(ctx.text_value) buffer_ctx.fillText( ctx.text_value, @@ -482,8 +499,25 @@ def special_actions(x: float, y: float) -> bool: if ctx.moving_image: ctx.moving_image = False buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) - ctx.drawImage(ctx.current_img, x - ctx.current_img.width / 2, y - ctx.current_img.height / 2) + ratio = ctx.current_img.width / ctx.current_img.height + if ctx.current_img.width < ctx.current_img.height: + ctx.drawImage( + ctx.current_img, + x - (ctx.current_img.width + ctx.size_change) / 2, + y - (ctx.current_img.height + ctx.size_change * ratio) / 2, + ctx.current_img.width + ctx.size_change, + ctx.current_img.height + ctx.size_change * ratio, + ) + else: + ctx.drawImage( + ctx.current_img, + x - (ctx.current_img.width + ctx.size_change * ratio) / 2, + y - (ctx.current_img.height + ctx.size_change) / 2, + ctx.current_img.width + ctx.size_change * ratio, + ctx.current_img.height + ctx.size_change, + ) ctx.globalCompositeOperation = ctx.prev_operation + ctx.size_change = 0 save_history() return True @@ -737,6 +771,21 @@ def handle_scroll(e: Event) -> None: ctx.font = f"{ctx.text_settings['italics']} {ctx.text_settings['bold']} {ctx.text_settings['size']}px {ctx.text_settings['font-family']}" # noqa: E501 buffer_ctx.font = f"{ctx.text_settings['italics']} {ctx.text_settings['bold']} {ctx.text_settings['size']}px {ctx.text_settings['font-family']}" # noqa: E501 show_action_icon(x, y) + elif ctx.moving_image: + if ( + e.deltaY > 0 + and min(ctx.current_img.width + ctx.size_change, ctx.current_img.height + ctx.size_change) > MIN_TEXT_SIZE + ): + ctx.size_change -= 5 + elif ( + e.deltaY < 0 + and max(ctx.current_img.width + ctx.size_change, ctx.current_img.height + ctx.size_change) + < MAX_TEXT_SIZE * 100 + ): + ctx.size_change += 5 + show_action_icon(x, y) + elif ctx.moving_clip: + pass window.addEventListener("resize", resize) From fc45f093324b70757cf67965c62db0fa2938c5ed Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 19:53:13 +0100 Subject: [PATCH 089/198] Implement clip resize --- packages/editor/scripts/editor.py | 76 ++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index 88dd8c71..79a571b9 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -169,14 +169,36 @@ def show_action_icon(x: float, y: float) -> bool: def draw_clip(img_bitmap: ImageBitmap) -> None: buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) - - buffer_ctx.strokeRect( - x - img_bitmap.width / 2, - y - img_bitmap.height / 2, - img_bitmap.width, - img_bitmap.height, - ) - buffer_ctx.drawImage(img_bitmap, x - img_bitmap.width / 2, y - img_bitmap.height / 2) + ratio = img_bitmap.width / img_bitmap.height + + if img_bitmap.width < img_bitmap.height: + buffer_ctx.strokeRect( + x - (img_bitmap.width + ctx.size_change) / 2, + y - (img_bitmap.height + ctx.size_change * ratio) / 2, + img_bitmap.width + ctx.size_change, + img_bitmap.height + ctx.size_change * ratio, + ) + buffer_ctx.drawImage( + img_bitmap, + x - (img_bitmap.width + ctx.size_change) / 2, + y - (img_bitmap.height + ctx.size_change * ratio) / 2, + img_bitmap.width + ctx.size_change, + img_bitmap.height + ctx.size_change * ratio, + ) + else: + buffer_ctx.strokeRect( + x - (img_bitmap.width + ctx.size_change * ratio) / 2, + y - (img_bitmap.height + ctx.size_change) / 2, + img_bitmap.width + ctx.size_change * ratio, + img_bitmap.height + ctx.size_change, + ) + buffer_ctx.drawImage( + img_bitmap, + x - (img_bitmap.width + ctx.size_change * ratio) / 2, + y - (img_bitmap.height + ctx.size_change) / 2, + img_bitmap.width + ctx.size_change * ratio, + img_bitmap.height + ctx.size_change, + ) if ctx.moving_clip: createImageBitmap(ctx.prev_data).then(draw_clip) @@ -539,7 +561,26 @@ def special_actions(x: float, y: float) -> bool: def draw_clip(img_bitmap: ImageBitmap) -> None: buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) - ctx.drawImage(img_bitmap, x - img_bitmap.width / 2, y - img_bitmap.height / 2) + ratio = img_bitmap.width / img_bitmap.height + + if img_bitmap.width < img_bitmap.height: + ctx.drawImage( + img_bitmap, + x - (img_bitmap.width + ctx.size_change) / 2, + y - (img_bitmap.height + ctx.size_change * ratio) / 2, + img_bitmap.width + ctx.size_change, + img_bitmap.height + ctx.size_change * ratio, + ) + else: + ctx.drawImage( + img_bitmap, + x - (img_bitmap.width + ctx.size_change * ratio) / 2, + y - (img_bitmap.height + ctx.size_change) / 2, + img_bitmap.width + ctx.size_change * ratio, + img_bitmap.height + ctx.size_change, + ) + + ctx.size_change = 0 save_history() createImageBitmap(ctx.prev_data).then(draw_clip) @@ -776,16 +817,27 @@ def handle_scroll(e: Event) -> None: e.deltaY > 0 and min(ctx.current_img.width + ctx.size_change, ctx.current_img.height + ctx.size_change) > MIN_TEXT_SIZE ): - ctx.size_change -= 5 + ctx.size_change -= 10 elif ( e.deltaY < 0 and max(ctx.current_img.width + ctx.size_change, ctx.current_img.height + ctx.size_change) < MAX_TEXT_SIZE * 100 ): - ctx.size_change += 5 + ctx.size_change += 10 show_action_icon(x, y) elif ctx.moving_clip: - pass + if ( + e.deltaY > 0 + and min(ctx.prev_data.width + ctx.size_change, ctx.prev_data.height + ctx.size_change) > MIN_TEXT_SIZE + ): + ctx.size_change -= 10 + elif ( + e.deltaY < 0 + and max(ctx.prev_data.width + ctx.size_change, ctx.prev_data.height + ctx.size_change) + < MAX_TEXT_SIZE * 100 + ): + ctx.size_change += 10 + show_action_icon(x, y) window.addEventListener("resize", resize) From 1a20a51bba19879f9b6240f706bd17cd79fd2d71 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 21:30:04 +0100 Subject: [PATCH 090/198] Fix formatting --- packages/editor/scripts/editor.py | 13 ++++++++++++- packages/editor/scripts/shortcuts.py | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index 79a571b9..c06d05af 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -240,6 +240,18 @@ def draw_clip(img_bitmap: ImageBitmap) -> None: y - ctx.start_coords[1], ) return True + regular_icon_show(x, y) + return False + + +def regular_icon_show(x: float, y: float) -> None: + """Show preview for regular actions. + + Args: + x (float): X coordinate + y (float): Y coordinate + + """ if ctx.type == "smooth": buffer_ctx.beginPath() buffer_ctx.arc(x, y, ctx.lineWidth / 2, 0, 2 * Math.PI) # Put a dot here @@ -255,7 +267,6 @@ def draw_clip(img_bitmap: ImageBitmap) -> None: buffer_ctx.stroke() buffer_ctx.lineWidth = prev_width buffer_ctx.fillStyle = prev_fill - return False def get_smudge_data(x: float, y: float) -> ImageData: diff --git a/packages/editor/scripts/shortcuts.py b/packages/editor/scripts/shortcuts.py index 7c3c1751..96ac436e 100644 --- a/packages/editor/scripts/shortcuts.py +++ b/packages/editor/scripts/shortcuts.py @@ -12,6 +12,7 @@ def handle_toggle(elem: Element, data: list[str]) -> None: Args: elem (Element): Toggle element data (list[str]): Keybind data + """ btn_dict = {btn.innerText: btn for btn in elem.children} @@ -27,6 +28,7 @@ def handle_btn(elem: Element, data: list[str]) -> None: Args: elem (Element): Button element data (list[str]): Keybind data + """ action = elem.click key = data[0] @@ -52,6 +54,7 @@ def handle_keydown(event: KeyboardEvent) -> None: Args: event (KeyboardEvent): Keydown event + """ # Disable keybinds when writing text if event.target == text_input: From 9dea0d329e0194dd667b65359f8a72308d892122 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 22:44:00 +0100 Subject: [PATCH 091/198] Delete image/text/clipped region upon pressing the backspace key --- packages/editor/scripts/editor.py | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index c06d05af..bff23780 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -6,6 +6,7 @@ Event, Image, ImageData, + KeyboardEvent, Math, MouseEvent, Object, @@ -851,10 +852,41 @@ def handle_scroll(e: Event) -> None: show_action_icon(x, y) +@create_proxy +def keydown_event(event: KeyboardEvent) -> None: + """Handle keydown events. + + Args: + event (KeyboardEvent): Keydown event + + """ + if event.key == "Backspace": + if ctx.moving_image: + ctx.moving_image = False + ctx.globalCompositeOperation = ctx.prev_operation + ctx.size_change = 0 + elif ctx.moving_clip: + ctx.moving_clip = False + ctx.setLineDash([]) + buffer_ctx.setLineDash([]) + ctx.strokeStyle = ctx.prev_stroke_style + ctx.lineWidth = ctx.prev_line_width + + buffer_ctx.strokeStyle = ctx.prev_stroke_style + buffer_ctx.lineWidth = ctx.prev_line_width + elif ctx.writing_text: + ctx.writing_text = False + ctx.text_placed = True + ctx.globalCompositeOperation = ctx.prev_operation + buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + + window.addEventListener("resize", resize) ctx.current_img.addEventListener("load", resize) +document.addEventListener("keydown", keydown_event) + # The wheel event is for most browsers. The mousewheel event is deprecated # but the wheel event is not supported by Safari and Webviewer on iOS. canvas.addEventListener("wheel", handle_scroll) From e6bb2bbf73face0896a3d6bf058d59ca1885abfd Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Fri, 15 Aug 2025 23:52:00 +0100 Subject: [PATCH 092/198] Implement rotations --- packages/editor/scripts/canvas_ctx.py | 11 +- packages/editor/scripts/editor.py | 210 +++++++++++++++++++------- 2 files changed, 164 insertions(+), 57 deletions(-) diff --git a/packages/editor/scripts/canvas_ctx.py b/packages/editor/scripts/canvas_ctx.py index 7694362b..99f89ac1 100644 --- a/packages/editor/scripts/canvas_ctx.py +++ b/packages/editor/scripts/canvas_ctx.py @@ -109,6 +109,9 @@ class CanvasContext: prev_stroke_style: str prev_line_width: int size_change: int + rotation: float + is_rotating: bool + current_position: list[float] # Builtin attributes canvas: Any @@ -437,9 +440,9 @@ def restore(self) -> None: """Add restore.""" self.ctx.restore() - def rotate(self) -> None: + def rotate(self, angle: float) -> None: """Add rotate.""" - self.ctx.rotate() + self.ctx.rotate(angle) def roundRect(self) -> None: # noqa: N802 """Add roundRect.""" @@ -477,6 +480,6 @@ def transform(self) -> None: """Add transform.""" self.ctx.transform() - def translate(self) -> None: + def translate(self, x: float, y: float) -> None: """Add translate.""" - self.ctx.translate() + self.ctx.translate(x, y) diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index bff23780..cf48fe8b 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -80,6 +80,9 @@ ctx.prev_stroke_style = "black" ctx.prev_line_width = 5 ctx.size_change = 0 +ctx.rotation = 0 +ctx.is_rotating = False +ctx.current_position = [0, 0] buffer_ctx.imageSmoothingEnabled = False @@ -92,8 +95,9 @@ ctx.history = [] ctx.history_index = -1 MAX_HISTORY = 50 -MIN_TEXT_SIZE = 20 -MAX_TEXT_SIZE = 200 +MIN_RESIZE_SIZE = 20 +MAX_RESIZE_SIZE = 200 +ROTATION_SPEED = 3 PIXEL_SIZE = 8 SMUDGE_BLEND_FACTOR = 0.5 @@ -170,70 +174,101 @@ def show_action_icon(x: float, y: float) -> bool: def draw_clip(img_bitmap: ImageBitmap) -> None: buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + + buffer_ctx.translate( + x, + y, + ) + buffer_ctx.rotate(ctx.rotation) ratio = img_bitmap.width / img_bitmap.height if img_bitmap.width < img_bitmap.height: buffer_ctx.strokeRect( - x - (img_bitmap.width + ctx.size_change) / 2, - y - (img_bitmap.height + ctx.size_change * ratio) / 2, + -(img_bitmap.width + ctx.size_change) / 2, + -(img_bitmap.height + ctx.size_change * ratio) / 2, img_bitmap.width + ctx.size_change, img_bitmap.height + ctx.size_change * ratio, ) buffer_ctx.drawImage( img_bitmap, - x - (img_bitmap.width + ctx.size_change) / 2, - y - (img_bitmap.height + ctx.size_change * ratio) / 2, + -(img_bitmap.width + ctx.size_change) / 2, + -(img_bitmap.height + ctx.size_change * ratio) / 2, img_bitmap.width + ctx.size_change, img_bitmap.height + ctx.size_change * ratio, ) else: buffer_ctx.strokeRect( - x - (img_bitmap.width + ctx.size_change * ratio) / 2, - y - (img_bitmap.height + ctx.size_change) / 2, + -(img_bitmap.width + ctx.size_change * ratio) / 2, + -(img_bitmap.height + ctx.size_change) / 2, img_bitmap.width + ctx.size_change * ratio, img_bitmap.height + ctx.size_change, ) buffer_ctx.drawImage( img_bitmap, - x - (img_bitmap.width + ctx.size_change * ratio) / 2, - y - (img_bitmap.height + ctx.size_change) / 2, + -(img_bitmap.width + ctx.size_change * ratio) / 2, + -(img_bitmap.height + ctx.size_change) / 2, img_bitmap.width + ctx.size_change * ratio, img_bitmap.height + ctx.size_change, ) + buffer_ctx.rotate(-ctx.rotation) + buffer_ctx.translate( + -x, + -y, + ) if ctx.moving_clip: createImageBitmap(ctx.prev_data).then(draw_clip) return True buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) if ctx.moving_image: + buffer_ctx.translate( + x, + y, + ) + buffer_ctx.rotate(ctx.rotation) ratio = ctx.current_img.width / ctx.current_img.height if ctx.current_img.width < ctx.current_img.height: buffer_ctx.drawImage( ctx.current_img, - x - (ctx.current_img.width + ctx.size_change) / 2, - y - (ctx.current_img.height + ctx.size_change * ratio) / 2, + -(ctx.current_img.width + ctx.size_change) / 2, + -(ctx.current_img.height + ctx.size_change * ratio) / 2, ctx.current_img.width + ctx.size_change, ctx.current_img.height + ctx.size_change * ratio, ) else: buffer_ctx.drawImage( ctx.current_img, - x - (ctx.current_img.width + ctx.size_change * ratio) / 2, - y - (ctx.current_img.height + ctx.size_change) / 2, + -(ctx.current_img.width + ctx.size_change * ratio) / 2, + -(ctx.current_img.height + ctx.size_change) / 2, ctx.current_img.width + ctx.size_change * ratio, ctx.current_img.height + ctx.size_change, ) + + buffer_ctx.rotate(-ctx.rotation) + buffer_ctx.translate( + -x, + -y, + ) return True if ctx.writing_text and not ctx.text_placed: + buffer_ctx.translate( + x, + y, + ) + buffer_ctx.rotate(ctx.rotation) text_dimensions = ctx.measureText(ctx.text_value) buffer_ctx.fillText( ctx.text_value, - x - text_dimensions.width / 2, - y + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, + -text_dimensions.width / 2, + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, + ) + buffer_ctx.rotate(-ctx.rotation) + buffer_ctx.translate( + -x, + -y, ) return True if ctx.clipping: - ctx.beginPath() buffer_ctx.strokeRect( ctx.start_coords[0], ctx.start_coords[1], @@ -365,7 +400,7 @@ def mouse_tracker(event: MouseEvent) -> None: """ x, y = get_canvas_coords(event) - + ctx.current_position = [x, y] if show_action_icon(x, y): return if not ctx.text_placed: @@ -531,41 +566,33 @@ def special_actions(x: float, y: float) -> bool: """ if ctx.moving_image: - ctx.moving_image = False - buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) - ratio = ctx.current_img.width / ctx.current_img.height - if ctx.current_img.width < ctx.current_img.height: - ctx.drawImage( - ctx.current_img, - x - (ctx.current_img.width + ctx.size_change) / 2, - y - (ctx.current_img.height + ctx.size_change * ratio) / 2, - ctx.current_img.width + ctx.size_change, - ctx.current_img.height + ctx.size_change * ratio, - ) - else: - ctx.drawImage( - ctx.current_img, - x - (ctx.current_img.width + ctx.size_change * ratio) / 2, - y - (ctx.current_img.height + ctx.size_change) / 2, - ctx.current_img.width + ctx.size_change * ratio, - ctx.current_img.height + ctx.size_change, - ) - ctx.globalCompositeOperation = ctx.prev_operation - ctx.size_change = 0 - save_history() + draw_image(x, y) return True if ctx.writing_text: ctx.text_placed = True buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + ctx.translate( + x, + y, + ) + ctx.rotate(ctx.rotation) text_dimensions = ctx.measureText(ctx.text_value) ctx.fillText( ctx.text_value, - x - text_dimensions.width / 2, - y + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, + -text_dimensions.width / 2, + (text_dimensions.actualBoundingBoxAscent + text_dimensions.actualBoundingBoxDescent) / 2, ) ctx.globalCompositeOperation = ctx.prev_operation + + ctx.rotate(-ctx.rotation) + ctx.translate( + -x, + -y, + ) + + ctx.rotation = 0 return True if ctx.moving_clip: @@ -573,26 +600,38 @@ def special_actions(x: float, y: float) -> bool: def draw_clip(img_bitmap: ImageBitmap) -> None: buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + ctx.translate( + x, + y, + ) + ctx.rotate(ctx.rotation) ratio = img_bitmap.width / img_bitmap.height if img_bitmap.width < img_bitmap.height: ctx.drawImage( img_bitmap, - x - (img_bitmap.width + ctx.size_change) / 2, - y - (img_bitmap.height + ctx.size_change * ratio) / 2, + -(img_bitmap.width + ctx.size_change) / 2, + -(img_bitmap.height + ctx.size_change * ratio) / 2, img_bitmap.width + ctx.size_change, img_bitmap.height + ctx.size_change * ratio, ) else: ctx.drawImage( img_bitmap, - x - (img_bitmap.width + ctx.size_change * ratio) / 2, - y - (img_bitmap.height + ctx.size_change) / 2, + -(img_bitmap.width + ctx.size_change * ratio) / 2, + -(img_bitmap.height + ctx.size_change) / 2, img_bitmap.width + ctx.size_change * ratio, img_bitmap.height + ctx.size_change, ) ctx.size_change = 0 + + ctx.rotate(-ctx.rotation) + ctx.translate( + -x, + -y, + ) + ctx.rotation = 0 save_history() createImageBitmap(ctx.prev_data).then(draw_clip) @@ -608,6 +647,49 @@ def draw_clip(img_bitmap: ImageBitmap) -> None: return False +def draw_image(x: float, y: float) -> None: + """Draws the uploaded image to the canvas. + + Args: + x (float): X coordinate + y (float): Y coordinate + + """ + ctx.moving_image = False + buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + ctx.translate( + x, + y, + ) + ctx.rotate(ctx.rotation) + ratio = ctx.current_img.width / ctx.current_img.height + if ctx.current_img.width < ctx.current_img.height: + ctx.drawImage( + ctx.current_img, + -(ctx.current_img.width + ctx.size_change) / 2, + -(ctx.current_img.height + ctx.size_change * ratio) / 2, + ctx.current_img.width + ctx.size_change, + ctx.current_img.height + ctx.size_change * ratio, + ) + else: + ctx.drawImage( + ctx.current_img, + -(ctx.current_img.width + ctx.size_change * ratio) / 2, + -(ctx.current_img.height + ctx.size_change) / 2, + ctx.current_img.width + ctx.size_change * ratio, + ctx.current_img.height + ctx.size_change, + ) + ctx.globalCompositeOperation = ctx.prev_operation + ctx.size_change = 0 + ctx.rotate(-ctx.rotation) + ctx.translate( + -x, + -y, + ) + ctx.rotation = 0 + save_history() + + @when("colourChange", "body") def colour_change(_: Event) -> None: """Handle colour change. @@ -817,9 +899,9 @@ def handle_scroll(e: Event) -> None: x, y = get_canvas_coords(e) if ctx.writing_text: # ctx.text_settings["size"] is an int - if e.deltaY > 0 and ctx.text_settings["size"] > MIN_TEXT_SIZE: # pyright: ignore[reportOperatorIssue] + if e.deltaY > 0 and ctx.text_settings["size"] > MIN_RESIZE_SIZE: # pyright: ignore[reportOperatorIssue] ctx.text_settings["size"] -= 5 # pyright: ignore[reportOperatorIssue] - elif e.deltaY < 0 and ctx.text_settings["size"] < MAX_TEXT_SIZE: # pyright: ignore[reportOperatorIssue] + elif e.deltaY < 0 and ctx.text_settings["size"] < MAX_RESIZE_SIZE: # pyright: ignore[reportOperatorIssue] ctx.text_settings["size"] += 5 # pyright: ignore[reportOperatorIssue] ctx.font = f"{ctx.text_settings['italics']} {ctx.text_settings['bold']} {ctx.text_settings['size']}px {ctx.text_settings['font-family']}" # noqa: E501 buffer_ctx.font = f"{ctx.text_settings['italics']} {ctx.text_settings['bold']} {ctx.text_settings['size']}px {ctx.text_settings['font-family']}" # noqa: E501 @@ -827,26 +909,27 @@ def handle_scroll(e: Event) -> None: elif ctx.moving_image: if ( e.deltaY > 0 - and min(ctx.current_img.width + ctx.size_change, ctx.current_img.height + ctx.size_change) > MIN_TEXT_SIZE + and min(ctx.current_img.width + ctx.size_change, ctx.current_img.height + ctx.size_change) + > MIN_RESIZE_SIZE ): ctx.size_change -= 10 elif ( e.deltaY < 0 and max(ctx.current_img.width + ctx.size_change, ctx.current_img.height + ctx.size_change) - < MAX_TEXT_SIZE * 100 + < MAX_RESIZE_SIZE * 100 ): ctx.size_change += 10 show_action_icon(x, y) elif ctx.moving_clip: if ( e.deltaY > 0 - and min(ctx.prev_data.width + ctx.size_change, ctx.prev_data.height + ctx.size_change) > MIN_TEXT_SIZE + and min(ctx.prev_data.width + ctx.size_change, ctx.prev_data.height + ctx.size_change) > MIN_RESIZE_SIZE ): ctx.size_change -= 10 elif ( e.deltaY < 0 and max(ctx.prev_data.width + ctx.size_change, ctx.prev_data.height + ctx.size_change) - < MAX_TEXT_SIZE * 100 + < MAX_RESIZE_SIZE * 100 ): ctx.size_change += 10 show_action_icon(x, y) @@ -878,7 +961,27 @@ def keydown_event(event: KeyboardEvent) -> None: ctx.writing_text = False ctx.text_placed = True ctx.globalCompositeOperation = ctx.prev_operation - buffer_ctx.clearRect(0, 0, canvas.width, canvas.height) + show_action_icon(ctx.current_position[0], ctx.current_position[1]) + elif event.key == "Alt": + ctx.is_rotating = True + elif event.key == "ArrowLeft" and ctx.is_rotating and (ctx.moving_image or ctx.moving_clip or ctx.writing_text): + ctx.rotation -= Math.PI / 180 * ROTATION_SPEED + show_action_icon(ctx.current_position[0], ctx.current_position[1]) + elif event.key == "ArrowRight" and ctx.is_rotating and (ctx.moving_image or ctx.moving_clip or ctx.writing_text): + ctx.rotation += Math.PI / 180 * ROTATION_SPEED + show_action_icon(ctx.current_position[0], ctx.current_position[1]) + + +@create_proxy +def keyup_event(event: KeyboardEvent) -> None: + """Handle keyup event. + + Args: + event (KeyboardEvent): Keyup event + + """ + if event.key == "Alt": + ctx.is_rotating = False window.addEventListener("resize", resize) @@ -886,6 +989,7 @@ def keydown_event(event: KeyboardEvent) -> None: ctx.current_img.addEventListener("load", resize) document.addEventListener("keydown", keydown_event) +document.addEventListener("keyup", keyup_event) # The wheel event is for most browsers. The mousewheel event is deprecated # but the wheel event is not supported by Safari and Webviewer on iOS. From 7579a6ea30cea0ecfd434cbf7d6413afbf62faa3 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Sat, 16 Aug 2025 02:52:30 +0300 Subject: [PATCH 093/198] move github callback uri to an env var --- docker-compose.yaml | 2 +- packages/backend/.env.template | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index b5463fbe..79e3e305 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -107,7 +107,7 @@ services: GOTRUE_EXTERNAL_GITHUB_ENABLED: true GOTRUE_EXTERNAL_GITHUB_CLIENT_ID: ${CLIENT_ID} GOTRUE_EXTERNAL_GITHUB_SECRET: ${CLIENT_SECRET} - GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI: "http://localhost:8000/auth/v1/callback" + GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI: ${GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI} meta: container_name: supabase-meta diff --git a/packages/backend/.env.template b/packages/backend/.env.template index 1ec44501..1fdc7629 100644 --- a/packages/backend/.env.template +++ b/packages/backend/.env.template @@ -37,6 +37,10 @@ POOLER_DB_POOL_SIZE="5" KONG_HTTP_PORT="8000" KONG_HTTPS_PORT="8443" +# Auth +# This is the same as the callback URL you set in your GitHub app. +GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI="http://localhost:8000/auth/v1/callback" + # General SITE_URL="http://localhost:3000" ADDITIONAL_REDIRECT_URLS="http://localhost:9000/auth" From 3c026b6747deaaad7f10eec17fa77085040d498e Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Sat, 16 Aug 2025 02:53:16 +0300 Subject: [PATCH 094/198] Add the editor bit to docker compose as well and mount files instead of copying them into the container (at least for now) --- Dockerfile.backend | 2 +- docker-compose.yaml | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Dockerfile.backend b/Dockerfile.backend index 3457eb71..9f60c2c7 100644 --- a/Dockerfile.backend +++ b/Dockerfile.backend @@ -9,7 +9,7 @@ RUN --mount=type=cache,target=/root/.cache/uv \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \ uv sync --frozen --no-install-workspace --package=backend -ADD ./packages/backend /app +# ADD ./packages/backend /app # we'll rely on mounts for now # RUN --mount=type=cache,target=/root/.cache/uv \ # uv sync --frozen diff --git a/docker-compose.yaml b/docker-compose.yaml index 79e3e305..508d3b67 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,7 +1,7 @@ name: cj12 services: - backend: + cj12-backend: build: context: . dockerfile: Dockerfile.backend @@ -9,10 +9,25 @@ services: container_name: cj12-backend ports: - "9000:8060" + volumes: + - ./packages/backend:/app + - ./packages/backend/.env:/app/.env:ro env_file: ./packages/backend/.env # networks: # - shared-net + cj12-editor: + image: zauberzeug/nicegui:latest + restart: always + ports: + - 9080:8080 + environment: + - PUID=1000 # change this to your user id + - PGID=1000 # change this to your group id + volumes: + - ./packages/editor:/app + + studio: container_name: supabase-studio image: supabase/studio:2025.06.30-sha-6f5982d From 0dce341209d08c0cf1a01c75f61f76a6ae3e51c7 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Sat, 16 Aug 2025 02:55:39 +0300 Subject: [PATCH 095/198] add optional network config for the editor as well for the shared network --- docker-compose.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker-compose.yaml b/docker-compose.yaml index 508d3b67..6c2e23d0 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -26,6 +26,8 @@ services: - PGID=1000 # change this to your group id volumes: - ./packages/editor:/app + # networks: + # - shared-net studio: @@ -237,6 +239,7 @@ services: volumes: db-config: + # networks: # shared-net: # external: true From d371ca1b7fa915d0991fdacad1f434bf11d5fad1 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Sat, 16 Aug 2025 03:01:30 +0300 Subject: [PATCH 096/198] yaml formatting --- docker-compose.yaml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 6c2e23d0..12bbfe4c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -20,15 +20,14 @@ services: image: zauberzeug/nicegui:latest restart: always ports: - - 9080:8080 + - 9080:8080 environment: - - PUID=1000 # change this to your user id - - PGID=1000 # change this to your group id + - PUID=1000 # change this to your user id + - PGID=1000 # change this to your group id volumes: - - ./packages/editor:/app + - ./packages/editor:/app # networks: - # - shared-net - + # - shared-net studio: container_name: supabase-studio @@ -239,7 +238,6 @@ services: volumes: db-config: - # networks: # shared-net: # external: true From 0d7814f50842b261b288e9224a559cbc5632dd72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Sat, 16 Aug 2025 04:24:08 +0200 Subject: [PATCH 097/198] Added gallery layout design --- packages/gallery/assets/map.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 packages/gallery/assets/map.txt diff --git a/packages/gallery/assets/map.txt b/packages/gallery/assets/map.txt new file mode 100644 index 00000000..cb28e203 --- /dev/null +++ b/packages/gallery/assets/map.txt @@ -0,0 +1,15 @@ +x - x - x - x - x - x - x - x +| | | | +x x x x - x - x +| | | | | +x x x x - x - x +| | | | +x - x - x - x - x - x - x - x +| | | | +x - x - x x x - x - x +| | | +x - x x x x +| | | | | +x x x x x - x - x +| | | | | | +x - x - x - x - x - x - x - x From d8aa738e360e988820a18b0c4c25d2e0f6819e87 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Sat, 16 Aug 2025 05:26:08 +0300 Subject: [PATCH 098/198] Add static github pages deployment workflow --- .github/workflows/static-deploy.yaml | 43 ++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .github/workflows/static-deploy.yaml diff --git a/.github/workflows/static-deploy.yaml b/.github/workflows/static-deploy.yaml new file mode 100644 index 00000000..51f5cde5 --- /dev/null +++ b/.github/workflows/static-deploy.yaml @@ -0,0 +1,43 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["main"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Pages + uses: actions/configure-pages@v5 + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # upload only the gallery + path: "./packages/gallery" + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 From 198430d43eb53ba49abc9a33925f7b6bacea0fc1 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sat, 16 Aug 2025 03:26:32 +0100 Subject: [PATCH 099/198] Wrapped ui in a route --- packages/editor/main.py | 523 ++++++++++++++++++++-------------------- 1 file changed, 259 insertions(+), 264 deletions(-) diff --git a/packages/editor/main.py b/packages/editor/main.py index 6fb12b35..1d00ddbf 100644 --- a/packages/editor/main.py +++ b/packages/editor/main.py @@ -8,287 +8,282 @@ SPIN_COUNT = 10 -app.add_static_files("/scripts", pathlib.Path(__file__).parent / "scripts") - -ui.add_head_html(""" - - - - -""") - -ui.add_body_html(""" - -

Loading...

-
-""") - - -def do_reset(*, mode_value: bool) -> None: - """Reset the canvas.""" - if mode_value: - ui.run_javascript(f""" - const event = new Event('change'); - const typeSelect = document.querySelector("#type-select"); - typeSelect.setAttribute("value", "{mode_value}"); - typeSelect.dispatchEvent(event); - """) - reset() - - -def reset_confirmation(*, mode_value: bool = False) -> None: - """Prompt user to reset canvas.""" - with ui.dialog() as dialog, ui.card(): - ui.label("Are you sure you want to clear the canvas?") - with ui.row().style("display: flex; justify-content: space-between; width: 100%;"): - ui.button("Cancel", on_click=lambda: dialog.close()) - ui.button("Clear", on_click=lambda: (do_reset(mode_value=mode_value), dialog.close())).props("color='red'") - dialog.open() +HEX = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"] +action_options = {"pen": "🖊️", "eraser": "🧽", "smudge": "💨", "clip": "📎"} # I really don't want to do this but I don't know how else to achieve it global_vars = { "type_programatically_changed": False, } - -def revert_type() -> None: - """Revert the type change when cancel is clicked.""" - global_vars["type_programatically_changed"] = True - type_toggle.set_visibility(False) - type_toggle.value = "smooth" if type_toggle.value == "pixel" else "pixel" - type_toggle.update() - type_toggle.set_visibility(True) - global_vars["type_programatically_changed"] = False - - -def handle_type_change(dialog: ui.dialog, *, mode_value: bool) -> None: - """Handle type change.""" - dialog.close() - do_reset(mode_value=mode_value) - action_toggle.set_value("pen") - if type_toggle.value == "smooth": - width_input.enable() - width_slider.enable() - file_uploader.enable() - text_input.enable() - add_text_button.enable() - bold_checkbox.enable() - italics_checkbox.enable() - font_family.enable() - elif type_toggle.value == "pixel": - width_input.disable() - width_slider.disable() - file_uploader.disable() - text_input.disable() - add_text_button.disable() - bold_checkbox.disable() - italics_checkbox.disable() - font_family.disable() - - -def change_type(*, mode_value: bool = False) -> None: - """Prompt user to reset canvas.""" - if global_vars["type_programatically_changed"]: - return - with ui.dialog() as dialog, ui.card(): - ui.label( - """ - Are you sure you want to change the drawing mode? This will clear the canvas. - You will not be able to undo this. - """, - ).style("text-align: center;") - with ui.row().style("display: flex; justify-content: space-between; width: 100%;"): - ui.button( - "Cancel", - on_click=lambda: ( - dialog.close(), - revert_type(), - ), - ) - ui.button( - "Change", - on_click=lambda: handle_type_change(dialog, mode_value=mode_value), - ).props( - "color='red'", - ) - dialog.open() - - -def reset() -> None: - """Reset canvas.""" - ui.run_javascript(""" - const event = new Event('reset'); - document.body.dispatchEvent(event); - """) - - -Hex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"] - - -async def spin() -> None: - """Change RGB values.""" - hex_value = "" - for x in range(SPIN_COUNT): - for y in range(3): - text = random.choice(Hex) + random.choice(Hex) # noqa: S311 This isn't for cryptography - colour_values[y].text = text - if x == SPIN_COUNT - 1: - hex_value += text - await asyncio.sleep(0.1) - ui.run_javascript(f""" - window.pen = window.pen || {{}}; - window.pen.colour = "#{hex_value}"; - const event = new Event('colourChange'); - document.body.dispatchEvent(event); - """) +app.add_static_files("/scripts", pathlib.Path(__file__).parent / "scripts") -def upload_image(e: UploadEventArguments) -> None: - """Fire upload event.""" - ui.notify(f"Uploaded {e.name}") - content = base64.b64encode(e.content.read()).decode("utf-8") - ui.run_javascript(f""" - let event = new Event("change"); - const fileUpload = document.querySelector("#file-upload"); - fileUpload.src = "data:{e.type};base64,{content}"; - fileUpload.dispatchEvent(event); +@ui.page("/") +def index() -> None: # noqa: C901, PLR0915 All of the below lines need to be in this function for private viewing of the page + """Index page for the editor.""" + ui.add_head_html(""" + + + + """) - # e.sender is the file upload element which has a .reset() method - e.sender.reset() # type: ignore # noqa: PGH003 - -def switch_action(e: ValueChangeEventArguments) -> None: - """Fire switch action event.""" - if type_toggle.value == "pixel" and e.value in ("smudge", "clip"): - action_toggle.value = "pen" - ui.notify("You cannot select the smudge or select action while in pixel mode.", type="negative") - return - ui.run_javascript(f""" - const event = new Event('change'); - const actionSelect = document.querySelector("#action-select"); - actionSelect.setAttribute("value", "{e.value}"); - actionSelect.dispatchEvent(event); + ui.add_body_html(""" + +

Loading...

+
""") - -ui.element("img").props("id='file-upload'").style("display: none;") - -with ui.row().style("display: flex; width: 100%;"): - # Page controls - with ui.column().style("flex-grow: 1; flex-basis: 0;"): - dark = ui.dark_mode() - ui.switch("Dark mode").bind_value(dark) - ui.button("Clear Canvas", on_click=reset_confirmation).props("color='red'") - ui.button("Download").props("id='download-button'") - file_uploader = ( - ui.upload( - label="Upload file", - auto_upload=True, - on_upload=upload_image, - on_rejected=lambda _: ui.notify("There was an issue with the upload."), + def do_reset(*, mode_value: bool) -> None: + """Reset the canvas.""" + if mode_value: + ui.run_javascript(f""" + const event = new Event('change'); + const typeSelect = document.querySelector("#type-select"); + typeSelect.setAttribute("value", "{mode_value}"); + typeSelect.dispatchEvent(event); + """) + reset() + + def reset_confirmation(*, mode_value: bool = False) -> None: + """Prompt user to reset canvas.""" + with ui.dialog() as dialog, ui.card(): + ui.label("Are you sure you want to clear the canvas?") + with ui.row().style("display: flex; justify-content: space-between; width: 100%;"): + ui.button("Cancel", on_click=lambda: dialog.close()) + ui.button("Clear", on_click=lambda: (do_reset(mode_value=mode_value), dialog.close())).props( + "color='red'", + ) + dialog.open() + + def revert_type() -> None: + """Revert the type change when cancel is clicked.""" + global_vars["type_programatically_changed"] = True + type_toggle.set_visibility(False) + type_toggle.value = "smooth" if type_toggle.value == "pixel" else "pixel" + type_toggle.update() + type_toggle.set_visibility(True) + global_vars["type_programatically_changed"] = False + + def handle_type_change(dialog: ui.dialog, *, mode_value: bool) -> None: + """Handle type change.""" + dialog.close() + do_reset(mode_value=mode_value) + action_toggle.set_value("pen") + if type_toggle.value == "smooth": + width_input.enable() + width_slider.enable() + file_uploader.enable() + text_input.enable() + add_text_button.enable() + bold_checkbox.enable() + italics_checkbox.enable() + font_family.enable() + elif type_toggle.value == "pixel": + width_input.disable() + width_slider.disable() + file_uploader.disable() + text_input.disable() + add_text_button.disable() + bold_checkbox.disable() + italics_checkbox.disable() + font_family.disable() + + def change_type(*, mode_value: bool = False) -> None: + """Prompt user to reset canvas.""" + if global_vars["type_programatically_changed"]: + return + with ui.dialog() as dialog, ui.card(): + ui.label( + """ + Are you sure you want to change the drawing mode? This will clear the canvas. + You will not be able to undo this. + """, + ).style("text-align: center;") + with ui.row().style("display: flex; justify-content: space-between; width: 100%;"): + ui.button( + "Cancel", + on_click=lambda: ( + dialog.close(), + revert_type(), + ), + ) + ui.button( + "Change", + on_click=lambda: handle_type_change(dialog, mode_value=mode_value), + ).props( + "color='red'", + ) + dialog.open() + + def reset() -> None: + """Reset canvas.""" + ui.run_javascript(""" + const event = new Event('reset'); + document.body.dispatchEvent(event); + """) + + async def spin() -> None: + """Change RGB values.""" + hex_value = "" + for x in range(SPIN_COUNT): + for y in range(3): + text = random.choice(HEX) + random.choice(HEX) # noqa: S311 This isn't for cryptography + colour_values[y].text = text + if x == SPIN_COUNT - 1: + hex_value += text + await asyncio.sleep(0.1) + ui.run_javascript(f""" + window.pen = window.pen || {{}}; + window.pen.colour = "#{hex_value}"; + const event = new Event('colourChange'); + document.body.dispatchEvent(event); + """) + + def upload_image(e: UploadEventArguments) -> None: + """Fire upload event.""" + ui.notify(f"Uploaded {e.name}") + content = base64.b64encode(e.content.read()).decode("utf-8") + ui.run_javascript(f""" + let event = new Event("change"); + const fileUpload = document.querySelector("#file-upload"); + fileUpload.src = "data:{e.type};base64,{content}"; + fileUpload.dispatchEvent(event); + """) + # e.sender is the file upload element which has a .reset() method + e.sender.reset() # type: ignore # noqa: PGH003 + + def switch_action(e: ValueChangeEventArguments) -> None: + """Fire switch action event.""" + if type_toggle.value == "pixel" and e.value in ("smudge", "clip"): + action_toggle.value = "pen" + ui.notify("You cannot select the smudge or select action while in pixel mode.", type="negative") + return + ui.run_javascript(f""" + const event = new Event('change'); + const actionSelect = document.querySelector("#action-select"); + actionSelect.setAttribute("value", "{e.value}"); + actionSelect.dispatchEvent(event); + """) + + ui.element("img").props("id='file-upload'").style("display: none;") + + with ui.row().style("display: flex; width: 100%;"): + # Page controls + with ui.column().style("flex-grow: 1; flex-basis: 0;"): + dark = ui.dark_mode() + ui.switch("Dark mode").bind_value(dark) + ui.button("Clear Canvas", on_click=reset_confirmation).props("color='red'") + ui.button("Download").props("id='download-button'") + file_uploader = ( + ui.upload( + label="Upload file", + auto_upload=True, + on_upload=upload_image, + on_rejected=lambda _: ui.notify("There was an issue with the upload."), + ) + .props("accept='image/*' id='file-input'") + .style("width: 100%;") + ) + type_toggle = ui.toggle( + {"smooth": "✍️", "pixel": "👾"}, + value="smooth", + on_change=lambda e: change_type(mode_value=e.value), + ).props("id='type-select'") + + with ui.element("div").style("position: relative;"): + ui.element("canvas").props("id='image-canvas'").style( + "border: 1px solid black; background-color: white;", + ) + ui.element("canvas").props("id='buffer-canvas'").style( + "pointer-events: none; position: absolute; top: 0; left: 0;", ) - .props("accept='image/*' id='file-input'") - .style("width: 100%;") - ) - type_toggle = ui.toggle( - {"smooth": "✍️", "pixel": "👾"}, - value="smooth", - on_change=lambda e: change_type(mode_value=e.value), - ).props("id='type-select'") - - with ui.element("div").style("position: relative;"): - ui.element("canvas").props("id='image-canvas'").style( - "border: 1px solid black; background-color: white;", - ) - ui.element("canvas").props("id='buffer-canvas'").style( - "pointer-events: none; position: absolute; top: 0; left: 0;", - ) - # Canvas controls - with ui.column().style("flex-grow: 1; flex-basis: 0;"): - with ui.row(): - ui.button("Undo").props("id='undo-button'").props("class='keyboard-shortcuts' shortcut_data='btn,u'") - ui.button("Redo").props("id='redo-button'").props("class='keyboard-shortcuts' shortcut_data='btn,r'") - action_options = {"pen": "🖊️", "eraser": "🧽", "smudge": "💨", "clip": "📎"} + # Canvas controls + with ui.column().style("flex-grow: 1; flex-basis: 0;"): + with ui.row(): + ui.button("Undo").props("id='undo-button'").props("class='keyboard-shortcuts' shortcut_data='btn,u'") + ui.button("Redo").props("id='redo-button'").props("class='keyboard-shortcuts' shortcut_data='btn,r'") - action_toggle = ui.toggle( - action_options, - value="pen", - on_change=switch_action, - ).props( - "id='action-select' class='keyboard-shortcuts' shortcut_data='toggle,p:🖊️,e:🧽,s:💨,c:📎'", - ) - ui.separator().classes("w-full") - with ui.row(): - colour_values = [] - for colour in ["R", "G", "B"]: - with ui.column().style("align-items: center;"): - ui.label(colour) - colour_label = ui.label("00") - colour_values.append(colour_label) - ui.button("Spin", on_click=spin).props("class='keyboard-shortcuts' shortcut_data='btn,z'") - ui.separator().classes("w-full") - width_input = ui.number(label="Line Width", min=1, max=50, step=1) - width_slider = ui.slider( - min=1, - max=50, - value=5, - on_change=lambda _: ui.run_javascript(""" - const event = new Event('change'); - document.querySelector(".width-input").dispatchEvent(event); - """), - ).classes("width-input") - width_input.bind_value(width_slider) - ui.separator().classes("w-full") - text_input = ui.input( - label="Text", - placeholder="Start typing", - ).props("id='text-input'") - with ui.row(): - bold_checkbox = ui.checkbox("Bold").props("id='bold-text'") - italics_checkbox = ui.checkbox("Italics").props("id='italics-text'") - with ui.row(): - font_family = ui.select( - [ - "Arial", - "Verdana", - "Tahoma", - "Trebuchet MS", - "Times New Roman", - "Georgia", - "Garamond", - "Courier New", - "Brush Script MT", - ], - value="Arial", - ).props("id='text-font-family'") - add_text_button = ui.button( - "Add to canvas", - on_click=lambda: ( - ui.run_javascript(""" - const event = new Event("addText"); - document.querySelector("#text-input").dispatchEvent(event); - """), - text_input.set_value(""), - ), + action_toggle = ui.toggle( + action_options, + value="pen", + on_change=switch_action, + ).props( + "id='action-select' class='keyboard-shortcuts' shortcut_data='toggle,p:🖊️,e:🧽,s:💨,c:📎'", ) + ui.separator().classes("w-full") + with ui.row(): + colour_values = [] + for colour in ["R", "G", "B"]: + with ui.column().style("align-items: center;"): + ui.label(colour) + colour_label = ui.label("00") + colour_values.append(colour_label) + ui.button("Spin", on_click=spin).props("class='keyboard-shortcuts' shortcut_data='btn,z'") + ui.separator().classes("w-full") + width_input = ui.number(label="Line Width", min=1, max=50, step=1) + width_slider = ui.slider( + min=1, + max=50, + value=5, + on_change=lambda _: ui.run_javascript(""" + const event = new Event('change'); + document.querySelector(".width-input").dispatchEvent(event); + """), + ).classes("width-input") + width_input.bind_value(width_slider) + ui.separator().classes("w-full") + text_input = ui.input( + label="Text", + placeholder="Start typing", + ).props("id='text-input'") + with ui.row(): + bold_checkbox = ui.checkbox("Bold").props("id='bold-text'") + italics_checkbox = ui.checkbox("Italics").props("id='italics-text'") + with ui.row(): + font_family = ui.select( + [ + "Arial", + "Verdana", + "Tahoma", + "Trebuchet MS", + "Times New Roman", + "Georgia", + "Garamond", + "Courier New", + "Brush Script MT", + ], + value="Arial", + ).props("id='text-font-family'") + add_text_button = ui.button( + "Add to canvas", + on_click=lambda: ( + ui.run_javascript(""" + const event = new Event("addText"); + document.querySelector("#text-input").dispatchEvent(event); + """), + text_input.set_value(""), + ), + ) + + ui.add_body_html(""" + + [[fetch]] + from = "/scripts/" + files = ["canvas_ctx.py", "editor.py", "shortcuts.py"] + + + + """) -ui.add_body_html(""" - - [[fetch]] - from = "/scripts/" - files = ["canvas_ctx.py", "editor.py", "shortcuts.py"] - - - -""") - ui.run() From 765b2450fbd9e6bed11885a168afa5ccb385ccfa Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Sat, 16 Aug 2025 05:32:43 +0300 Subject: [PATCH 100/198] trigger on push --- .github/workflows/static-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/static-deploy.yaml b/.github/workflows/static-deploy.yaml index 51f5cde5..80c4f267 100644 --- a/.github/workflows/static-deploy.yaml +++ b/.github/workflows/static-deploy.yaml @@ -4,7 +4,7 @@ name: Deploy static content to Pages on: # Runs on pushes targeting the default branch push: - branches: ["main"] + branches: ["main", "test-static-deploy"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: From 93c5dfbe8f1af44120176408ba304e3563140283 Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Sat, 16 Aug 2025 06:00:46 +0300 Subject: [PATCH 101/198] add button to get to the editor + minor formatting --- packages/gallery/assets/css/style.css | 20 +++++++++ packages/gallery/assets/editor.html | 26 ++++++++++++ packages/gallery/index.html | 6 ++- packages/gallery/main.py | 61 ++++++++++++++++----------- 4 files changed, 86 insertions(+), 27 deletions(-) create mode 100644 packages/gallery/assets/editor.html diff --git a/packages/gallery/assets/css/style.css b/packages/gallery/assets/css/style.css index 35079ad5..e6934132 100644 --- a/packages/gallery/assets/css/style.css +++ b/packages/gallery/assets/css/style.css @@ -20,6 +20,26 @@ border-radius: 8px; /* rounded corners */ box-shadow: 0 4px 8px rgba(0,0,0,0.2); /* subtle shadow for depth */ display: none; + cursor: pointer; +} + + +#editor { + position: absolute; + top: 20%; + left: 50%; + transform: translate(-50%, -50%); /* perfectly center horizontally & vertically */ + max-width: 80%; /* optional, keeps text from stretching too wide */ + text-align: center; + color: black; + font-size: 28px; + font-family: sans-serif; + font-weight: bold; + background-color: white; /* highlight effect */ + padding: 12px 20px; /* padding inside box */ + border-radius: 8px; /* rounded corners */ + box-shadow: 0 4px 8px rgba(0,0,0,0.2); /* subtle shadow for depth */ + display: none; } diff --git a/packages/gallery/assets/editor.html b/packages/gallery/assets/editor.html new file mode 100644 index 00000000..ff5c06e8 --- /dev/null +++ b/packages/gallery/assets/editor.html @@ -0,0 +1,26 @@ + + + + + HHH Editor + + + + + + diff --git a/packages/gallery/index.html b/packages/gallery/index.html index 32bde86b..557bc9bc 100644 --- a/packages/gallery/index.html +++ b/packages/gallery/index.html @@ -34,7 +34,7 @@ window.LineMaterial = LineMaterial; window.GLTFLoader = GLTFLoader; window.PointerLockControls = PointerLockControls; - + @@ -43,6 +43,8 @@ addEventListener('py:ready', () => loading.close()); const instructions = document.getElementById('instructions') addEventListener('py:ready', () => instructions.style.display='block'); + const editor = document.getElementById('editor') + addEventListener('py:ready', () => editor.style.display='block'); loading.showModal(); @@ -57,9 +59,9 @@

Loading...

Click here to look around!
+
- diff --git a/packages/gallery/main.py b/packages/gallery/main.py index f1817a0c..784da0c0 100644 --- a/packages/gallery/main.py +++ b/packages/gallery/main.py @@ -4,25 +4,24 @@ ## DOCS ## https:#threejs.org/docs/ -from pyodide.ffi import to_js, create_proxy # pyright: ignore[reportMissingImports] -from pyodide.http import pyfetch # pyright: ignore[reportMissingImports] -from pyscript import when, window, document # pyright: ignore[reportMissingImports] +import asyncio +import json +from collections import defaultdict +from enum import Enum + from js import ( # pyright: ignore[reportMissingImports] - Math, THREE, + GLTFLoader, + Math, # LineSegments2, # LineMaterial, Object, - console, - GLTFLoader, PointerLockControls, + console, ) - - -from collections import defaultdict -from enum import Enum -import asyncio -import json +from pyodide.ffi import create_proxy, to_js # pyright: ignore[reportMissingImports] +from pyodide.http import pyfetch # pyright: ignore[reportMissingImports] +from pyscript import document, when, window # pyright: ignore[reportMissingImports] def log(*msgs): @@ -78,20 +77,34 @@ def create_bounding_box(obj): CONTROLS.addEventListener( "lock", create_proxy( - lambda x: setattr( - document.getElementById("instructions").style, - "display", - "none", + lambda _: ( + setattr( + document.getElementById("instructions").style, + "display", + "none", + ), + setattr( + document.getElementById("editor").style, + "display", + "none", + ), ), ), ) CONTROLS.addEventListener( "unlock", create_proxy( - lambda x: setattr( - document.getElementById("instructions").style, - "display", - "block", + lambda _: ( + setattr( + document.getElementById("instructions").style, + "display", + "block", + ), + setattr( + document.getElementById("editor").style, + "display", + "block", + ), ), ), ) @@ -103,10 +116,8 @@ def create_bounding_box(obj): INPUTS.LEFT: {"KeyH", "KeyA", "ArrowLeft"}, INPUTS.RIGHT: {"KeyL", "KeyD", "ArrowRight"}, INPUTS.BACK: {"KeyJ", "KeyS", "ArrowDown"}, - # INPUTS.UP: {"Space"}, INPUTS.DOWN: {"ShiftLeft", "ShiftRight"}, - # INPUTS.RUN: {"KeyZ"}, } KEY_STATES: dict[str, bool] = defaultdict(bool) @@ -242,7 +253,7 @@ def create_plane(texture): { "map": texture, "transparent": True, - } + }, ) geometry = THREE.PlaneGeometry.new(1, 1, 1) @@ -348,9 +359,9 @@ def inner_loader(gltf): v.visible = False - print(f"Loading done! Here's its component structure:") + print("Loading done! Here's its component structure:") print(tree_print(obj)) - print(f"Painting slots:") + print("Painting slots:") print(list(PAINTING_SLOTS.keys())) def inner_progress(xhr): From eed60f655d2e93a692ad4e357d344a87a14b66f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Sat, 16 Aug 2025 07:38:06 +0200 Subject: [PATCH 102/198] Renovated gallery layout, added loading triggers --- packages/gallery/assets/gallery_2c.glb | Bin 0 -> 25200 bytes packages/gallery/main.py | 22 ++++++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 packages/gallery/assets/gallery_2c.glb diff --git a/packages/gallery/assets/gallery_2c.glb b/packages/gallery/assets/gallery_2c.glb new file mode 100644 index 0000000000000000000000000000000000000000..56a78926a96bc354bd79910db72be3cd22540faa GIT binary patch literal 25200 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 literal 0 HcmV?d00001 diff --git a/packages/gallery/main.py b/packages/gallery/main.py index f1817a0c..207e5451 100644 --- a/packages/gallery/main.py +++ b/packages/gallery/main.py @@ -256,7 +256,7 @@ def create_plane(texture): V3 = tuple[float, float, float] V2 = tuple[float, float] -PAINTING_SLOTS: dict[int, tuple[V3, V3, V2]] = {} +PAINTING_SLOTS: list[tuple[V3, V3, V2]] = [] # doesnt work, idk why """ @@ -284,7 +284,7 @@ def create_borders(plane): async def snap_to_slot(photo, slot: int): - while slot not in PAINTING_SLOTS: + while not PAINTING_SLOTS: await asyncio.sleep(0.05) (x, y, z), (nx, ny, nz), (w, h) = PAINTING_SLOTS[slot] photo.position.x = x @@ -326,32 +326,34 @@ def inner_loader(gltf): MODULAR_GROUP.add(obj) # Backface culling - assert obj.children[0].name == "Cube" + assert obj.children[0].name.startswith("Cube") for v in obj.children[0].children: CUBES.append(v) v.material.side = THREE.FrontSide for v in obj.children[1:]: - id_ = int(v.name[-3:]) + if not v.name.startswith("pic"): + continue position: V3 = v.position.x, v.position.y, v.position.z n_array = v.geometry.attributes.normal.array - # Y-up/Z-up shenanigans - normal: V3 = (n_array[0], n_array[2], n_array[1]) + # Beware possible Y-up/Z-up shenanigans + normal: V3 = (-n_array[2], n_array[1], n_array[0]) + id_ = int(v.name[-3:]) + print(id_, normal) bb = v.geometry.boundingBox size_xyz = [abs(getattr(bb.max, i) - getattr(bb.min, i)) for i in ("x", "y", "z")] # Height is Z size_wh: V2 = (max(size_xyz[0], size_xyz[1]), (size_xyz[2])) - PAINTING_SLOTS[id_] = (position, normal, size_wh) + PAINTING_SLOTS.append((position, normal, size_wh)) v.visible = False print(f"Loading done! Here's its component structure:") print(tree_print(obj)) - print(f"Painting slots:") - print(list(PAINTING_SLOTS.keys())) + print(f"Number of painting slots:", len(PAINTING_SLOTS)) def inner_progress(xhr): print(str(xhr.loaded) + " loaded") @@ -361,7 +363,7 @@ def inner_error(error): loader = GLTFLoader.new() loader.load( - "./assets/gallery.glb", + "./assets/gallery_2c.glb", create_proxy(inner_loader), create_proxy(inner_progress), create_proxy(inner_error), From b3431681e1f9937499d6d343d3b836325bcfc3a2 Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sat, 16 Aug 2025 18:47:49 +0100 Subject: [PATCH 103/198] Add help menu --- packages/editor/main.py | 90 ++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/packages/editor/main.py b/packages/editor/main.py index 1d00ddbf..465c7c26 100644 --- a/packages/editor/main.py +++ b/packages/editor/main.py @@ -23,24 +23,6 @@ @ui.page("/") def index() -> None: # noqa: C901, PLR0915 All of the below lines need to be in this function for private viewing of the page """Index page for the editor.""" - ui.add_head_html(""" - - - - - """) - - ui.add_body_html(""" - -

Loading...

-
- """) def do_reset(*, mode_value: bool) -> None: """Reset the canvas.""" @@ -174,13 +156,81 @@ def switch_action(e: ValueChangeEventArguments) -> None: actionSelect.dispatchEvent(event); """) + def show_help_menu() -> None: + """Show help modal.""" + with ui.dialog() as dialog, ui.card(): + with ui.card_section(): + ui.markdown( + """ + There are keybinds for the editor actions. + """, + ) + with ui.list().props("dense separator"): + ui.item("p: Select pen (🖊️) mode.") + ui.item("e: Select eraser (🧽) mode.") + ui.item("s: Select smudge (💨) mode.") + ui.item("c: Select clip (📎) mode.") + ui.item("z: Spin a new colour.") + ui.item("u: Undo.") + ui.item("r: Redo.") + ui.markdown( + """ + To add images to the canvas, upload one via the file upload, and then click where you want to add + it on the canvas. + """, + ) + ui.markdown( + """ + To add text to the canvas, type in the text input and click the `Add to canvas` button. You can + set the text to be bolded or italicised. You can also select the font from the dropdown. + """, + ) + ui.markdown( + """ + Clipped regions, images, and text can all be resized and rotated. They can be resized using the + scroll wheel or similar. They can be rotated by holding `Alt` and then pressing the + left or right arrow key. + """, + ) + ui.markdown( + """ + You can switch between the smooth (✍️) or pixel (👾) modes using the toggle below. + """, + ) + ui.button( + "Close", + on_click=dialog.close, + ) + dialog.open() + + ui.add_head_html(""" + + + + + """) + + ui.add_body_html(""" + +

Loading...

+
+ """) + ui.element("img").props("id='file-upload'").style("display: none;") with ui.row().style("display: flex; width: 100%;"): # Page controls with ui.column().style("flex-grow: 1; flex-basis: 0;"): - dark = ui.dark_mode() - ui.switch("Dark mode").bind_value(dark) + with ui.row(): + dark = ui.dark_mode() + ui.switch("Dark mode").bind_value(dark) + ui.button(icon="help", on_click=lambda: show_help_menu()) ui.button("Clear Canvas", on_click=reset_confirmation).props("color='red'") ui.button("Download").props("id='download-button'") file_uploader = ( From be1d7c072f280a0fb5ecbc573b8d817b7e4ae71e Mon Sep 17 00:00:00 2001 From: Aadil Goyal Date: Sun, 17 Aug 2025 01:26:01 +0530 Subject: [PATCH 104/198] Tried making a 4 room map Kinda works, the collision thing doesnt work and the lighting is also messed up other than tha its pretty good Also cleaned up the cood (reorganised + comments) --- packages/gallery/main.py | 485 ++++++++++++++++++++++++--------------- 1 file changed, 306 insertions(+), 179 deletions(-) diff --git a/packages/gallery/main.py b/packages/gallery/main.py index 207e5451..47073f10 100644 --- a/packages/gallery/main.py +++ b/packages/gallery/main.py @@ -4,16 +4,17 @@ ## DOCS ## https:#threejs.org/docs/ + +# -------------------------------------- IMPORTS -------------------------------------- +print('IMPORTS') + from pyodide.ffi import to_js, create_proxy # pyright: ignore[reportMissingImports] from pyodide.http import pyfetch # pyright: ignore[reportMissingImports] from pyscript import when, window, document # pyright: ignore[reportMissingImports] from js import ( # pyright: ignore[reportMissingImports] Math, THREE, - # LineSegments2, - # LineMaterial, Object, - console, GLTFLoader, PointerLockControls, ) @@ -25,16 +26,10 @@ import json -def log(*msgs): - for msg in msgs: - console.log(msg) - - -def convert_dict_to_js_object(my_dict: dict): - """Convert a Python dict to a JavaScript object.""" - return Object.fromEntries(to_js(my_dict)) - +# -------------------------------------- GLOBAL VARIABLES -------------------------------------- +print('GLOBAL VARIABLES') +# Renderer set up RENDERER = THREE.WebGLRenderer.new({"antialias": False}) RENDERER.shadowMap.enabled = False RENDERER.shadowMap.type = THREE.PCFSoftShadowMap @@ -42,61 +37,96 @@ def convert_dict_to_js_object(my_dict: dict): RENDERER.setSize(window.innerWidth, window.innerHeight) document.body.appendChild(RENDERER.domElement) -CAMERA = THREE.PerspectiveCamera.new(53, window.innerWidth / window.innerHeight, 0.01, 500) -CAMERA.position.set(3, 1, 3.5) -CAMERA.rotation.set(0, 0.4, 0) - +# Scene setup setcolor = "#8B8B8B" # Nicer than just black SCENE = THREE.Scene.new() SCENE.background = THREE.Color.new(setcolor) -# SCENE.fog = THREE.Fog.new(setcolor, 2.5, 3.5) -# CAMERA.lookAt(SCENE.position) -MODULAR_GROUP = THREE.Object3D.new() -SCENE.add(MODULAR_GROUP) +# Camera setup +CAMERA = THREE.PerspectiveCamera.new(53, window.innerWidth / window.innerHeight, 0.01, 500) +CAMERA.position.set(3, 1, 3.5) +CAMERA.rotation.set(0, 0.4, 0) +SCENE.add(CAMERA) + +# Other global variables +ROOMS: list[THREE.Group] = [] # a list of all rooms in the scene +LOADED_ROOMS: list[THREE.Group] = [] # a list of all loaded rooms (or the loaded chunks) +CURRENT_ROOM: THREE.Group = None # the room in which the player currently is +ROOM_SIZE = [11.5, 4.2, 11.5] -CUBES: list[THREE.Mesh] = [] # a list of all cubes in the scene OFFSET = 0.1 # distance which we maintain from walls +TRIGGER_COLLISION = False # whether we are currently colliding with a trigger -""" -BOUNDING_BOXES = list() # a list of all bounding boxes -OBJECTS = list() # a list of objs who have a bb +VELOCITY = THREE.Vector3.new() -def create_bounding_box(obj): - box = THREE.Box3.new().setFromObject(obj) - BOUNDING_BOXES.append(box) - OBJECTS.append(obj) - return box +REPO_URL = ( + r"https://cdn.jsdelivr.net/gh/" + r"Matiiss/pydis-cj12-heavenly-hostas@dev/" + r"packages/gallery/assets/images/" +) -CAMERA_BOUNDING_BOX = create_bounding_box(CAMERA) -SCENE.add(THREE.Box3Helper.new(CAMERA_BOUNDING_BOX, "#ff00ff")) -""" +# For Type Hinting +V3 = tuple[float, float, float] +V2 = tuple[float, float] + + +# -------------------------------------- HELPER FUNCTIONS -------------------------------------- +print('HELPER FUNCTIONS') + +# def log(*msgs): +# for msg in msgs: +# console.log(msg) + +def tree_print(x, indent=0): + # Prints a 3D model's tree structure + qu = '"' + output = " " * 4 * indent + f"{x.name or qu * 2} ({x.type})" + for i in x.children: + output += "\n" + tree_print(i, indent=indent + 1) + return output -# Camera controls and mouse lock -CONTROLS = PointerLockControls.new(CAMERA, document.body) -document.getElementById("instructions").addEventListener("click", create_proxy(CONTROLS.lock)) -CONTROLS.addEventListener( - "lock", - create_proxy( - lambda x: setattr( - document.getElementById("instructions").style, - "display", - "none", - ), - ), -) -CONTROLS.addEventListener( - "unlock", - create_proxy( - lambda x: setattr( - document.getElementById("instructions").style, - "display", - "block", - ), - ), -) +def convert_dict_to_js_object(my_dict: dict): + """Convert a Python dict to a JavaScript object.""" + return Object.fromEntries(to_js(my_dict)) + + +def mathRandom(num=1): + setNumber = -Math.random() * num + Math.random() * num + return setNumber + +def get_painting_info(p: THREE.Mesh) -> tuple[V3, V3, V2]: + position: V3 = p.position.x, p.position.y, p.position.z + + n_array = p.geometry.attributes.normal.array + # Beware possible Y-up/Z-up shenanigans + normal: V3 = (-n_array[2], n_array[1], n_array[0]) + id_ = int(p.name[-3:]) + print(id_, normal) + + bb = p.geometry.boundingBox + size_xyz = [abs(getattr(bb.max, i) - getattr(bb.min, i)) for i in ("x", "y", "z")] + # Height is Z + size_wh: V2 = (max(size_xyz[0], size_xyz[1]), (size_xyz[2])) + + return (position, normal, size_wh) + + +def get_chunk_coords() -> tuple[int, int]: + x_coord = (CAMERA.position.x - ROOM_SIZE[0]/2) // ROOM_SIZE[0] + z_coord = (CAMERA.position.z - ROOM_SIZE[2]/2) // ROOM_SIZE[2] + + if x_coord < 0: x_coord = 0 + if z_coord < 0: z_coord = 0 + + return x_coord, z_coord + + +# -------------------------------------- MOVEMENT CONTROLS -------------------------------------- +print('MOVEMENT CONTROLS') + +# Movement Controls INPUTS = Enum("INPUTS", ["FORW", "LEFT", "RIGHT", "BACK", "UP", "DOWN", "RUN"]) KEY_MAPPINGS: dict[INPUTS, set[str]] = { INPUTS.FORW: {"KeyW", "KeyK", "ArrowUp"}, @@ -125,9 +155,8 @@ def toggle_run(event): document.addEventListener("keydown", create_proxy(toggle_run)) -VELOCITY = THREE.Vector3.new() - +# Main move function def move_character(delta_time: float): pressed_keys = {k for k, v in KEY_MAPPINGS.items() if any(KEY_STATES[i] for i in v)} damping = 7 @@ -175,69 +204,127 @@ def move_character(delta_time: float): return VELOCITY -def check_collision(velocity: THREE.Vector3, delta_time: float): +# -------------------------------------- MOUSE CONTROLS -------------------------------------- +print('MOUSE CONTROLS') + +MOUSE = THREE.Vector2.new() + +# Mouse Lock +CONTROLS = PointerLockControls.new(CAMERA, document.body) +document.getElementById("instructions").addEventListener("click", create_proxy(CONTROLS.lock)) +CONTROLS.addEventListener( + "lock", + create_proxy( + lambda x: setattr( + document.getElementById("instructions").style, + "display", + "none", + ), + ), +) +CONTROLS.addEventListener( + "unlock", + create_proxy( + lambda x: setattr( + document.getElementById("instructions").style, + "display", + "block", + ), + ), +) + +# Mouse Controls +@when("mousemove", "body") +def onMouseMove(event): + event.preventDefault() + MOUSE.x = (event.clientX / window.innerWidth) * 2 - 1 + MOUSE.y = -(event.clientY / window.innerHeight) * 2 + 1 + + +# -------------------------------------- COLLISION DETECTION -------------------------------------- +print('COLLISION DETECTION') + +def check_collision(velocity: THREE.Vector3, delta_time: float) -> bool: + ''' + Checks for collision with walls (cubes) and triggers + returns true if it is safe to move and false if movement should be stopped + ''' + # print("Checking collision with walls and triggers...") + # print(CURRENT_ROOM) raycaster = THREE.Raycaster.new() direction = velocity.clone().normalize() raycaster.set(CAMERA.position, direction) - intersections = raycaster.intersectObjects(CUBES) + check_collision_with_trigger(velocity, delta_time, raycaster) + + return check_collision_with_wall(velocity, delta_time, raycaster) + +def check_collision_with_wall(velocity: THREE.Vector3, delta_time: float, raycaster: THREE.Raycaster) -> bool: + # print('walls', CURRENT_ROOM.name) + cubes = [] + [cubes.extend(c.getObjectByName("Cubes").children) for c in LOADED_ROOMS] + intersections = raycaster.intersectObjects(cubes, recursive=True) if not intersections: return True return intersections[0].distance > velocity.length() * delta_time + OFFSET +def check_collision_with_trigger(velocity: THREE.Vector3, delta_time: float, raycaster: THREE.Raycaster): + global CURRENT_ROOM, TRIGGER_COLLISION + # print('trigger', CURRENT_ROOM.name) -MOUSE = THREE.Vector2.new() + triggers = [] + [triggers.extend(c.getObjectByName("Triggers").children) for c in LOADED_ROOMS] + intersections = raycaster.intersectObjects(triggers, recursive=True) + if intersections and intersections[0].distance <= velocity.length() * delta_time: + if not TRIGGER_COLLISION: + TRIGGER_COLLISION = True + else: + if TRIGGER_COLLISION: + TRIGGER_COLLISION = False + print("Exited trigger area") -@when("mousemove", "body") -def onMouseMove(event): - event.preventDefault() - MOUSE.x = (event.clientX / window.innerWidth) * 2 - 1 - MOUSE.y = -(event.clientY / window.innerHeight) * 2 + 1 + calc = lambda x, y: (x - y/2) // y + """ + coords = get_chunk_coords() + CURRENT_ROOM = SCENE.getObjectByName(f"room_{int(coords[0])}_{int(coords[1])}") + print("UPDATED CURRENT ROOM", CURRENT_ROOM.name) + load_room() + """ -def mathRandom(num=1): - setNumber = -Math.random() * num + Math.random() * num - return setNumber +# -------------------------------------- ROOM CREATION -------------------------------------- +print('ROOM CREATION') -def generate_lights() -> None: - light = THREE.SpotLight.new(0xFF_FF_FF, 3) - light.position.set(5, 5, 2) - light.castShadow = True - light.shadow.mapSize.width = 10000 - light.shadow.mapSize.height = light.shadow.mapSize.width - light.penumbra = 0.5 - SCENE.add(light) +def generate_lights() -> THREE.Group: + light_main = THREE.SpotLight.new(0xFF_FF_FF, 3) + light_main.position.set(5, 5, 2) + light_main.castShadow = True + light_main.shadow.mapSize.width = 10000 + light_main.shadow.mapSize.height = light_main.shadow.mapSize.width + light_main.penumbra = 0.5 - lightBack = THREE.PointLight.new(0xEF_FF_FF, 1) - lightBack.position.set(0, -3, -1) - SCENE.add(lightBack) + light_back = THREE.PointLight.new(0xEF_FF_FF, 1) + light_back.position.set(0, -3, -1) - ambientLight = THREE.AmbientLight.new(0xFFFFFF, 0.3) - SCENE.add(ambientLight) + ambient_light = THREE.AmbientLight.new(0xFFFFFF, 0.3) + lights = THREE.Group.new() + lights.add(light_main) + lights.add(light_back) + lights.add(ambient_light) -REPO_URL = ( - r"https://cdn.jsdelivr.net/gh/" - r"Matiiss/pydis-cj12-heavenly-hostas@dev/" - r"packages/gallery/assets/images/" -) + return lights -def load_image(image_loc: str): +def load_image(image_loc: str) -> THREE.Texture: textureLoader = THREE.TextureLoader.new() texture = textureLoader.load(REPO_URL + image_loc) - # texture = textureLoader.load( - # image_loc, - # create_proxy(lambda e: create_photoframe(texture)), - # create_proxy(log), - # create_proxy(log), - # ) return texture -def create_plane(texture): +def create_plane(texture: THREE.Texture) -> THREE.Mesh: perms = convert_dict_to_js_object( { "map": texture, @@ -254,39 +341,10 @@ def create_plane(texture): return plane -V3 = tuple[float, float, float] -V2 = tuple[float, float] -PAINTING_SLOTS: list[tuple[V3, V3, V2]] = [] - -# doesnt work, idk why -""" -def create_borders(plane): - width = 0.02 # Width of the border - - # Create a border around the plane - borderGeometry = THREE.EdgesGeometry.new(plane.geometry) - borderMaterial = LineMaterial.new( - convert_dict_to_js_object({ - "color": "#FF0000", - "linewidth": 10 - }) - ) - border = LineSegments2.new(borderGeometry, borderMaterial) - - # Set the position and scale of the border - border.position.copy(plane.position) - border.scale.x = plane.scale.x * (1 + width) - border.scale.y = plane.scale.y * (1 + width) - border.scale.z = plane.scale.z * (1 + width) - - return border - """ - - -async def snap_to_slot(photo, slot: int): - while not PAINTING_SLOTS: - await asyncio.sleep(0.05) - (x, y, z), (nx, ny, nz), (w, h) = PAINTING_SLOTS[slot] +async def snap_to_slot(photo: THREE.Group, slot: int, picture_grp: THREE.Group) -> None: + # while not PAINTING_SLOTS: + # await asyncio.sleep(0.05) + (x, y, z), (nx, ny, nz), (w, h) = get_painting_info(picture_grp.children[slot]) photo.position.x = x photo.position.y = y photo.position.z = z @@ -296,64 +354,78 @@ async def snap_to_slot(photo, slot: int): photo.quaternion.copy(q) -async def create_photoframe(image_loc, slot: int = 0): +async def create_photoframe(image_loc, slot: int, picture_grp: THREE.Group) -> THREE.Group: texture = load_image(image_loc) plane = create_plane(texture) - # border = create_borders(plane) photo = THREE.Object3D.new() photo.add(plane) - # photo.add(border) - await snap_to_slot(photo, slot) - SCENE.add(photo) + await snap_to_slot(photo, slot, picture_grp) + photo.name = f"picture_{slot:03d}" + picture_grp.add(photo) return photo -def tree_print(x, indent=0): - # Prints a 3D model's tree structure - qu = '"' - output = " " * 4 * indent + f"{x.name or qu * 2} ({x.type})" - for i in x.children: - output += "\n" + tree_print(i, indent=indent + 1) - return output - +async def load_images_from_listing(room: THREE.Group) -> None: + r = await pyfetch(REPO_URL + "../" + "test-image-listing.json") + data = await r.text() + images = json.loads(data) -def load_gallery(): - def inner_loader(gltf): - obj = gltf.scene - MODULAR_GROUP.add(obj) + while not room.getObjectByName("Pictures"): + await asyncio.sleep(0.05) + picture_grp = room.getObjectByName("Pictures") - # Backface culling - assert obj.children[0].name.startswith("Cube") - for v in obj.children[0].children: - CUBES.append(v) - v.material.side = THREE.FrontSide + for idx, img in enumerate(images): + asyncio.ensure_future(create_photoframe(img, idx, picture_grp)) + + +def room_objects_handling(room: THREE.Group) -> THREE.Group: + assert room.children[0].name.startswith("Cube") + room.children[0].name = "Cubes" + for v in room.children[0].children: + v.material.side = THREE.FrontSide + + triggers = THREE.Group.new() + triggers.name = "Triggers" + + pictures = THREE.Group.new() + pictures.name = "Pictures" + + for v in room.children[1:]: + if v.name.startswith("trigger"): + room.remove(v) + triggers.add(v) + # v.visible = False + # size_xyz = [1, 4.2, 1.8] + + if v.name.startswith("pic"): + room.remove(v) + pictures.add(v) + v.visible = False + + room.add(triggers) + room.add(pictures) - for v in obj.children[1:]: - if not v.name.startswith("pic"): - continue - position: V3 = v.position.x, v.position.y, v.position.z + return pictures - n_array = v.geometry.attributes.normal.array - # Beware possible Y-up/Z-up shenanigans - normal: V3 = (-n_array[2], n_array[1], n_array[0]) - id_ = int(v.name[-3:]) - print(id_, normal) - bb = v.geometry.boundingBox - size_xyz = [abs(getattr(bb.max, i) - getattr(bb.min, i)) for i in ("x", "y", "z")] - # Height is Z - size_wh: V2 = (max(size_xyz[0], size_xyz[1]), (size_xyz[2])) +async def create_room(chunk_coords: tuple[int, int] = (0, 0), rotation: int = 0, room_type: int = 0) -> THREE.Group: + ''' + chunk_coords represent the coordinates of the room + rotation represents the rotation of the room, which is supposed to be multiples of pi/2 + room_type represents the type of the room (TODO) + ''' - PAINTING_SLOTS.append((position, normal, size_wh)) + lights = generate_lights() + print("Lights generated") - v.visible = False + gltf = None - print(f"Loading done! Here's its component structure:") - print(tree_print(obj)) - print(f"Number of painting slots:", len(PAINTING_SLOTS)) + def inner_loader(loaded_obj): + nonlocal gltf + gltf = loaded_obj def inner_progress(xhr): print(str(xhr.loaded) + " loaded") @@ -369,32 +441,87 @@ def inner_error(error): create_proxy(inner_error), ) + while not gltf: + await asyncio.sleep(0.05) -async def load_images_from_listing() -> None: - r = await pyfetch(REPO_URL + "../" + "test-image-listing.json") - data = await r.text() - images = json.loads(data) - for idx, img in enumerate(images): - asyncio.ensure_future(create_photoframe(img, idx)) + print('loaded gltf') + obj = gltf.scene + # obj.visible = False + obj.name = f"room_{chunk_coords[0]}_{chunk_coords[1]}" + ROOMS.append(obj) + + # Backface culling + picture_grp = room_objects_handling(obj) + + print(f"Loading done! Here's its component structure:") + print(tree_print(obj)) + print(f"Number of painting slots:", len(picture_grp.children)) + + room = gltf.scene + position = (chunk_coords[0] * ROOM_SIZE[0], 0, chunk_coords[1] * ROOM_SIZE[2]) + room.position.set(*position) + room.rotation.y = rotation * 1.57 + + + await load_images_from_listing(room) + + room.add(lights) + SCENE.add(room) + return room + + +# -------------------------------------- GALLERY LOADING -------------------------------------- +print('GALLERY LOADING') + +async def load_gallery() -> None: + print("Creating first room") + await create_room((0, 0), 2) + print("Creating second room") + await create_room((0, 1), 3) + await create_room((1, 0), 1) + await create_room((1, 1), 0) + + +""" def load_room(r: int = 3) -> None: + ''' + Loads all rooms which are at r distance from the current room + ''' + print("Loading rooms...") + for room in ROOMS: + if room not in LOADED_ROOMS: + if room.position.distanceTo(CAMERA.position) < r * ROOM_SIZE[0]: + room.visible = True + LOADED_ROOMS.append(room) + print(f"Room {room.name} loaded at position {room.position.toArray()}") + else: + print(f"Room {room.name} is too far away, not loading it.") + pass + """ async def main(): + global CURRENT_ROOM + + while not SCENE.getObjectByName("room_0_0"): + print("Waiting for the initial room to load...") + await asyncio.sleep(0.05) + print("Initial room loaded") + CURRENT_ROOM = SCENE.getObjectByName("room_0_0") + # load_room() + clock = THREE.Clock.new() while True: delta = clock.getDelta() velocity = move_character(delta) if check_collision(velocity, delta): CAMERA.position.addScaledVector(velocity, delta) - # else: - # print("COLLISION DETECTED") RENDERER.render(SCENE, CAMERA) await asyncio.sleep(0.02) if __name__ == "__main__": - generate_lights() - load_gallery() - asyncio.ensure_future(load_images_from_listing()) - + print("Loading gallery...") + asyncio.ensure_future(load_gallery()) + print("Starting main loop...") asyncio.ensure_future(main()) From 86d8dca5ac1934a46b3e54d3a54cfbe90ee3058b Mon Sep 17 00:00:00 2001 From: Yubo Wang Date: Sat, 16 Aug 2025 23:10:27 +0100 Subject: [PATCH 105/198] Allow users to continue drawing path upon leaving and reentering canvas --- packages/editor/scripts/editor.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/editor/scripts/editor.py b/packages/editor/scripts/editor.py index cf48fe8b..de6be845 100644 --- a/packages/editor/scripts/editor.py +++ b/packages/editor/scripts/editor.py @@ -454,7 +454,7 @@ def stop_path(_: MouseEvent) -> None: save_history() -@when("mouseup", "#image-canvas") +@when("mouseup", "body") def drop_media(event: MouseEvent) -> None: """Place text or clipping. @@ -504,17 +504,13 @@ def leaves_canvas(event: MouseEvent) -> None: event (MouseEvent): The mouse event """ - if not ctx.drawing: + if not ctx.drawing or ctx.clipping: return if ctx.type == "smooth" and ctx.action != "smudge": # "pen" or "eraser" x, y = get_canvas_coords(event) ctx.lineTo(x, y) ctx.stroke() - ctx.drawing = False - ctx.smudge_data = None - save_history() - @when("mousedown", "#image-canvas") def canvas_click(event: MouseEvent) -> None: From 1da8d1f24fb92e9f3c4ae24e9dcf993bce22c41a Mon Sep 17 00:00:00 2001 From: Matiiss <83066658+Matiiss@users.noreply.github.com> Date: Sun, 17 Aug 2025 05:14:32 +0300 Subject: [PATCH 106/198] Initial commit on orphan branch From 107d0382cb404a3353b611c9c606adf3be1ffbc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20D=C3=ADaz?= Date: Sun, 17 Aug 2025 07:31:38 +0200 Subject: [PATCH 107/198] Implemented improved large gallery with 55 rooms Finally implemented a tile-based gallery layout to greatly expand the image capacity. Also prettyfied the lighting with the help of an HDR from Greg Zaal @ Poly Haven (Licensed CC0) Rooms as well as painting slots are generated asynchronously from the renderer but in order, always generating first the closest element to (0,0) in hamiltonian distance. All slots are put on a global list, which is not an issue because you can know their chunk by accessing the 'parent' attr. --- .gitattributes | 1 + .../assets/{gallery.glb => gallery_0.glb} | Bin packages/gallery/assets/gallery_1.glb | Bin 0 -> 23256 bytes packages/gallery/assets/gallery_2s.glb | Bin 0 -> 21644 bytes packages/gallery/assets/gallery_3.glb | Bin 0 -> 26332 bytes packages/gallery/assets/gallery_4.glb | Bin 0 -> 31260 bytes packages/gallery/assets/lebombo_1k.hdr | Bin 0 -> 1476953 bytes packages/gallery/assets/map.txt | 6 +- .../gallery/assets/test-image-listing.json | 26 ++ packages/gallery/index.html | 2 + packages/gallery/main.py | 405 +++++++++++------- packages/gallery/map_loader.py | 114 +++++ packages/gallery/pyscript.toml | 2 +- 13 files changed, 398 insertions(+), 158 deletions(-) rename packages/gallery/assets/{gallery.glb => gallery_0.glb} (100%) create mode 100644 packages/gallery/assets/gallery_1.glb create mode 100644 packages/gallery/assets/gallery_2s.glb create mode 100644 packages/gallery/assets/gallery_3.glb create mode 100644 packages/gallery/assets/gallery_4.glb create mode 100644 packages/gallery/assets/lebombo_1k.hdr create mode 100644 packages/gallery/map_loader.py diff --git a/.gitattributes b/.gitattributes index 42868764..541aa8a6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,4 @@ *.blend binary # Model binaries *.glb binary +*.hdr binary diff --git a/packages/gallery/assets/gallery.glb b/packages/gallery/assets/gallery_0.glb similarity index 100% rename from packages/gallery/assets/gallery.glb rename to packages/gallery/assets/gallery_0.glb diff --git a/packages/gallery/assets/gallery_1.glb b/packages/gallery/assets/gallery_1.glb new file mode 100644 index 0000000000000000000000000000000000000000..ca1f3a04ce117c17a71949576f2363b2b64ad9ae GIT binary patch literal 23256 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 Z*9E!KGGs$5aovIpYB{o>Rk&^w{|5#Dt*HP2 literal 0 HcmV?d00001 diff --git a/packages/gallery/assets/gallery_2s.glb b/packages/gallery/assets/gallery_2s.glb new file mode 100644 index 0000000000000000000000000000000000000000..ad5e2d389dfc393c41706398c4442cac57d768f9 GIT binary patch literal 21644 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 literal 0 HcmV?d00001 diff --git a/packages/gallery/assets/gallery_3.glb b/packages/gallery/assets/gallery_3.glb new file mode 100644 index 0000000000000000000000000000000000000000..c3249279d4f17a16e858d4d05f4144db2301ebba GIT binary patch literal 26332 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 Z{4dMx9q*2Rb?h^&k9&FNws-dU|6i}DJRbl6 literal 0 HcmV?d00001 diff --git a/packages/gallery/assets/gallery_4.glb b/packages/gallery/assets/gallery_4.glb new file mode 100644 index 0000000000000000000000000000000000000000..7cd9a7fc8ee03cfdc818b330e38fce5c6dc32aed GIT binary patch literal 31260 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 literal 0 HcmV?d00001 diff --git a/packages/gallery/assets/lebombo_1k.hdr b/packages/gallery/assets/lebombo_1k.hdr new file mode 100644 index 0000000000000000000000000000000000000000..3aee1937cd2dabc9ded2a7bd5a5a1bcc4ca13a7b GIT binary patch literal 1476953 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�OM zKB|&&D77q;2Ww;Ff<{yNmQ@Uq8W}=Y7gN8y&ef~fiE-pJLn2`XN~ z*RZKd-Y1ENFir*}GKmoji&^KcGQ+#;Krc9#KG`^ zsQqr=0OA8HAC&h-8`>jnsD;@i$t^o6!Qj|#`y^ho#g(gn30Rsv3zd!%AnWosW2Wo~ zRwO(w$L@d+9;t5GWC>wUlpOB)0BePu-Xv3YXM?rcnOj1X`NWXbf@#N@S z!Kp-1U^o^JM(5O6J|4m?)2KwIZt81%ExuQ)1@=#%v-R?TR3A8YaT3| zxo~lnX2q5*AyiJpYMABnF)1vAh{5x*fTGh{OoDoPys*;dM`BN#yA>7un)xrcxet*h zOxB&G7nU;d@o!qB8tRm$$P~y^G^wj@RP8~%>3(E&4J+MPmFba#$dpWJavdqCq9;0- zf!E$~EPOmpDUeg%$=FjTPMvh8(iohmF_0E`p#|$ zRl}U;#936%b7iRk)y)%cZ3RqC29K{7mj(9Lt^7bYoUYom5XN2uEUs0 zJtDT3I)eLlD_@cWUtTZnz;B~}ph-&wslpd|RWE7s0FeZST?Rf7I3!1qyG)cOivM2V z#(HDoXomC=P*wP$_nRK0e#4}nkwR0H(8!3W4*l=Z6F{_I`|hhmkAVQLX$VNuhoYJFWD_GyCJlP;>tb5 z*$={mG6Ucoth>R3-|+{(43Ylo=l}Bd;B?f|x8LE}@2_rfBF}m6;CH4E26yc@D0%Ty-ce}f%r+0hqO!u9g-Mx2acJH0to%u|6o1_4kV7qNH5;=*|Id3Td0wEy~ zIp>@dNe*P&m?VJ#V;gKR*v1&!fWiCyJ+J7VKklX83JR#I-a6-bzUTLZ!{;g?3u#a+ z0+Pr<6P2*FqF7YrPiv9R*TH*0=z3rj&m3(0xg<%eud&Ky(3AWSa{5QR9A~cS!VHK-72@Ti^ej5Aqr(Q>n*7?N1db=E%A%mh(iIU8o>;D znw#gUyMm!4kSgy;(KI~BY-p5(dfW)6jaJxxdK++@ZtL8E`OiD1aW30GEWeaHKR=Sq%5|AW3hghMa;4>LXn$*w?VkmyzS>EFYl z0?;t+@|pmYCZg9ryDr*OnbGH;-@Hkqr!Q}PNnR)ViP zLO=TOgO8w3HQE2*GO>8eA-(v%HfuEil@3aAeslBr_fIx%-+oZB%rov(niZ1JTmJ+N zBmWyEC?`S(4Sk9gL<)*mhFiz0-UjZak~=y(;~myAmnBpP&% z8yAdC8fRHve(Y1GeTqKEj4mJ_Y>eTjZ80{#1NfY?(X>e=0 zs-O7#Vp=yoiqh&Q#3r_xAURYoNmurqnv@>0vWdEoGj9ssEF>E5wIh_=Rub=9Z#{^Q z1um8*C#GatWr`*%{)7rZ8b6v!BDh%&Zl=zh5%aO>30m^p7S&U7VM`w;5duJ$Vq3&!%v){9?+gZLVL*UOmt(9pQg4Zqo z-|!P_p~UBROW@A<GoyqB?np~T8rlTM&FPMYf1&JtqstWMB);e2*`1A-1c@tO~omW zgjlETor*_96m<8)lGP%L*mBumKdAJzBtVP9{V4(MFUJ1z!Ao((tJ6*IB#KQ;JLsQg zS)Z0*>0gXUU8Gf0AMOYA@6#)%1c?(#k_saaM|$Gw0fF?C-qJ9EL7$hzqukzkJ~tU| z%;Os5by}rI*dZ|P)7|bfmXXvpifYrGWWlI$}k120X-_0B5=(5g?QL zr8LeKyE=(7OGhT<)2}q2pnKNHL4yXV{iqg_qru zBq;k4Y1;b3t&W76XQCt^wp8y7%t%jTHVQTceoRSQ&Unk-Mu?+SDU%Wnoa-*Ahq|U1 zG4@XQTm>V=m$kL{=e~{g^mp{NMO>3%PC=;K^&~1OLs^P7faevmM2=la>H>iZ&P~X=w>L1?$>s#>1XA-&e7kaLZ_qkIA*Q z22jRHA`8?n{cFKks}WGpJxuOgvV6hZS#$Ya>Bg!7(|=s3qPGYTij9b0I6qhrhZLD5 z9AtO_p&0raPxh6Fa~_zffhU~gf|kj5t7juhz@hBMf=y}Fp21O(=p0wwc5XG4%8e?@ z^xr)WMaD-knpHiA?`vx^WYKwKko?#_Q8|Bj$Ky>hO46DXk~ zZ>6rbxh(>bWzpcpE`RQH+1Gqv!JxO^_qrXJmym#;W zdv{^X@4mWu>)}HHR0a3kJb3W^1Cv9INWXUvUY1OH4;an|>nOar~g$lELNv4nsLxZUa zVua-#CWc)_B`vtZHtKqecqqRhvh!2{giKdLaeD->L84D$;lwc`M!N}V*dB}zb_YFl z+W2Bty%u(H<}@nfQ+ zi^oJ1jdx=@h*7!f7GAZZbX<~xI_e{Z^jU&ZqEt|xo^X6RFVvtJQVvK;@>3Epk$!5s zLhB(QKL&Z4E%ga3;$6_*%&bm?$XsWJlawOYhHqozr&#&p(*vlJPWhPb%F0SPIS#OM zP9oNXV#_({qR`nDbLTIh`myFotdnd5M#22Rd{tCp+LkQ#OMa)Buc?pLg4*(D`oyj( z!3>Kl_XK{*m1&-0o|&kPt|gnmx zlV&>S2GZovIook&%_FUrHl%azmj764NQj?H@Y&X<1k6;JR$fr>3x8hI&=b}DHJ2w&P|@io-Yxt7Q4BA z9m2Mwv<3}}d{pZbyhvqxSzl5)X*Ak5uX_%{W1l`{y}O2(C>gRh9LiPYMIb4cJg733 zmk~my5HmNgI5zf~a-(@cZt5dMCdMlBO0-2?~=@KhZy(EBbc~7Li~lQBKgrRK~=CQwFG(R`VA?C6i_zaS1Mb z?z#w3q=!Otj1LJ!Ze`IbzdC~fq@|3hpl)N*hK(Q(4RPWKjmK}HFOJ`uD0tlJwx?*x zsA;R68MW6<-Inzm$P(2I=88jh^_}%_+vcr%n&f=($eP`?P--2F8UgSYbZ$rL6*sVupEB;Aj}u3;Y1*Xq^S6$bpuRm)fU<^RA~x2Q8WFbL+y z&BdHL!1oYSrD#NE&6+tYn3+s0jmm=QD)O2Yj2|_;2rKDJ9#{Mf z9TcY_I0a4d95@bF_zNRbAXSkx=@>e2AbfrZ258%+Ovrx6=mX_O2czN&{vwKokHT(H zKT@%aP7)}?S>^n4mT5#{CuXPHHd16NBBE)#2#G5n5b7OTG3yDy)NaRHGN3!{`L{S&xPphV-wf+P&2M+Rhp znGwM!BB`C?ni|MbCz^wMBhk6l!Q4*zHtOiy>dNvNv#V=lZg3{9DuG9M6kAKl(^Spz z)p2wEoH+bUM4y)9%RuyMc8VLGj>FY-WL#@lv;5*Nyg>m;;6*8C0Dt5b{@jpUh{{`L zJm@U&&h;+!?zt{gWMDZv6sEDnS-D~b=WHeIaOJC549ThrPuI!VYC@osCfZspwx!MH zwX0Xrm5(YWj5JHNU4JJUl`j*WhDWPw+qq?DJz4{Ep#lF^&y{;^YsldneuCU0cXwd_ z{{542)b10<>+mjOsn_i%X$zMuUsG5yPuYByU zJO!R!kz5MI(Y!R2MG+v$6TRs^kI(~(-b@2;L4pdNOTpAFqUIOZKhwUWuqcWr0eJ3j z-1z$bclW+ij2>6(5eG?(z17^fK&%9;b#QXe>IJYdRzJmymXWRq#Rshgq0O;k)>%hGLIn~ zqDE*5tZ(emnLP@z9#q*$2CiQDsC;DFlyLXs@td8`2rO|o zNTbQP9ew4-w2}6S>KSUFW5&crr|Zjtf?>n+$Bgr%fLN}cW-yQ|k5eF53)#;cox;6> z_o$_D{3Sm&0bW%eDcwViSd|0d#<#}?>X1{zr}4TbmO$6!(33eD2eQVi?utIA+9fK~ zUO-mDeBQ@PF-_M=(HY`!rA3r1{TBr0N6rpxod&N?BmPG?tCd-mh=wh}nkZ`m3!?+= zbne{BS=HFJngk4npPxo1`}_q8QO4z6^#JX|?>r^9FrnqC$Ltj)Xrecsm zGiJD}?abu0sSL*P(eEKsI9!=1i!@OYk2n0ANpHO+bae+44$(dIXu1T;W8oH0w8KZr ze1;i*f*l@+vY&u8C6k^xcKFD<@12&8&sx-<{ijn$kDh8d&BBx@2@{{ArA2owY(z@r zL|+rJ=Q01`6oq&i)uLDtEPwOelPBDJKL%p0eu*0ZR)hQ)!FwQ<#n;gzjBtJE21{>)a20hsXasny{f&wwb+MV-D_>Esi$R9Dw*`< z*h_6lBpsj#w^h;i@9)4>5=T`&FC~?S5#??M)?2hsUu0F+C#`S)KDphHO?y+L)DeWt zLtizJeFU>Ha5Id&gRZ$~s|k5|IgZ<0B-Ds7)#a4tJ_WL7_k5u{Jx+78LxRnQVRg+d z&WYo9f?S^ypR4}~*ut=Av&nj15V?fvC<9nMu`o7996w$S|Fu0;e>$I{sP-S=`lsm* zM7LbhByPzob)=Lg{pl5*4KizAOR{qXzNV_HDc9lbTlzTSs*1rzj)Yw~znsqDBcWHv z64sARhF(D(V!$22*Vef%>ok7M#KNL*a=WR$SZ9k|xdUUF-QbkTtFnZa7p_I9V)-+r zu5xJA2}qzpF-`f{ap}TWqn2eVZV|pNC$zzaj;l3SS5s>Y2|3i&bP7D=uc>V(r>+a5 zZ%f$AiLq$>Y6#2HbLXyLcLrqI(9pP*xc#o$pze7nRw%Z4OI=evVF4cEw>8lDN?+(( zwc20ff7QCxcx@*`-Dp-1v}ogET|2kIYf^SYr8n4U?a?*%Nq^0f+^Rv3D#p0?tlECP zYzay$NM<0$z=zf!4g8wNY zfI%KCifN-!7%?5&&&aB&F`P^RB&C4P^K*a0IzcCy@y7tvjeR+ng+n!Vreb>eY(jCI zce$5Jc^Fsq^b^P?9!a7*qkI>58rolI`g;mx91_VikkWBXtFpU0!_;m)x>^MWEJEQd(E9L}&GD zGLc%fIw13uGwn7;v~+NrGZX}%z3;m9Yy;)DrK7L%>98o<4a>%H?Zjhzoo?xMTEA=S z?)p8fQe4Bo;PIF+$g6cWAL^kV`9L66^#%&I8OF-<9Xdp~A7^6)_!bPrui@5AUUe-m zP<`8c&RCY}a!^ed3ZO24v=`Z3{v+6q!gbp6D;x95$0(8P653jNfAi*N3a^vq$#zhv zt6aY%>(t$P?kg*lr_&RW`p>W5`1)JWRpRPhRL=(w?|yUl{yld;`hD;q^66qPeTOr6<`fP2W^jyi^aKXTL^ z{!hvkw1dw?-5<5s;IrcL=R>t2dl6Xq9C7ZA^^e*@#m)5PsTgKSgfmDLikso41!bvH z9SDxeutYE{#P?GmR}4D`fwcCR6f6oWVvDs2Q2oS2m~^su)r3}j#zcLeAF!?Hq^T3e zj8Kv%c1PFPgmi*CvOfAo@wkYf(nFfbQbw^v&SXsCeC}hTI`FLmHohBP zfaVGpr~tx`N(&$8i`b|H{)Zb?KDw>`qo`J0VWh{z{#+A9GL!P@11kE_URCAK>+utl zLK1hAi^w%i<_+py`Y91Gozy57%_x#x70cr2%E_CX{NHc#M8=JtmMs+n+_u_qMl&~Q{IQGuDbIqsE7B{E1 zoNGC!qdC?Rcg{6OM6CYIUjwVqDkB(dRj~iPlXQo|ObA^0!!%A6wGu9PhY{`GcE`HX z@$8uGeRddVC2qj2l2~kXBe}ZQpVO;X9<_v5T0_ymZZDRpsi~p9u`x_iqL*nVXQFkX zjuUsgpO&oy?xjgf=YkiuZ(mz8r)rI9Esj*Y1Z=2Zn@QH0&N1ZBtO4^&QFPI{4_j9+ouFV{cdnXI;$U) zfQIN^i`QPHiLXglbbs>HIz9K&%OW-r>Ht**5h~|mQS{baQWX`YtHMYJfLh!qO5{DI zf8U%Qip`gxcS`egy`zNxV|kf;4<wxDn| z$mx^ovl9(WeRit-o__4IBiuo$aoG+;jew|jmnYPX<9U_lB66JVuQ zmH1;Tev06ZVbv}h(es$A5Rcoy$1a7ynk@ot#fKN|DsP6!xf~wqV((l^6i)E|d)m}rKzsfk*K;Mqy>bJDttmFe& z85DyIcumSX-9SEo>8GtZw!Oq5X6yMXnQZynWee? z0MV+d%Gnf+Rfil3UWR6+va-0UqrTuu<(b?F2ML$rpZ-Do!wTU=%$zm2OZt3IZgXD*R&}GZj zDQv~+RV!B&ug-+$1)too?ul(|yNThxas8^5Yu3@`iLMgCwqyn(qn?$*AO@$FP__Yr znd99W_>?^DY}hO2tPhuBb#-c_U_)GGQ1wPF_^|zyNr*n>z~sCRnX{6FDzBmd|7pAw zAwfB)X4mp88Y)O-zDfO!R8_7(HeHWEFtSfS`p|v!2e?zCB#pOsQjmUckh31Vf{OIzWIh!f!p7GeVhAl0MW1c7HaC9JGXD$c3(Yq zhi#(-pS&RUsQTi@7mzV3>a*0{U!xrqsR%$Pycw1{!JnUA{rHO7Tz%|6O1uPje&{}U zp3Kq&27PJ~^B1t7w4 zN~5U)IdT-I96K2Q*1_P-h+s1~@D!}MUk(}dh;@RbGO`SD$PKj(zfo^v>;qAlnb?MK zOHyp?bm@FLFuKqtdTD8^X6lQRBp<|LE{G7yXF=Nr)Iwe;g1ZQnO`YndbPmZA3$M#W zT~Q_MX4=FeIIiuaDHBHJ6MWO5%PeHl1U!Tro2Ip{co3KbGhxHh(Gf|Y?CDYfSz=)_ z!a{}-gNBS8GrFvxoxWS}=PN%f8}$U-DT@SN8lUP9=*zK0{Q2AJ2ZLs+IDZ)Hw<;%I zO%URyiXz}+_C-yYD2tbX;Uo14*aSG03pKTnH|nEprWQ@r8#mr0JQbtcQ>dAO=f3nw zP90~^LWE@{&KH*CiH()=R=J+(XEsklO!klIzOE&d&ne`SA)Kup4cTH^> z4-5;22jc^kkxihIv~)a3nyEX|0rb=)7IeN%G(^iAcjB)Zc_#o*c#&z1da4y=%h}^c zRDIWc=Gc+2Jl!u8XmIh}cXV08I=}x!9BAk+7dQyMx1lQo* z=UJ^Pl^_JqcX(PfTSm84HzAh7oZ`;I{!pib2a!q@>*vajrC1-vIJJAJjBpL{hQ^>F zr5@o(@7dM7(+*s6`;>_H9e&RxZ%?IH4vYffTd3Zf&sUv9+99;+-%A zPKR41Ne6kuEQ&^@aG}$&yJy<<+Gn~jFue~-DQM3S6)E1T& z53ztgHY7Ga5jq)1VdQ_8$-x$lo-nzUFlC=WO$-%@I?xUAd}gie84QGtD=QUcP8VgO z<^fQAga}AfkhHG-=Hrqha>9NIa1pKmskIhlGCWqf)oCCm^rpb2+mN(z!$#=NZAoL4 z$iszd*@iW>3nlon1 z^y5a43plfYCdEx1INL!?Y>(@Z=fHOQXu3QHs)Yh>$}v@p4aYHQf`kZSSqX>%Zk(cB z?eGX=%&LbrKmUIMoawT4;n^jbH=drNJAMP~*n9^y35wA73fffXRX!xKx7DEumq1P? zzt#$C+7cKc*J0&KeZUg?+>#%|V~`lPi&<%=TG9b`Fc^VQf(zxt=) zMBrS4n>x8n39WKAtXzpqBFty$MRrT4ZEAF x*GHb)q_+u3)Q2D_MSO^Z#tcI{*I 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�u^XJhn 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

s+XA?mYceRt&$2Qe}Un@fENtWep=@JvhQLm3G5k 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

iN(uIey_Kf=rqXs%c9K6pMf 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