diff --git a/.gitignore b/.gitignore
index 9c87395..8b57165 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,6 @@
*.pytest_cache
*.vscode
*.idea
-*.DS_Store
\ No newline at end of file
+*.DS_Store
+tree.txt
+uv.lock
\ No newline at end of file
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..2a47ac7
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,38 @@
+# π **FletX Code of Conduct**
+
+## π Our Pledge
+We pledge to foster an open, inclusive, and respectful environment for all contributors, regardless of:
+- Background or experience level
+- Gender identity or expression
+- Sexual orientation
+- Disability
+- Personal appearance
+- Race, ethnicity, or religion
+- Technology preferences
+
+## π« Unacceptable Behavior
+Examples include but are not limited to:
+- Harassment or derogatory comments
+- Trolling or personal/political attacks
+- Publishing others' private information without consent
+- Other conduct that could reasonably be considered inappropriate
+
+## π Enforcement Responsibilities
+Project maintainers will:
+- Remove/edit inappropriate content
+- Warn or ban offenders temporarily/permanently
+- Apply consequences fairly and consistently
+
+## βοΈ Reporting Guidelines
+Report violations to **[project email/contact]** with:
+1. **Where/when** the incident occurred
+2. **Description** of the behavior
+3. **Context** (if available)
+4. Your **contact information** (optional)
+
+All reports will be reviewed and investigated promptly.
+
+## π Attribution
+This Code of Conduct is adapted from:
+- [Contributor Covenant 2.1](https://www.contributor-covenant.org/)
+- [Django Code of Conduct](https://www.djangoproject.com/conduct/)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a6dfc8c..717184f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,56 +1,197 @@
+# Contributing to FletX
----
-
-### π§ `CONTRIBUTING.md`
+Thank you for your interest in FletX! π This comprehensive guide outlines how to contribute effectively.
+## π Table of Contents
+1. [Getting Started](#-getting-started)
+2. [Project Structure](#-project-structure)
+3. [Development Workflow](#-development-workflow)
+4. [Code Conventions](#-code-conventions)
+5. [Testing & Quality](#-testing--quality)
+6. [Documentation](#-documentation)
+7. [Reporting Bugs](#-reporting-bugs)
+8. [Feature Proposals](#-feature-proposals)
+9. [Code of Conduct](#-code-of-conduct)
-# Contributing to EasySwitch
+## π Getting Started
-First of all, thank you for your interest in contributing to **EasySwitch!** π
-This guide outlines how to contribute effectively and maintain high-quality standards.
+### Local Setup
----
+1. **Clone the repository**
+```bash
+git clone https://github.com/AllDotPy/FletX.git
+cd FletX
+```
-## π§ Local Setup
+2. **Set up virtual environment** (Recommended: UV)
+```bash
+pip install uv
+uv venv
+source venv/bin/activate # Linux/Mac
+# or .\venv\Scripts\activate # Windows
+```
-1. **Clone the repository**
+3. **Install dependencies**
+```bash
+uv pip install -e .[dev] # Development mode
+```
+4. **Verify installation**
```bash
-git clone https://github.com/AllDotPy/easyswitch.git
+pytest tests/
+```
+
+## π Project Structure
+
+```sh
+.
+βββ CONTRIBUTING.md
+βββ LICENSE
+βββ README.md
+βββ architecture.svg
+βββ docs/
+βββ examples/
+βββ fletx
+βΒ Β βββ __init__.py
+βΒ Β βββ app.py
+βΒ Β βββ core
+βΒ Β βΒ Β βββ __init__.py
+βΒ Β βΒ Β βββ controller.py
+βΒ Β βΒ Β βββ di.py
+βΒ Β βΒ Β βββ effects.py
+βΒ Β βΒ Β βββ factory.py
+βΒ Β βΒ Β βββ navigation
+βΒ Β βΒ Β βΒ Β βββ guards.py
+βΒ Β βΒ Β βΒ Β βββ middleware.py
+βΒ Β βΒ Β βΒ Β βββ transitions.py
+βΒ Β βΒ Β βββ observer.py
+βΒ Β βΒ Β βββ page.py
+βΒ Β βΒ Β βββ route_config.py
+βΒ Β βΒ Β βββ router.py
+βΒ Β βΒ Β βββ state.py
+βΒ Β βΒ Β βββ types.py
+βΒ Β βΒ Β βββ widget.py
+βΒ Β βββ decorators
+βΒ Β βΒ Β βββ controllers.py
+βΒ Β βΒ Β βββ reactive.py
+βΒ Β βΒ Β βββ route.py
+βΒ Β βββ utils
+βΒ Β βΒ Β βββ __init__.py
+βΒ Β βΒ Β βββ context.py
+βΒ Β βΒ Β βββ exceptions.py
+βΒ Β βΒ Β βββ logger.py
+βΒ Β βββ widgets
+βΒ Β βββ __init__.py
+βΒ Β βββ text.py
+βββ main.py
+βββ pyproject.toml
+βββ setup.py
```
-2. **Create a virtual environment**
-We use [UV](https://docs.astral.sh/uv/) to manage our projects
+## π Development Workflow
+
+1. **Create a branch**
+ Branch from `master` with descriptive naming:
+ ```bash
+ git checkout -b feat/new-reactive-component
+ ```
+
+2. **Implement changes**
+ - Keep commits atomic
+ - Document new features
+
+3. **Run tests**
```bash
-# First install uv
-pip install uv
+uv pip install -e .[test]
+pytest tests/
+```
-# Navigate to the projet folder
-cd easyswitch
+4. **Submit a Pull Request**
+ - Clearly describe changes
+ - Reference related issues
+ - Address code review feedback
+
+## β¨ Code Conventions
+
+### Style Guide
+- Follow PEP 8 (88 chars max line length)
+- Type hints for all public functions
+- Google-style docstrings for key modules
+
+### Reactivity Pattern
+```python
+# Good
+class ReactiveButton(ft.ElevatedButton, FletXWidget):
+ """ My Reactive Button which.... """
+
+ def __init__(self, text: RxStr, **kwargs):
+ super().__init__(**kwargs)
+ # Create a reactive object
+ self.rx_text: RxStr = RxStr('')
+ # And bind it to self (@ft.ElevatedButton) text attribute
+ self.bind('text', self.rx_text)
+```
-# Create a virtual environment for thr project
-uv venv
+### Widget Standards
+- Prefix reactive widgets with `Reactive`
+- Isolate state logic in dedicated classes
-# Then activate it
-source venv/bin/activate
+## π§ͺ Testing & Quality
-# Now install deps
-uv pip install
+### Running Tests
+```bash
+pytest tests/ --cov=fletx --cov-report=html
+```
+
+### Quality Standards
+- Maintain >90% code coverage
+- All new widgets require:
+ - Unit tests
+ - Functional example
+ - Documentation
+
+## π Documentation
+
+### Writing Docs
+```python
+class ReactiveText(ft.Text, FletXWidget):
+ """Text widget with reactive value binding.
+
+ Args:
+ value: RxStr to bind to text value
+ color: RxStr for text color (optional)
+ """
+```
-# Install EasySwitch locally
-uv pip install -e .
+### Building Documentation
+```bash
+cd docs/
+make html
```
+## π Reporting Bugs
-## Contribution Guidelines
+1. Check existing issues for duplicates
+2. Include:
+ - Steps to reproduce
+ - Expected vs actual behavior
+ - FletX/Python versions
+ - Minimal reproducible example
-1. Make sure to follow coding best practices and maintain consistency with the existing code.
-2. Document new features or modifications in the code.
-3. Thoroughly test your modifications and ensure they do not introduce any regressions.
-4. Respect the project's code of conduct and treat other contributors with respect and courtesy.
+## π‘ Feature Proposals
-## Issues and Feature Requests
+1. Clearly describe the use case
+2. Suggest technical approach
+3. Outline potential impacts
+4. Attach mockups if applicable
-If you encounter an issue or have an idea for a new feature, feel free to open an issue in this repository. We are always open to suggestions and will do our best to address them promptly.
+## π€ Code of Conduct
+
+We adhere to the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md). By participating:
+- Be kind and open-minded
+- Respect differing viewpoints
+- Assume good faith
+
+---
-We greatly appreciate all contributions, and thank you in advance for your participation in the project!
\ No newline at end of file
+Thank you for helping build FletX! Together we're creating the best reactive framework for Flet. π
\ No newline at end of file
diff --git a/README.md b/README.md
index 1ae02be..3ee2a94 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,7 @@
-Here's a comprehensive, well-structured, and engaging technical documentation for your GitHub README:
-
----
-
# FletX π
**The GetX-inspired Python Framework for Building Reactive, Cross-Platform Apps with Flet**
-[](https://pypi.org/project/fletx/)
+[](https://pypi.org/project/Flet-X/)
[](LICENSE)
[](https://discord.gg/your-link)
@@ -177,10 +173,32 @@ FletXRouter.add_middleware(AnalyticsMiddleware())
## Roadmap πΊοΈ
-- [ ] FletX CLI tool
-- [ ] VS Code extension
+- [x] **Step 1** β **Fondation**
+ > βοΈ **Goal** : build thechnical bases and essential abstractions.
+- [x] **Step 2** β **State Management + DI**
+ > π― **Goal** : Enable reactive state management.
+- [x] **Step 3** β **Advanced navigation**
+ > π§ **Goal** : Add support for modular and nested routing, middlewares and Guards.
+- [ ] **Step 4** β **Composants UI enrichis**
+ > π§± **Goal** : Add ready to use reactive UI components (enabling extensibility).
+- [ ] **Step 5** β **Utilities & CLI**
+ > π οΈ **Goal** : Add tools to boost DX (developer experience).
+- [ ] **Step 6** β **Write Documentation**
+ > π **Goal** : Write FletX's documentation.
+
+### Currently Working on
+
+- [x] Add @reactive_control to allow converting flet Controls into a FletX reactive Widgets
+- [ ] Add Ready to use Reactive Widgets or components
+- [ ] FletX CLI tool Eg: `fletx new my_project`; `fletx generate module my_project/my_module`
+- [ ] Write Documentation
+
+### For the next version
+
+- [ ] Improve Actual routing system (enabling devs to create subrouters for modules)
+- [ ] Add Screen Management System for Page Widgets
- [ ] Enhanced dev tools
-- [ ] Plugin system
+- [ ] VS Code extension
---
diff --git a/examples/1/assets/fonts/bungee.ttf b/examples/1/assets/fonts/bungee.ttf
new file mode 100644
index 0000000..fa64510
Binary files /dev/null and b/examples/1/assets/fonts/bungee.ttf differ
diff --git a/examples/1/assets/fonts/inter.ttf b/examples/1/assets/fonts/inter.ttf
new file mode 100644
index 0000000..e31b51e
Binary files /dev/null and b/examples/1/assets/fonts/inter.ttf differ
diff --git a/examples/1/assets/icons/apple.svg b/examples/1/assets/icons/apple.svg
new file mode 100644
index 0000000..b586428
--- /dev/null
+++ b/examples/1/assets/icons/apple.svg
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/examples/1/assets/icons/facebook.svg b/examples/1/assets/icons/facebook.svg
new file mode 100644
index 0000000..9e21545
--- /dev/null
+++ b/examples/1/assets/icons/facebook.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/examples/1/assets/icons/google.svg b/examples/1/assets/icons/google.svg
new file mode 100644
index 0000000..3ffa2aa
--- /dev/null
+++ b/examples/1/assets/icons/google.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/examples/1/assets/images/dev1.jpg b/examples/1/assets/images/dev1.jpg
new file mode 100644
index 0000000..398014d
Binary files /dev/null and b/examples/1/assets/images/dev1.jpg differ
diff --git a/examples/1/assets/logos/ln_bg_alpha_3000.png b/examples/1/assets/logos/ln_bg_alpha_3000.png
new file mode 100644
index 0000000..adcad96
Binary files /dev/null and b/examples/1/assets/logos/ln_bg_alpha_3000.png differ
diff --git a/examples/1/assets/logos/ln_grad.svg b/examples/1/assets/logos/ln_grad.svg
new file mode 100644
index 0000000..3398a1f
--- /dev/null
+++ b/examples/1/assets/logos/ln_grad.svg
@@ -0,0 +1,145 @@
+
+
+
+
diff --git a/examples/1/assets/logos/ln_tx_bg_alpha_3000.png b/examples/1/assets/logos/ln_tx_bg_alpha_3000.png
new file mode 100644
index 0000000..3a46f63
Binary files /dev/null and b/examples/1/assets/logos/ln_tx_bg_alpha_3000.png differ
diff --git a/examples/main.py b/examples/1/main.py
similarity index 83%
rename from examples/main.py
rename to examples/1/main.py
index a4e18ae..20553e8 100644
--- a/examples/main.py
+++ b/examples/1/main.py
@@ -11,8 +11,9 @@ def main(page: ft.Page):
color_scheme_seed = ft.Colors.GREEN
)
page.dark_theme = ft.Theme(
- color_scheme_seed = ft.Colors.TEAL,
- scaffold_bgcolor = ft.Colors.BLACK
+ color_scheme_seed = ft.Colors.BLUE_800,
+ scaffold_bgcolor = ft.Colors.BLACK,
+ font_family = 'Bebas Neue, sans-serif',
)
page.theme_mode = ft.ThemeMode.DARK
diff --git a/examples/models/user.py b/examples/1/models/user.py
similarity index 100%
rename from examples/models/user.py
rename to examples/1/models/user.py
diff --git a/examples/pages/auth/controller.py b/examples/1/pages/auth/controller.py
similarity index 91%
rename from examples/pages/auth/controller.py
rename to examples/1/pages/auth/controller.py
index 19118cc..f48f60b 100644
--- a/examples/pages/auth/controller.py
+++ b/examples/1/pages/auth/controller.py
@@ -10,7 +10,7 @@ def __init__(self):
def login(self, email: str, password: str, on_success: callable, on_failure: callable):
# Simulation d'authentification
- if email == "admin@demo.com" and password == "admin":
+ if email == "a" and password == "a":
self.current_user.value = email
self.is_authenticated.value = True
on_success()
diff --git a/examples/pages/auth/guards.py b/examples/1/pages/auth/guards.py
similarity index 100%
rename from examples/pages/auth/guards.py
rename to examples/1/pages/auth/guards.py
diff --git a/examples/1/pages/auth/login.py b/examples/1/pages/auth/login.py
new file mode 100644
index 0000000..d887ccd
--- /dev/null
+++ b/examples/1/pages/auth/login.py
@@ -0,0 +1,323 @@
+from flet import *
+from ..shared.components import ReactivePasswordField, ReactiveTextFieldProps
+from fletx import FletX
+from fletx.core.page import FletXPage
+from fletx.core.router import FletXRouter
+from fletx.core.state import RxBool
+from fletx.decorators.reactive import computed
+from .controller import AuthController
+from .guards import AuthGuard
+
+class LoginPage(FletXPage):
+ default_radius = 30
+ hide_password: RxBool = RxBool(True)
+
+
+ def build(self):
+ # Récupère le contrôleur
+ self.controller = FletX.find(AuthController) or AuthController()
+ FletX.put(self.controller)
+
+ # Email or phone number field
+ self.email_field = TextField(
+ label = "email or phone number",
+ height = 55,
+ fill_color = Colors.GREY_900,
+ bgcolor = Colors.with_opacity(
+ color = Colors.GREY_900,
+ opacity = .6
+ ),
+ content_padding = padding.symmetric(horizontal = 30),
+ border_radius = self.default_radius,
+ border = InputBorder.NONE,
+ adaptive = True,
+ filled = True,
+ value = '',
+ text_style = TextStyle(
+ size = 14,
+ weight = FontWeight.W_400
+ ),
+ label_style = TextStyle(
+ size = 14,
+ weight = FontWeight.W_400,
+ color = Colors.GREY_500
+ ),
+ prefix = Container(
+ margin = margin.only(left = 20),
+ ),
+ suffix = Container(
+ margin = margin.only(right = 20),
+ ),
+ )
+
+ # Passaord Field
+ self.password_field = ReactivePasswordField(
+ label = "Password",
+ hint_text = "Enter your password",
+ height = 55,
+ fill_color = Colors.GREY_900,
+ bgcolor = Colors.with_opacity(
+ color = Colors.GREY_900,
+ opacity = .6
+ ),
+ content_padding = padding.symmetric(horizontal = 30),
+ suffix = Container(
+ on_click = lambda e: self.hide_password.toggle(),
+ margin = margin.only(right = 20),
+ # Content
+ content = Icon(
+ Icons.PASSWORD_OUTLINED,
+ color = Colors.GREY_500,
+ size = 20
+ )
+ ),
+ prefix = Container(
+ margin = margin.only(left = 20),
+ ),
+ border_radius = self.default_radius,
+ border = InputBorder.NONE,
+ adaptive = True,
+ filled = True,
+ password = True,
+ value = '',
+ text_style = TextStyle(
+ size = 14,
+ weight = FontWeight.W_400
+ ),
+ label_style = TextStyle(
+ size = 14,
+ weight = FontWeight.W_400,
+ color = Colors.GREY_500
+ ),
+ is_password = self.hide_password
+ )
+
+ return SafeArea(
+ expand = True,
+ content = Container(
+ expand = True,
+ padding = padding.symmetric(horizontal = 12),
+
+ # Content
+ content = Column(
+ expand = True,
+ alignment = MainAxisAlignment.SPACE_BETWEEN,
+ horizontal_alignment = CrossAxisAlignment.CENTER,
+ controls = [
+ Column(
+ expand = True,
+ # width = 350,
+ spacing = 20,
+ alignment = MainAxisAlignment.START,
+ horizontal_alignment = CrossAxisAlignment.CENTER,
+
+ controls = [
+ Container(
+ height = 35,
+ ),
+ Column(
+ spacing = 5,
+ alignment = MainAxisAlignment.CENTER,
+ horizontal_alignment = CrossAxisAlignment.CENTER,
+ controls = [
+ Image(
+ src = 'logos'
+ '/ln_grad.svg',
+ fit = ImageFit.CONTAIN,
+ width = 90,
+ height = 90
+ ),
+ # SPACER
+ Container(
+ height = 10
+ ),
+ # Welcome Text
+ Text(
+ value = "Welcome Back To Learnia",
+ style = TextStyle(
+ size = 22,
+ weight = FontWeight.W_600
+ )
+ ),
+ Text(
+ value = "Welcome Back To Learnia",
+ style = TextStyle(
+ size = 14,
+ weight = FontWeight.W_400
+ )
+ ),
+ ]
+ ),
+
+ Container(
+ height = 0
+ ),
+
+ # Email or phone number field
+ self.email_field,
+
+ # Password Field
+ self.password_field,
+
+ # BUTTON
+ GestureDetector(
+ on_tap = self.on_login,
+ mouse_cursor = MouseCursor.CLICK,
+ # Content
+ content = Container(
+ # width = self.width,
+ height = 55,
+ border_radius = self.default_radius,
+ bgcolor = Colors.BLUE_800,
+
+ content = Row(
+ alignment = MainAxisAlignment.CENTER,
+ vertical_alignment = CrossAxisAlignment.CENTER,
+ controls = [
+ Text(
+ 'Login',
+ text_align = TextAlign.CENTER,
+ style = TextStyle(
+ size = 16,
+ weight = FontWeight.W_600,
+ color = Colors.WHITE
+ )
+ ),
+ ],
+ )
+ ),
+ ),
+
+ # SEPARATOR
+ Row(
+ expand = False,
+ alignment = MainAxisAlignment.CENTER,
+
+ # Contents
+ controls = [
+ Container(
+ width = 100,
+ height = 1,
+ bgcolor = Colors.GREY_800
+ ),
+ Text(
+ value = "or continue with",
+ style = TextStyle(
+ size = 12,
+ weight = FontWeight.W_400,
+ color = Colors.GREY_500
+ ),
+ text_align = TextAlign.CENTER
+ ),
+ Container(
+ width = 100,
+ height = 1,
+ bgcolor = Colors.GREY_800
+ )
+ ]
+ ),
+ # TextButton(
+ # "AccΓ©der sans compte (demo)",
+ # on_click=lambda e: FletXRouter.to("/dashboard")
+ # ),
+
+ # Spacer
+ Container(
+ height = 15
+ ),
+
+ # Social auth buttons
+ Container(
+ expand = False,
+ padding = padding.all(8),
+ width = 200,
+ border_radius = self.default_radius,
+ bgcolor = Colors.with_opacity(
+ color = Colors.GREY_900,
+ opacity = .6
+ ),
+
+ # Content
+ content = Row(
+ alignment = MainAxisAlignment.SPACE_EVENLY,
+ vertical_alignment = CrossAxisAlignment.CENTER,
+ controls = [
+ # Google Button
+ Container(
+ height = 45,
+ width = 45,
+ bgcolor = Colors.BLACK,
+ border_radius = self.default_radius,
+ padding = padding.all(10),
+
+ content = Image(
+ src = 'icons/google.svg',
+ fit = ImageFit.COVER,
+ # width = 10,
+ # height = 10
+ )
+ ),
+
+ # Facebook Button
+ Container(
+ height = 45,
+ width = 45,
+ bgcolor = Colors.BLACK,
+ border_radius = self.default_radius,
+ padding = padding.all(10),
+
+ content = Image(
+ src = 'icons/apple.svg',
+ fit = ImageFit.COVER,
+ # width = 10,
+ # height = 10
+ )
+ ),
+
+ # Apple Button
+ Container(
+ height = 45,
+ width = 45,
+ bgcolor = Colors.BLACK,
+ border_radius = self.default_radius,
+ padding = padding.all(10),
+
+ content = Image(
+ src = 'icons/facebook.svg',
+ fit = ImageFit.COVER,
+ # width = 10,
+ # height = 10
+ )
+ )
+ ]
+ )
+ ),
+ ],
+ ),
+
+ # Terms and Conditions text
+ Text(
+ value = "By continuing, you agree to our Terms of Service and Privacy Policy.",
+ style = TextStyle(
+ size = 12,
+ weight = FontWeight.W_400,
+ color = Colors.GREY_500
+ ),
+ text_align = TextAlign.CENTER
+ )
+ ],
+ )
+ )
+ )
+ def on_login(self, e):
+ # Validation basique
+ if not self.email_field.value or not self.password_field.value:
+ return
+
+ # Appel au contrΓ΄leur
+ self.controller.login(
+ self.email_field.value,
+ self.password_field.value,
+ on_success=lambda: FletXRouter.to("/dashboard"),
+ on_failure=lambda: print("Γchec de connexion")
+ )
\ No newline at end of file
diff --git a/examples/1/pages/dashboard/controller.py b/examples/1/pages/dashboard/controller.py
new file mode 100644
index 0000000..1b58198
--- /dev/null
+++ b/examples/1/pages/dashboard/controller.py
@@ -0,0 +1,91 @@
+from fletx.core.controller import FletXController
+from fletx.core.state import RxStr, RxList
+from fletx.decorators.reactive import computed
+from fletx.core.effects import useEffect
+from models.user import User
+
+class DashboardController(FletXController):
+ def __init__(self):
+ super().__init__()
+ self.username = RxStr("InvitΓ©")
+ self.todos = RxList([])
+ self._is_initialized = False
+
+ # Effet auto-nettoyant
+ self.add_effect(
+ lambda: print("DashboardController prΓͺt"),
+ []
+ )
+
+ # @property
+ @computed
+ def todo_count(self) -> int:
+ return len(self.todos.value)
+
+ # @property
+ @computed
+ def welcome_message(self) -> str:
+ return f"Bienvenue, {self.username.value}"
+
+ def initialize(self):
+ """MΓ©thode sΓ©parΓ©e pour l'initialisation"""
+ if not self._is_initialized:
+ self.load_data()
+ self._is_initialized = True
+
+ def load_data(self):
+ # Simulation chargement async
+ import asyncio
+ async def load():
+ await asyncio.sleep(1)
+ self.username.value = "Admin"
+ self.todos.value = [
+ {
+ 'task_id': '1',
+ 'task_name': 'Ajouter @fletx.widgets.reactive_control',
+ },
+ {
+ 'task_id': '2',
+ 'task_name': 'CrΓ©er un exemple de Projet avec FletX',
+ },
+ {
+ 'task_id': '3',
+ 'task_name': 'Γcrire la documentation',
+ },
+ {
+ 'task_id': '4',
+ 'task_name': 'Tester l\'application',
+ },
+ {
+ 'task_id': '5',
+ 'task_name': 'DΓ©ployer sur GitHub',
+ },
+ {
+ 'task_id': '6',
+ 'task_name': 'Faire une vidΓ©o de prΓ©sentation',
+ },
+ {
+ 'task_id': '7',
+ 'task_name': 'Partager sur les rΓ©seaux sociaux',
+ },
+ {
+ 'task_id': '8',
+ 'task_name': 'RΓ©pondre aux questions des utilisateurs',
+ },
+ {
+ 'task_id': '9',
+ 'task_name': 'PrΓ©parer la prochaine version',
+ },
+ {
+ 'task_id': '10',
+ 'task_name': 'Organiser une session de feedback',
+ }
+ ]
+
+ asyncio.run(load())
+
+ def logout(self):
+ from fletx import FletX
+ auth = FletX.find('AuthController')
+ if auth:
+ auth.logout()
\ No newline at end of file
diff --git a/examples/1/pages/dashboard/home.py b/examples/1/pages/dashboard/home.py
new file mode 100644
index 0000000..79099c1
--- /dev/null
+++ b/examples/1/pages/dashboard/home.py
@@ -0,0 +1,262 @@
+from flet import *
+from fletx import FletX
+from fletx.core.page import FletXPage
+from fletx.core.router import FletXRouter
+from fletx.decorators.controllers import page_controller
+from .controller import DashboardController
+from ..shared.components import (
+ TaskComponent
+)
+
+# @page_controller # Injection automatique du contrΓ΄leur
+class DashboardHomePage(FletXPage):
+ def __init__(self):
+ super().__init__()
+ self.controller = FletX.find(DashboardController) or DashboardController()
+
+ def _safe_refresh(self, e):
+ """MΓ©thode sΓ©curisΓ©e sans risque de rΓ©cursion"""
+ if not hasattr(self, '_refreshing'):
+ self._refreshing = True
+ self.controller.load_data()
+ del self._refreshing
+
+ def on_logout(self, e):
+ self.controller.logout()
+ FletXRouter.to("/login", replace=True)
+
+ def did_mount(self):
+ # Charge les donnΓ©es quand la page est montΓ©e
+ self.controller.load_data()
+
+ def build(self):
+ # Initialisation sΓ©curisΓ©e
+ if not hasattr(self, '_built'): # Protection contre les appels multiples
+ self.controller.initialize()
+ self._built = True
+
+ return SafeArea(
+ expand = True,
+ minimum_padding = padding.symmetric(vertical=12),
+
+ content = Column(
+ expand = True,
+ alignment = MainAxisAlignment.START,
+ scroll = ScrollMode.AUTO,
+ spacing = 20,
+
+ controls = [
+ Container(
+ height = 0
+ ),
+ Container(
+ padding = padding.symmetric(horizontal=8, vertical=4),
+ content = Column(
+ expand = True,
+ controls = [
+ # Header with User Avatar and Logout Button
+ Row(
+ alignment = MainAxisAlignment.SPACE_BETWEEN,
+ controls = [
+ # Content with IconButton
+ IconButton(
+ icon = Icons.MENU_OUTLINED,
+ bgcolor = Colors.BLACK45,
+ icon_color = Colors.WHITE,
+ on_click = self.on_logout
+
+ # style
+
+ ),
+
+ # User Avatar
+ CircleAvatar(
+ foreground_image_src = 'images/dev1.jpg',
+ radius = 24,
+ ),
+ ]
+ ),
+
+ # Divider
+ Container(
+ height = 10
+ ),
+
+ # Welcome TEXT
+ Text(
+ f"What are you doing today {self.controller.username}?",
+ style = TextStyle(
+ size = 20,
+ weight = FontWeight.W_400
+ )
+ ),
+
+ # Search Bar
+ TextField(
+ hint_text = "Search...",
+ prefix_icon = Icons.SEARCH,
+ border = InputBorder.NONE,
+ filled = True,
+ # fill_color = Colors.GREY_900,
+ bgcolor = Colors.with_opacity(
+ color = Colors.GREY_900,
+ opacity = .5
+ ),
+ border_radius = BorderRadius(
+ top_left = 8,
+ top_right = 8,
+ bottom_left = 8,
+ bottom_right = 8
+ ),
+ focused_border_color = Colors.TRANSPARENT,
+ hover_color = Colors.with_opacity(
+ color = Colors.GREY_900,
+ opacity = .55
+ ),
+ content_padding = padding.symmetric(horizontal=16, vertical=8),
+ on_submit = self._safe_refresh
+ ),
+ ]
+ ),
+ ),
+
+ # Categories
+ Column(
+ expand = True,
+ spacing = 2,
+ controls = [
+ # Categories Header
+ Container(
+ padding = padding.symmetric(horizontal=8, vertical=4),
+ content = Row(
+ alignment = MainAxisAlignment.SPACE_BETWEEN,
+ controls = [
+ Text(
+ "CATEGORIES",
+ style = TextStyle(
+ size = 14,
+ weight = FontWeight.W_400,
+ color = Colors.GREY_500
+ )
+ ),
+ ElevatedButton(
+ text = "See all",
+ on_click = lambda e: FletXRouter.to("/categories")
+ )
+ ]
+ )
+ ),
+
+ # Categories List
+ Container(
+ expand = True,
+ padding = padding.symmetric(horizontal=0, vertical=4),
+ height = 110,
+ content = ListView(
+ expand = True,
+ auto_scroll = True,
+ horizontal = True,
+ spacing = 20,
+ controls = [
+ Container(
+ width = 170,
+ height = 110,
+ bgcolor = Colors.with_opacity(
+ color = Colors.GREY_900,
+ opacity = .5
+ ),
+ clip_behavior = ClipBehavior.NONE,
+ padding = padding.all(10),
+ border_radius = 20,
+ content = Column(
+ expand = True,
+ alignment = MainAxisAlignment.CENTER,
+ spacing = 10,
+ controls = [
+ Text(
+ f"{i * 10} Tasks",
+ style = TextStyle(
+ size = 12,
+ weight = FontWeight.W_400,
+ color = Colors.GREY_500
+ )
+ ),
+ Text(
+ f"Category {i + 1}",
+ style = TextStyle(
+ size = 16,
+ weight = FontWeight.W_500,
+ color = Colors.WHITE
+ )
+ ),
+ # Progress Bar
+ ProgressBar (
+ value = i / 5, # Simulated progress
+ # stroke_width = 4,
+ color = Colors.BLUE_800 if i % 2 == 0 else Colors.PINK_600,
+ )
+ ]
+ )
+ ) for i in range(5)
+ ]
+ )
+ ),
+
+ # Divider
+ Container(
+ height = 5
+ ),
+
+ # Tasks Section
+ Container(
+ padding = padding.symmetric(horizontal=8, vertical=4),
+ content = Row(
+ alignment = MainAxisAlignment.SPACE_BETWEEN,
+ controls = [
+ Text(
+ "TASKS",
+ style = TextStyle(
+ size = 14,
+ weight = FontWeight.W_400,
+ color = Colors.GREY_500
+ )
+ ),
+ ElevatedButton(
+ text = "See all",
+ on_click = lambda e: FletXRouter.to("/tasks")
+ )
+ ]
+ )
+ ),
+
+ # Tasks List
+ Container(
+ expand = True,
+ padding = padding.symmetric(horizontal=0, vertical=4),
+ # height = 200,
+ content = ListView(
+ expand = True,
+ auto_scroll = True,
+ spacing = 10,
+ controls = [
+ TaskComponent(
+ index = idx + 1,
+ task_id = task.get(
+ 'task_id', f'task-{idx + 1}'
+ ),
+ task_name = task.get(
+ 'task_name', f"Task {idx + 1}"
+ ) )
+ for idx, task in enumerate(self.controller.todos)
+ ]
+ )
+ )
+ ]
+ ),
+ ]
+ )
+ )
+
+ return ProgressRing() # Fallback UI
+
+
\ No newline at end of file
diff --git a/examples/pages/dashboard/settings.py b/examples/1/pages/dashboard/settings.py
similarity index 100%
rename from examples/pages/dashboard/settings.py
rename to examples/1/pages/dashboard/settings.py
diff --git a/examples/1/pages/shared/components.py b/examples/1/pages/shared/components.py
new file mode 100644
index 0000000..883764d
--- /dev/null
+++ b/examples/1/pages/shared/components.py
@@ -0,0 +1,117 @@
+from typing import Optional, List
+from flet import *
+from dataclasses import dataclass, field
+
+from fletx.core.state import RxBool, RxStr
+from fletx.core.widget import FletXWidget
+from fletx.widgets import reactive_control
+
+# class AppHeader(FletXWidget):
+# """En-tΓͺte rΓ©utilisable"""
+
+# def __init__(self, title: str):
+# super().__init__(title=title)
+
+# def build(self) -> Control:
+# return Row(
+# controls=[
+# Text(self.get_prop('title'), size=20, weight="bold"),
+# IconButton(Icons.SETTINGS, on_click=lambda e: FletXRouter.to("/settings"))
+# ],
+# alignment="spaceBetween"
+# )
+
+@dataclass
+class ReactiveTextFieldProps:
+ can_reveal_password: RxBool = field(default_factory=lambda: RxBool(False))
+ value: RxStr = field(default_factory=lambda: RxStr(""))
+ label: RxStr = field(default_factory=lambda: RxStr(""))
+ hint_text: RxStr = field(default_factory=lambda: RxStr(""))
+ password: RxBool = field(default_factory=lambda: RxBool())
+
+
+# Reactive Password Field
+class ReactivePasswordField(TextField, FletXWidget):
+ def __init__(
+ self,
+ is_password: RxBool = RxBool(),
+ **kwargs
+ ):
+ super().__init__(**kwargs)
+ FletXWidget.__init__(self, **kwargs)
+
+ self.is_password = is_password
+ # print("ReactivePasswordField initialized with reactives:", type(reactives.password))
+ self.bind('password', self.is_password)
+ # self.bind('label', reactives.label)
+ # self.bind('hint_text', reactives.hint_text)
+ # self.bind('can_reveal_password', reactives.can_reveal_password)
+
+
+@reactive_control(
+ bindings = {
+ '_is_done':'is_completed'
+ }
+)
+class TaskComponent(Container):
+ """
+ Reactive CheckBox widget that integrates with FletX's reactivity system.
+ """
+
+ is_completed: RxBool
+
+ def __init__(self, index: int, task_id: str, task_name: str, **kwargs):
+ super().__init__(**kwargs)
+ self._task_name: str = task_name
+ self._task_id: str = task_id
+ self.index: int = index
+
+ # Reactive state for task completion
+ self.is_completed: RxBool = RxBool(False)
+ self._is_done = False
+
+ self.padding = padding.symmetric(horizontal = 15, vertical = 10)
+ self.bgcolor = Colors.GREY_900
+ self.border_radius = 15
+ self.height = 60
+
+ # Events
+ self.on_click = self._handle_click
+
+ # content
+ self.content = self.build()
+
+ def build(self) -> Row:
+ return Row(
+ expand = False,
+ spacing = 15,
+ alignment = MainAxisAlignment.START,
+ vertical_alignment = CrossAxisAlignment.CENTER,
+
+ # Controls for the task component
+ controls = [
+ # Icon for the task
+ Icon(
+ Icons.CIRCLE_OUTLINED if not self._is_done else Icons.CHECK_CIRCLE,
+ size = 24,
+ color = Colors.GREY_400 if self._is_done else (Colors.BLUE if not self.index % 2 == 0 else Colors.PINK_600),
+ ),
+
+ # Text for the task name
+ Text(
+ self._task_name,
+ size = 16,
+ weight = FontWeight.NORMAL,
+ color = Colors.WHITE if not self._is_done else Colors.GREY_400,
+ style = TextStyle(
+ decoration = TextDecoration.LINE_THROUGH if self._is_done else TextDecoration.NONE
+ )
+ ),
+ ]
+ )
+
+ def _handle_click(self, e):
+ """Gère le clic pour basculer l'état de complétion"""
+ self.is_completed.toggle()
+ # Update UI or perform other actions based on completion state
+ print(f"Task {self._task_id} completed: {self._is_done}")
diff --git a/examples/routes.py b/examples/1/routes.py
similarity index 100%
rename from examples/routes.py
rename to examples/1/routes.py
diff --git a/examples/pages/auth/login.py b/examples/pages/auth/login.py
deleted file mode 100644
index 7d584b4..0000000
--- a/examples/pages/auth/login.py
+++ /dev/null
@@ -1,244 +0,0 @@
-from flet import *
-from ..shared.components import ReactivePasswordField, ReactiveTextFieldProps
-from fletx import FletX
-from fletx.core.page import FletXPage
-from fletx.core.router import FletXRouter
-from fletx.core.state import RxBool
-from fletx.decorators.reactive import computed
-from .controller import AuthController
-from .guards import AuthGuard
-
-class LoginPage(FletXPage):
- default_radius = 30
- can_show_password = RxBool(False)
-
-
- def build(self):
- # Récupère le contrôleur
- self.controller = FletX.find(AuthController) or AuthController()
- FletX.put(self.controller)
-
- # ΓlΓ©ments UI
- self.email_field = TextField(
- label = "email or phone number",
- height = 55,
- fill_color = Colors.GREY_900,
- bgcolor = Colors.with_opacity(
- color = Colors.GREY_900,
- opacity = .6
- ),
- content_padding = padding.symmetric(horizontal = 30),
- border_radius = self.default_radius,
- border = InputBorder.NONE,
- adaptive = True,
- filled = True,
- value = '',
- text_style = TextStyle(
- size = 14,
- weight = FontWeight.W_400
- ),
- label_style = TextStyle(
- size = 14,
- weight = FontWeight.W_400,
- color = Colors.GREY_500
- )
- )
- self.password_field = ReactivePasswordField(
- reactives = ReactivePasswordField(
- can_reveal_password = self.can_show_password,
- # value = '',
- # label = 'Password',
- # hint_text = 'Enter your password',
- password = self.can_show_password
- ),
- label = "Password",
- height = 55,
- fill_color = Colors.GREY_900,
- bgcolor = Colors.with_opacity(
- color = Colors.GREY_900,
- opacity = .6
- ),
- content_padding = padding.symmetric(horizontal = 30),
- suffix = Container(
- on_click = lambda e: self.can_show_password.toggle(),
- # Content
- content = Icon(
- Icons.PASSWORD_OUTLINED,
- color = Colors.GREY_500,
- size = 20
- )
- ),
- border_radius = self.default_radius,
- border = InputBorder.NONE,
- adaptive = True,
- filled = True,
- password = True,
- value = '',
- text_style = TextStyle(
- size = 14,
- weight = FontWeight.W_400
- ),
- label_style = TextStyle(
- size = 14,
- weight = FontWeight.W_400,
- color = Colors.GREY_500
- )
- )
-
- return Container(
- expand = True,
- padding = padding.symmetric(horizontal = 12),
-
- # Content
- content = Column(
- expand = True,
- alignment = MainAxisAlignment.SPACE_BETWEEN,
- horizontal_alignment = CrossAxisAlignment.CENTER,
- controls = [
- Column(
- expand = True,
- # width = 350,
- spacing = 20,
- alignment = MainAxisAlignment.CENTER,
- horizontal_alignment = CrossAxisAlignment.CENTER,
-
- controls = [
- # Container(
- # height = 10
- # ),
- Column(
- spacing = 5,
- alignment = MainAxisAlignment.CENTER,
- horizontal_alignment = CrossAxisAlignment.CENTER,
- controls = [
- Text(
- value = "Welcome Back To Learnia",
- style = TextStyle(
- size = 22,
- weight = FontWeight.W_600
- )
- ),
- Text(
- value = "Welcome Back To Learnia",
- style = TextStyle(
- size = 14,
- weight = FontWeight.W_400
- )
- ),
- ]
- ),
-
- Container(
- height = 10
- ),
-
- # Email or phone number field
- self.email_field,
-
- # Password Field
- self.password_field,
-
- # BUTTON
- GestureDetector(
- on_tap = self.on_login,
- mouse_cursor = MouseCursor.CLICK,
- # Content
- content = Container(
- # width = self.width,
- height = 55,
- border_radius = self.default_radius,
- bgcolor = Colors.TEAL,
-
- content = Row(
- alignment = MainAxisAlignment.CENTER,
- vertical_alignment = CrossAxisAlignment.CENTER,
- controls = [
- Text(
- 'Login',
- text_align = TextAlign.CENTER,
- style = TextStyle(
- size = 16,
- weight = FontWeight.W_600,
- color = Colors.WHITE
- )
- ),
- ],
- )
- ),
- ),
-
- TextButton(
- "AccΓ©der sans compte (demo)",
- on_click=lambda e: FletXRouter.to("/dashboard")
- ),
-
- # Social auth buttons
- Container(
- expand = False,
- padding = padding.all(8),
- border_radius = 15,
- bgcolor = Colors.with_opacity(
- color = Colors.GREY_900,
- opacity = .6
- ),
-
- # Content
- content = Row(
- alignment = MainAxisAlignment.SPACE_EVENLY,
- vertical_alignment = CrossAxisAlignment.CENTER,
- controls = [
- # Google Button
- Container(
- height = 45,
- width = 45,
- bgcolor = Colors.BLACK,
- border_radius = 8
- ),
-
- # Facebook Button
- Container(
- height = 45,
- width = 45,
- bgcolor = Colors.BLACK,
- border_radius = 8
- ),
-
- # Apple Button
- Container(
- height = 45,
- width = 45,
- bgcolor = Colors.BLACK,
- border_radius = 8
- )
- ]
- )
- ),
- ],
- ),
-
- # Terms and Conditions text
- Text(
- value = "By continuing, you agree to our Terms of Service and Privacy Policy.",
- style = TextStyle(
- size = 12,
- weight = FontWeight.W_400,
- color = Colors.GREY_500
- ),
- text_align = TextAlign.CENTER
- )
- ],
- )
- )
-
- def on_login(self, e):
- # Validation basique
- if not self.email_field.value or not self.password_field.value:
- return
-
- # Appel au contrΓ΄leur
- self.controller.login(
- self.email_field.value,
- self.password_field.value,
- on_success=lambda: FletXRouter.to("/dashboard"),
- on_failure=lambda: print("Γchec de connexion")
- )
\ No newline at end of file
diff --git a/examples/pages/dashboard/controller.py b/examples/pages/dashboard/controller.py
deleted file mode 100644
index 3f0b578..0000000
--- a/examples/pages/dashboard/controller.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from fletx.core.controller import FletXController
-from fletx.core.state import RxStr, RxList
-from fletx.decorators.reactive import computed
-from fletx.core.effects import useEffect
-from models.user import User
-
-class DashboardController(FletXController):
- def __init__(self):
- super().__init__()
- self.username = RxStr("InvitΓ©")
- self.todos = RxList([])
- self._is_initialized = False
-
- # Effet auto-nettoyant
- self.add_effect(
- lambda: print("DashboardController prΓͺt"),
- []
- )
-
- # @property
- @computed
- def todo_count(self) -> int:
- return len(self.todos.value)
-
- # @property
- @computed
- def welcome_message(self) -> str:
- return f"Bienvenue, {self.username.value}"
-
- def initialize(self):
- """MΓ©thode sΓ©parΓ©e pour l'initialisation"""
- if not self._is_initialized:
- self.load_data()
- self._is_initialized = True
-
- def load_data(self):
- # Simulation chargement async
- import asyncio
- async def load():
- await asyncio.sleep(1)
- self.username.value = "Admin"
- self.todos.value = ["TΓ’che 1", "TΓ’che 2"]
-
- asyncio.run(load())
-
- def logout(self):
- from fletx import FletX
- auth = FletX.find('AuthController')
- if auth:
- auth.logout()
\ No newline at end of file
diff --git a/examples/pages/dashboard/home.py b/examples/pages/dashboard/home.py
deleted file mode 100644
index 8a6f8eb..0000000
--- a/examples/pages/dashboard/home.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import flet as ft
-from fletx import FletX
-from fletx.core.page import FletXPage
-from fletx.core.router import FletXRouter
-from fletx.decorators.controllers import page_controller
-from .controller import DashboardController
-
-# @page_controller # Injection automatique du contrΓ΄leur
-class DashboardHomePage(FletXPage):
- def __init__(self):
- super().__init__()
- self.controller = FletX.find(DashboardController) or DashboardController()
-
- def build(self):
- # Initialisation sΓ©curisΓ©e
- if not hasattr(self, '_built'): # Protection contre les appels multiples
- self.controller.initialize()
- self._built = True
-
- return ft.Column(
- controls=[
- ft.Text(self.controller.welcome_message, size=24),
- ft.ElevatedButton(
- "Actualiser",
- on_click=self._safe_refresh # MΓ©thode sΓ©curisΓ©e
- )
- ],
- expand=True,
- alignment="center"
- )
- return ft.ProgressRing() # Fallback UI
-
- def _safe_refresh(self, e):
- """MΓ©thode sΓ©curisΓ©e sans risque de rΓ©cursion"""
- if not hasattr(self, '_refreshing'):
- self._refreshing = True
- self.controller.load_data()
- del self._refreshing
-
- def on_logout(self, e):
- self.controller.logout()
- FletXRouter.to("/login", replace=True)
-
- def did_mount(self):
- # Charge les donnΓ©es quand la page est montΓ©e
- self.controller.load_data()
\ No newline at end of file
diff --git a/examples/pages/shared/components.py b/examples/pages/shared/components.py
deleted file mode 100644
index 6e1b173..0000000
--- a/examples/pages/shared/components.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from typing import Optional
-from flet import *
-from dataclasses import dataclass
-
-from fletx.core.state import RxBool, RxStr
-from fletx.core.widget import FletXWidget
-from fletx.core.router import FletXRouter
-
-# class AppHeader(FletXWidget):
-# """En-tΓͺte rΓ©utilisable"""
-
-# def __init__(self, title: str):
-# super().__init__(title=title)
-
-# def build(self) -> Control:
-# return Row(
-# controls=[
-# Text(self.get_prop('title'), size=20, weight="bold"),
-# IconButton(Icons.SETTINGS, on_click=lambda e: FletXRouter.to("/settings"))
-# ],
-# alignment="spaceBetween"
-# )
-
-@dataclass
-class ReactiveTextFieldProps:
- can_reveal_password: RxBool = RxBool(False)
- value: RxStr = RxStr("")
- label: RxStr = RxStr("")
- hint_text: RxStr = RxStr("")
- password: RxBool = RxBool(False)
-
-class ReactivePasswordField(TextField, FletXWidget):
- def __init__(
- self,
- reactives: ReactiveTextFieldProps = ReactiveTextFieldProps(),
- **kwargs
- ):
- super().__init__(**kwargs)
- FletXWidget.__init__(self, **kwargs)
- print("ReactivePasswordField initialized with reactives:", type(reactives.password))
- self.bind('password', reactives.password)
- # self.bind('label', reactives.label)
- # self.bind('hint_text', reactives.hint_text)
- # self.bind('can_reveal_password', reactives.can_reveal_password)
-
-
\ No newline at end of file
diff --git a/fletx/app.py b/fletx/app.py
index 6f207c2..e89f82a 100644
--- a/fletx/app.py
+++ b/fletx/app.py
@@ -64,7 +64,6 @@ def _main(self, page: ft.Page):
# Configuration de la page
page.theme_mode = self.theme_mode
page.title = "FletX App"
- # page.
# Register all widgets
# FletXWidgetRegistry.register_all(page)
diff --git a/fletx/core/widget.py b/fletx/core/widget.py
index 0ae0dab..fa86cdd 100644
--- a/fletx/core/widget.py
+++ b/fletx/core/widget.py
@@ -10,26 +10,13 @@
import flet as ft
from abc import ABC, abstractmethod
from typing import Union, List, Optional, Any, Dict
-from fletx.core.state import Reactive
+from fletx.core.state import (
+ Reactive, RxBool, RxInt, RxList, RxDict
+)
from fletx.utils import get_logger
from fletx.core.factory import FletXWidgetRegistry
from fletx.utils.context import AppContext
-# from flet_core.control import Control as ft_Control
-
-
-class FletXWidgetMeta(type(ft.Control)):
- """MΓ©taclasse pour l'enregistrement automatique"""
- def __new__(cls, name, bases, dct):
- # CrΓ©e la classe
- new_class = super().__new__(cls, name, bases, dct)
-
- # Enregistre auprès de Flet si c'est un widget concret
- if 'build' in dct and not getattr(new_class, '_abstract', False):
- # ft.Control.(new_class)
- pass
- return new_class
-
####
## FLETX WIDGET CLASS
@@ -50,8 +37,8 @@ def __init__(self, **kwargs):
# self.content = self.build()
# Automatic registration for cleanup
- # if AppContext.get_data("page"):
- # AppContext.get_data("page").add(self)
+ if AppContext.get_page():
+ self.page = AppContext.get_page()
def __init_subclass__(cls, **kwargs):
"""Automatically register widget classes with FletXWidgetRegistry"""
@@ -87,13 +74,17 @@ def will_unmount(self):
self._dispose_reactives()
self._is_mounted = False
- def bind(self, prop_name: str, reactive_obj: Reactive):
+ def bind(
+ self,
+ prop_name: str,
+ reactive_obj: Union[Reactive, RxBool, RxInt, RxList, RxDict]
+ ):
"""
Binds a widget property to a reactive object
Usage: self.bind("text", rx_text)
"""
- print(f"Binding {prop_name} to {reactive_obj}")
- if not isinstance(reactive_obj, Reactive):
+
+ if not isinstance(reactive_obj, (Reactive, RxBool, RxInt, RxList, RxDict)):
self.logger.error(
f"Attempted to bind {prop_name} to a non-reactive object: {reactive_obj}"
)
@@ -106,6 +97,10 @@ def bind(self, prop_name: str, reactive_obj: Reactive):
self._reactives[prop_name] = reactive_obj
setattr(self, prop_name, reactive_obj.value)
+ self.logger.debug(
+ f"bound {prop_name} to the reactive object: {reactive_obj}"
+ )
+
def _create_update_callback(self, prop_name: str):
"""Generates a safe update callback"""
@@ -118,23 +113,39 @@ def callback():
# Optionally, you could raise an exception or log an error
# raise RuntimeError(f"{self.__class__.__name__} is not mounted")
# or return to prevent further processing
- return
+ # return
new_value = self._reactives[prop_name].value
setattr(self, prop_name, new_value)
# Special handling for Control properties
if hasattr(self, "content") and isinstance(self.content, ft.Control):
- setattr(self.content, prop_name, new_value)
+ if hasattr(self.content, prop_name):
+ # Update the property on the content control
+ self.logger.debug(
+ f"Updating {self.__class__.__name__}.content.{prop_name} to {new_value}"
+ )
+ setattr(self.content, prop_name, new_value)
+
+ if hasattr(self,'build'):
+ # If the widget has a build method, call it to update the UI
+ self.logger.debug(
+ f"Rebuilding {self.__class__.__name__} after updating {prop_name}"
+ )
+ self.content = self.build()
+
+ # Special for handling for List[ft.Control] properties
+ elif hasattr(self, "controls") and isinstance(self.controls, list):
+ if hasattr(self, 'build'):
+ # If the widget has a build method, call it to update the UI
+ self.logger.debug(
+ f"Rebuilding {self.__class__.__name__} after updating {prop_name}"
+ )
+ self.controls = self.build()
self.update()
return callback
- # def _build_add_commands(self, *args, **kwargs) -> None:
- # """Internal method to add commands to the widget."""
-
- # return self.build()._build_add_commands(*args, **kwargs)
-
def _dispose_reactives(self):
"""Cleanup all reactive bindings"""
diff --git a/fletx/utils/context.py b/fletx/utils/context.py
index d382cfd..bc1433e 100644
--- a/fletx/utils/context.py
+++ b/fletx/utils/context.py
@@ -40,7 +40,7 @@ def initialize(cls, page: ft.Page, debug: bool = False):
@classmethod
def get_page(cls) -> Optional[ft.Page]:
"""Retrieves the current Flet page"""
- return cls._page.add
+ return cls._page
@classmethod
def set_data(cls, key: str, value: Any):
diff --git a/fletx/widgets/__init__.py b/fletx/widgets/__init__.py
index bdea823..8ab8a35 100644
--- a/fletx/widgets/__init__.py
+++ b/fletx/widgets/__init__.py
@@ -1,61 +1,103 @@
+import flet as ft
from functools import wraps
-from typing import get_type_hints
+from typing import (
+ get_type_hints, Dict
+)
+
from fletx.core.state import (
Reactive, RxInt, RxStr, RxBool, RxList, RxDict
)
+from fletx.core.widget import FletXWidget
-def reactive_control(cls):
- """
- DΓ©corateur qui transforme un contrΓ΄le Flet en widget rΓ©actif
- avec liaison automatique des propriΓ©tΓ©s Rx.
+
+def reactive_control(bindings: Dict[str, str]):
"""
- class ReactiveControl(cls):
- def __init__(self, **kwargs):
- # SΓ©paration des props rΓ©actives et normales
- reactive_props = {}
- normal_props = {}
-
- for k, v in kwargs.items():
- if isinstance(v, (Reactive, RxInt, RxStr, RxBool, RxList, RxDict)):
- reactive_props[k] = v
- else:
- normal_props[k] = v
-
- # Initialisation du widget parent
- super().__init__(**normal_props)
-
- # Liaison automatique des propriΓ©tΓ©s rΓ©actives
- self._reactive_bindings = {}
- for prop_name, rx_obj in reactive_props.items():
- self._bind_reactive(prop_name, rx_obj)
+ Decorator that creates a reactive control while preserving the original inheritance chain.
+ This decorator grafts reactive capabilities onto existing control classes.
+ Modifies the class in-place by:
+ 1. Adding FletXWidget as a parent class
+ 2. Injecting reactive initialization
+ 3. Preserving all original functionality
+
+ Args:
+ bindings: Dictionary mapping widget properties to reactive attribute names
+ Example: {'value': 'rx_value', 'color': 'rx_color'}
+ Returns: A Reactive Version of the ControlClass
+
+ Usage:
+ ```python
+ @reactive_control(bindings={'value': 'rx_value',})
+ class MyReactiveCheckbox(ft.Checkbox):
- def _bind_reactive(self, prop_name: str, rx_obj: Reactive):
- """CrΓ©e une liaison bidirectionnelle"""
- # Initialisation de la valeur
- setattr(self, prop_name, rx_obj.value)
-
- # Mise Γ jour du widget quand Rx change
- def update_widget(value):
- setattr(self, prop_name, value)
- if hasattr(self, 'update'):
- self.update()
-
- cleanup = rx_obj.listen(update_widget)
- self._reactive_bindings[prop_name] = cleanup
-
- # Mise Γ jour de Rx quand le widget change (si Γ©vΓ©nement disponible)
- widget_event = f"on_{prop_name}_change"
- if hasattr(self, widget_event):
- def handle_change(e):
- rx_obj.value = getattr(self, prop_name)
- setattr(self, widget_event, handle_change)
+ # Defining the reactive properties
+ self.rx_value: RxBool = RxBool(False) # Reactive property for checkbox value
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ ```
+ """
+
+ # Validate bindings
+ if not isinstance(bindings, dict):
+ raise TypeError(
+ f"Bindings must be a dictionary, got {type(bindings).__name__}"
+ )
+
+ def decorator(ControlClass):
+
+ # Store original init
+ original_init = ControlClass.__init__
+
+ # Add FletXWidget as a parent while preserving existing parents
+ ControlClass.__bases__ = (*ControlClass.__bases__, FletXWidget)
+
+ @wraps(original_init)
+ def __init__(self, *args, **kwargs):
+ # Separate reactive props from normal kwargs
+
+ # Process checks
+ for prop, rx_name in bindings.items():
+ # if not hasattr(ControlClass, prop):
+ # raise AttributeError(
+ # f"{ControlClass.__name__} does not have property '{prop}'"
+ # "You must define it in your reactive control class."
+ # )
+
+ # ControlCall must define the reactive properties specified in bindings
+ # if not hasattr(ControlClass(), rx_name) :
+ # raise ValueError(
+ # f"Reactive property '{rx_name}' must be provided in kwargs."
+ # )
+
+ if not get_type_hints(ControlClass).get(rx_name, None) in (
+ Reactive, RxInt, RxStr, RxBool, RxList, RxDict
+ ):
+ raise TypeError(
+ f"Property '{rx_name}' in {ControlClass.__name__} must be a reactive type."
+ )
+
+ # _rx_store = {
+ # rx_name: kwargs.pop(rx_name)
+ # for rx_name in bindings.values()
+ # if rx_name in kwargs
+ # }
+
+ # Call original initialization
+ original_init(self, *args, **kwargs)
+
+ # Initialize FletXWidget
+ FletXWidget.__init__(self)
+
+ # Setup reactive bindings
+ for widget_prop, rx_name in bindings.items():
+ # if rx_name in _rx_store:
+ # If the reactive attribute is provided, bind it
+ self.bind(widget_prop, getattr(self, rx_name)) # Inherited from FletXWidget
+
- def dispose(self):
- """Nettoyage des liaisons rΓ©actives"""
- for cleanup in self._reactive_bindings.values():
- cleanup()
- self._reactive_bindings.clear()
- if hasattr(super(), 'dispose'):
- super().dispose()
+ # Inject new methods
+ ControlClass.__init__ = __init__
+
+ return ControlClass
- return ReactiveControl
\ No newline at end of file
+ return decorator
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index 4a31801..f53e54e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,8 +1,9 @@
[project]
-name = "fletx"
+name = "FletX"
version = "0.1.0"
-description = "Add your description here"
+description = "The GetX-inspired Python Framework for Building Reactive, Cross-Platform Apps with Flet"
readme = "README.md"
+authors = [{ name = "#Einswilli", email = "einswilligoeh@email.com" }]
requires-python = ">=3.12"
dependencies = [
"flet-core>=0.24.1",
diff --git a/setup.py b/setup.py
index 13d8a1f..971ab42 100755
--- a/setup.py
+++ b/setup.py
@@ -6,20 +6,21 @@
setup(
name = 'FletX',
- version = '1.0.0',
+ version = '0.1.0',
packages = find_packages(),
install_requires = [
'httpx',
- 'simplejson',
'colorlog',
- 'flet>=0.3.0',
+ 'flet-core>=0.24.1',
+ 'flet[all]>=0.28.3',
'pydantic>=2.11.5',
+ 'logging>=0.4.9.6',
'typing-extensions',
],
long_description=long_description,
long_description_content_type="text/markdown",
author = '#Einswilli',
author_email = 'einswilligoeh@email.com',
- description = 'SwitchPay Python SDK for AllDotPy internal use. ',
- url = 'https://github.com/AllDotPy/iSwitch.git',
+ description = 'The GetX-inspired Python Framework for Building Reactive, Cross-Platform Apps with Flet',
+ url = 'https://github.com/AllDotPy/FletX.git',
)
\ No newline at end of file
diff --git a/uv.lock b/uv.lock
deleted file mode 100644
index 3aa7f22..0000000
--- a/uv.lock
+++ /dev/null
@@ -1,854 +0,0 @@
-version = 1
-revision = 2
-requires-python = ">=3.12"
-
-[[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.9.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/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" },
-]
-
-[[package]]
-name = "arrow"
-version = "1.3.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "python-dateutil" },
- { name = "types-python-dateutil" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/2e/00/0f6e8fcdb23ea632c866620cc872729ff43ed91d284c866b515c6342b173/arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85", size = 131960, upload-time = "2023-09-30T22:11:18.25Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/f8/ed/e97229a566617f2ae958a6b13e7cc0f585470eac730a73e9e82c32a3cdd2/arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80", size = 66419, upload-time = "2023-09-30T22:11:16.072Z" },
-]
-
-[[package]]
-name = "binaryornot"
-version = "0.4.4"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "chardet" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/a7/fe/7ebfec74d49f97fc55cd38240c7a7d08134002b1e14be8c3897c0dd5e49b/binaryornot-0.4.4.tar.gz", hash = "sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061", size = 371054, upload-time = "2017-08-03T15:55:25.08Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/24/7e/f7b6f453e6481d1e233540262ccbfcf89adcd43606f44a028d7f5fae5eb2/binaryornot-0.4.4-py2.py3-none-any.whl", hash = "sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4", size = 9006, upload-time = "2017-08-03T15:55:31.23Z" },
-]
-
-[[package]]
-name = "certifi"
-version = "2025.4.26"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/e8/9e/c05b3920a3b7d20d3d3310465f50348e5b3694f4f88c6daf736eef3024c4/certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6", size = 160705, upload-time = "2025-04-26T02:12:29.51Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" },
-]
-
-[[package]]
-name = "chardet"
-version = "5.2.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618, upload-time = "2023-08-01T19:23:02.662Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385, upload-time = "2023-08-01T19:23:00.661Z" },
-]
-
-[[package]]
-name = "charset-normalizer"
-version = "3.4.2"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936, upload-time = "2025-05-02T08:32:33.712Z" },
- { url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790, upload-time = "2025-05-02T08:32:35.768Z" },
- { url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924, upload-time = "2025-05-02T08:32:37.284Z" },
- { url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626, upload-time = "2025-05-02T08:32:38.803Z" },
- { url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567, upload-time = "2025-05-02T08:32:40.251Z" },
- { url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957, upload-time = "2025-05-02T08:32:41.705Z" },
- { url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408, upload-time = "2025-05-02T08:32:43.709Z" },
- { url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399, upload-time = "2025-05-02T08:32:46.197Z" },
- { url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815, upload-time = "2025-05-02T08:32:48.105Z" },
- { url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537, upload-time = "2025-05-02T08:32:49.719Z" },
- { url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565, upload-time = "2025-05-02T08:32:51.404Z" },
- { url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357, upload-time = "2025-05-02T08:32:53.079Z" },
- { url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776, upload-time = "2025-05-02T08:32:54.573Z" },
- { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" },
- { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" },
- { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" },
- { url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" },
- { url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" },
- { url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" },
- { url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" },
- { url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" },
- { url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" },
- { url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" },
- { url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" },
- { url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" },
- { url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" },
- { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" },
-]
-
-[[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 = "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 = "cookiecutter"
-version = "2.6.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "arrow" },
- { name = "binaryornot" },
- { name = "click" },
- { name = "jinja2" },
- { name = "python-slugify" },
- { name = "pyyaml" },
- { name = "requests" },
- { name = "rich" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/52/17/9f2cd228eb949a91915acd38d3eecdc9d8893dde353b603f0db7e9f6be55/cookiecutter-2.6.0.tar.gz", hash = "sha256:db21f8169ea4f4fdc2408d48ca44859349de2647fbe494a9d6c3edfc0542c21c", size = 158767, upload-time = "2024-02-21T18:02:41.949Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/b6/d9/0137658a353168ffa9d0fc14b812d3834772040858ddd1cb6eeaf09f7a44/cookiecutter-2.6.0-py3-none-any.whl", hash = "sha256:a54a8e37995e4ed963b3e82831072d1ad4b005af736bb17b99c2cbd9d41b6e2d", size = 39177, upload-time = "2024-02-21T18:02:39.569Z" },
-]
-
-[[package]]
-name = "fastapi"
-version = "0.115.12"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "pydantic" },
- { name = "starlette" },
- { name = "typing-extensions" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/f4/55/ae499352d82338331ca1e28c7f4a63bfd09479b16395dce38cf50a39e2c2/fastapi-0.115.12.tar.gz", hash = "sha256:1e2c2a2646905f9e83d32f04a3f86aff4a286669c6c950ca95b5fd68c2602681", size = 295236, upload-time = "2025-03-23T22:55:43.822Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/50/b3/b51f09c2ba432a576fe63758bddc81f78f0c6309d9e5c10d194313bf021e/fastapi-0.115.12-py3-none-any.whl", hash = "sha256:e94613d6c05e27be7ffebdd6ea5f388112e5e430c8f7d6494a9d1d88d43e814d", size = 95164, upload-time = "2025-03-23T22:55:42.101Z" },
-]
-
-[[package]]
-name = "flet"
-version = "0.28.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "httpx", marker = "platform_system != 'Pyodide'" },
- { name = "oauthlib", marker = "platform_system != 'Pyodide'" },
- { name = "repath" },
-]
-wheels = [
- { url = "https://files.pythonhosted.org/packages/2f/d0/9ba4ee34972e9e0cf54b1f7d17c695491632421f81301993f2aec8d12105/flet-0.28.3-py3-none-any.whl", hash = "sha256:649bfc4af7933956ecf44963df6c0d997bff9ceeaf89d3c86d96803840cab83e", size = 463000, upload-time = "2025-05-20T19:44:58.651Z" },
-]
-
-[package.optional-dependencies]
-all = [
- { name = "flet-cli" },
- { name = "flet-desktop", marker = "sys_platform == 'darwin' or sys_platform == 'win32'" },
- { name = "flet-desktop-light", marker = "sys_platform == 'linux'" },
- { name = "flet-web" },
-]
-
-[[package]]
-name = "flet-cli"
-version = "0.28.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "cookiecutter" },
- { name = "flet" },
- { name = "packaging" },
- { name = "qrcode" },
- { name = "toml" },
- { name = "watchdog" },
-]
-wheels = [
- { url = "https://files.pythonhosted.org/packages/22/33/9398add46c07a8247a28dc05fd96e26d12d07c7153126ce67ed42a6439bb/flet_cli-0.28.3-py3-none-any.whl", hash = "sha256:2759e4526472a32a584836cf926a9c3ba8fe6e363b4305454a759668d4fcad70", size = 44149, upload-time = "2025-05-20T19:44:57.336Z" },
-]
-
-[[package]]
-name = "flet-core"
-version = "0.24.1"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "repath" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/b5/cf/7b5a5a4e59814415270bda0b3c45e7c8be5e31037197a9cac3aa3e2af14a/flet_core-0.24.1.tar.gz", hash = "sha256:1137109aec43b78a911f460a56e0e4581b4c411ba53e5c68fe785502e7e89498", size = 288332, upload-time = "2024-09-03T20:46:35.279Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/a4/fd/17c690b9d8a437797f6bcec813e423711bfbacabab1f6a4aa28aed303fd1/flet_core-0.24.1-py3-none-any.whl", hash = "sha256:0c729a6a5f914b54ce90d727594d896b975ad1ef749c7076b6775ad4684ea4ed", size = 412157, upload-time = "2024-09-03T20:46:03.44Z" },
-]
-
-[[package]]
-name = "flet-desktop"
-version = "0.28.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "flet" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/a3/0e/f797d3052de953fa42b804b6ff170ad5c7708fc2959ffcce9d2a49a4b56c/flet_desktop-0.28.3.tar.gz", hash = "sha256:3e5db7b152de8cd3935e98eb39c162bf5c66f595d30c006f28d48d60e77a463d", size = 39876159, upload-time = "2025-05-20T19:39:28.548Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/2b/e6/280350788df36041b825a1e2ceeb2a60672f208164f3f2ff75c2cc16f1c8/flet_desktop-0.28.3-py3-none-macosx_10_14_x86_64.whl", hash = "sha256:6763b8e14863b0ee93e310720efa02202acae6d6ce8ff783663380f350f4f382", size = 47048073, upload-time = "2025-05-20T19:42:36.252Z" },
- { url = "https://files.pythonhosted.org/packages/34/e0/7a1486d8f71bca34ae928f5f8833d19ec0bda5ad5975e8db9e0543ae577b/flet_desktop-0.28.3-py3-none-macosx_12_0_arm64.whl", hash = "sha256:89797a387e743808733f308c7faa1158ab768966180c0fc4207f3e95d3b25db3", size = 47048072, upload-time = "2025-05-20T19:42:41.787Z" },
- { url = "https://files.pythonhosted.org/packages/c9/5f/85e74518b6ef0cebc6f7b1dfc63b523df821602745cf3a31a9607be18cf5/flet_desktop-0.28.3-py3-none-win32.whl", hash = "sha256:dc24f57ba725b974b4795b46e35f2b5348c4843f5117e9fc18b25c4abfa5caf4", size = 40265313, upload-time = "2025-05-20T19:39:19.761Z" },
- { url = "https://files.pythonhosted.org/packages/b1/d0/c953ee675f2751f14329e23dbf538bb703c64ca1ad1c88e244ca17fe459e/flet_desktop-0.28.3-py3-none-win_amd64.whl", hash = "sha256:35db313302fd4c376ba9be4d43f953a5c67d1ba99180dc6afee702699ed14749", size = 40265319, upload-time = "2025-05-20T19:39:24.527Z" },
-]
-
-[[package]]
-name = "flet-desktop-light"
-version = "0.28.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "flet" },
-]
-wheels = [
- { url = "https://files.pythonhosted.org/packages/f1/a9/3eb542246b49c40d39ba667c53f1f1f0c40f87b6b96d5542f29e2ae98eb3/flet_desktop_light-0.28.3-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:af6e53224bedd5c287c54ec3021ef3879abbba1265261a01e80badc3fbaddb86", size = 14978766, upload-time = "2025-05-20T19:31:54.681Z" },
- { url = "https://files.pythonhosted.org/packages/c6/06/a21078e117408519e4ea27f18d3826cf067d069d92e684a683261da1ab54/flet_desktop_light-0.28.3-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f3dc473aae8d6cf4270e59bbb51e819068c343a49a8836cced2d17fb0359a7f5", size = 15579831, upload-time = "2025-05-20T19:32:11.698Z" },
- { url = "https://files.pythonhosted.org/packages/c0/83/195152cc264b37426c8595418d52d51a30ef55d55db9e1c3c22818c01e47/flet_desktop_light-0.28.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d45647d68ce0aaf5418c938e8e02f404bbb8814ece504f7242730520c3697c47", size = 14978756, upload-time = "2025-05-20T19:31:57.01Z" },
- { url = "https://files.pythonhosted.org/packages/07/03/6b44479989b55994c14a88c41b1bdc0635ee19509453d301b7caaff8e1af/flet_desktop_light-0.28.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3090ca7c07392c76bd47ef29f79744c7d114edda466be5f675abc5f65f1f5be7", size = 15579821, upload-time = "2025-05-20T19:32:13.836Z" },
-]
-
-[[package]]
-name = "flet-web"
-version = "0.28.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "fastapi" },
- { name = "flet" },
- { name = "uvicorn", extra = ["standard"] },
-]
-wheels = [
- { url = "https://files.pythonhosted.org/packages/65/8a/01f73ae7123090b2974f0c5ba70d7d9fc463f47f6e12daeca59fdc40e1a9/flet_web-0.28.3-py3-none-any.whl", hash = "sha256:919c13f374e7cee539d29a8ccd6decb739528ef257c88e60af4df1ebab045bfb", size = 3137744, upload-time = "2025-05-20T19:27:32.443Z" },
-]
-
-[[package]]
-name = "fletx"
-version = "0.1.0"
-source = { virtual = "." }
-dependencies = [
- { name = "flet", extra = ["all"] },
- { name = "flet-core" },
- { name = "httpx" },
- { name = "logging" },
- { name = "pydantic" },
- { name = "setuptools" },
-]
-
-[package.metadata]
-requires-dist = [
- { name = "flet", extras = ["all"], specifier = ">=0.28.3" },
- { name = "flet-core", specifier = ">=0.24.1" },
- { name = "httpx", specifier = ">=0.28.1" },
- { name = "logging", specifier = ">=0.4.9.6" },
- { name = "pydantic", specifier = ">=2.11.5" },
- { name = "setuptools", specifier = ">=80.8.0" },
-]
-
-[[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 = "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 = "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 = "logging"
-version = "0.4.9.6"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/93/4b/979db9e44be09f71e85c9c8cfc42f258adfb7d93ce01deed2788b2948919/logging-0.4.9.6.tar.gz", hash = "sha256:26f6b50773f085042d301085bd1bf5d9f3735704db9f37c1ce6d8b85c38f2417", size = 96029, upload-time = "2013-06-04T23:43:22.086Z" }
-
-[[package]]
-name = "markdown-it-py"
-version = "3.0.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "mdurl" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" },
-]
-
-[[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 = "mdurl"
-version = "0.1.2"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
-]
-
-[[package]]
-name = "oauthlib"
-version = "3.2.2"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/6d/fa/fbf4001037904031639e6bfbfc02badfc7e12f137a8afa254df6c4c8a670/oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918", size = 177352, upload-time = "2022-10-17T20:04:27.471Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/7e/80/cab10959dc1faead58dc8384a781dfbf93cb4d33d50988f7a69f1b7c9bbe/oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", size = 151688, upload-time = "2022-10-17T20:04:24.037Z" },
-]
-
-[[package]]
-name = "packaging"
-version = "25.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
-]
-
-[[package]]
-name = "pydantic"
-version = "2.11.5"
-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/f0/86/8ce9040065e8f924d642c58e4a344e33163a07f6b57f836d0d734e0ad3fb/pydantic-2.11.5.tar.gz", hash = "sha256:7f853db3d0ce78ce8bbb148c401c2cdd6431b3473c0cdff2755c7690952a7b7a", size = 787102, upload-time = "2025-05-22T21:18:08.761Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/b5/69/831ed22b38ff9b4b64b66569f0e5b7b97cf3638346eb95a2147fdb49ad5f/pydantic-2.11.5-py3-none-any.whl", hash = "sha256:f9c26ba06f9747749ca1e5c94d6a85cb84254577553c8785576fd38fa64dc0f7", size = 444229, upload-time = "2025-05-22T21:18:06.329Z" },
-]
-
-[[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.1"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" },
-]
-
-[[package]]
-name = "pypng"
-version = "0.20220715.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/93/cd/112f092ec27cca83e0516de0a3368dbd9128c187fb6b52aaaa7cde39c96d/pypng-0.20220715.0.tar.gz", hash = "sha256:739c433ba96f078315de54c0db975aee537cbc3e1d0ae4ed9aab0ca1e427e2c1", size = 128992, upload-time = "2022-07-15T14:11:05.301Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/3e/b9/3766cc361d93edb2ce81e2e1f87dd98f314d7d513877a342d31b30741680/pypng-0.20220715.0-py3-none-any.whl", hash = "sha256:4a43e969b8f5aaafb2a415536c1a8ec7e341cd6a3f957fd5b5f32a4cfeed902c", size = 58057, upload-time = "2022-07-15T14:11:03.713Z" },
-]
-
-[[package]]
-name = "python-dateutil"
-version = "2.9.0.post0"
-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, 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.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920, upload-time = "2025-03-25T10:14:56.835Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256, upload-time = "2025-03-25T10:14:55.034Z" },
-]
-
-[[package]]
-name = "python-slugify"
-version = "8.0.4"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "text-unidecode" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/87/c7/5e1547c44e31da50a460df93af11a535ace568ef89d7a811069ead340c4a/python-slugify-8.0.4.tar.gz", hash = "sha256:59202371d1d05b54a9e7720c5e038f928f45daaffe41dd10822f3907b937c856", size = 10921, upload-time = "2024-02-08T18:32:45.488Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/a4/62/02da182e544a51a5c3ccf4b03ab79df279f9c60c5e82d5e8bec7ca26ac11/python_slugify-8.0.4-py2.py3-none-any.whl", hash = "sha256:276540b79961052b66b7d116620b36518847f52d5fd9e3a70164fc8c50faa6b8", size = 10051, upload-time = "2024-02-08T18:32:43.911Z" },
-]
-
-[[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 = "qrcode"
-version = "7.4.2"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "colorama", marker = "sys_platform == 'win32'" },
- { name = "pypng" },
- { name = "typing-extensions" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/30/35/ad6d4c5a547fe9a5baf85a9edbafff93fc6394b014fab30595877305fa59/qrcode-7.4.2.tar.gz", hash = "sha256:9dd969454827e127dbd93696b20747239e6d540e082937c90f14ac95b30f5845", size = 535974, upload-time = "2023-02-05T22:11:46.548Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/24/79/aaf0c1c7214f2632badb2771d770b1500d3d7cbdf2590ae62e721ec50584/qrcode-7.4.2-py3-none-any.whl", hash = "sha256:581dca7a029bcb2deef5d01068e39093e80ef00b4a61098a2182eac59d01643a", size = 46197, upload-time = "2023-02-05T22:11:43.4Z" },
-]
-
-[[package]]
-name = "repath"
-version = "0.9.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "six" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/65/e1/824989291d0f01886074fdf9504ba54598f5665bc4dd373b589b87e76608/repath-0.9.0.tar.gz", hash = "sha256:8292139bac6a0e43fd9d70605d4e8daeb25d46672e484ed31a24c7ce0aef0fb7", size = 5492, upload-time = "2019-10-08T00:25:22.3Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/87/ed/92e9b8a3ffc562f21df14ef2538f54e911df29730e1f0d79130a4edc86e7/repath-0.9.0-py3-none-any.whl", hash = "sha256:ee079d6c91faeb843274d22d8f786094ee01316ecfe293a1eb6546312bb6a318", size = 4738, upload-time = "2019-10-08T00:25:20.842Z" },
-]
-
-[[package]]
-name = "requests"
-version = "2.32.3"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "certifi" },
- { name = "charset-normalizer" },
- { name = "idna" },
- { name = "urllib3" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218, upload-time = "2024-05-29T15:37:49.536Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928, upload-time = "2024-05-29T15:37:47.027Z" },
-]
-
-[[package]]
-name = "rich"
-version = "14.0.0"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "markdown-it-py" },
- { name = "pygments" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/a1/53/830aa4c3066a8ab0ae9a9955976fb770fe9c6102117c8ec4ab3ea62d89e8/rich-14.0.0.tar.gz", hash = "sha256:82f1bc23a6a21ebca4ae0c45af9bdbc492ed20231dcb63f297d6d1021a9d5725", size = 224078, upload-time = "2025-03-30T14:15:14.23Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/0d/9b/63f4c7ebc259242c89b3acafdb37b41d1185c07ff0011164674e9076b491/rich-14.0.0-py3-none-any.whl", hash = "sha256:1c9491e1951aac09caffd42f448ee3d04e58923ffe14993f6e83068dc395d7e0", size = 243229, upload-time = "2025-03-30T14:15:12.283Z" },
-]
-
-[[package]]
-name = "setuptools"
-version = "80.8.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/8d/d2/ec1acaaff45caed5c2dedb33b67055ba9d4e96b091094df90762e60135fe/setuptools-80.8.0.tar.gz", hash = "sha256:49f7af965996f26d43c8ae34539c8d99c5042fbff34302ea151eaa9c207cd257", size = 1319720, upload-time = "2025-05-20T14:02:53.503Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/58/29/93c53c098d301132196c3238c312825324740851d77a8500a2462c0fd888/setuptools-80.8.0-py3-none-any.whl", hash = "sha256:95a60484590d24103af13b686121328cc2736bee85de8936383111e421b9edc0", size = 1201470, upload-time = "2025-05-20T14:02:51.348Z" },
-]
-
-[[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, 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, 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, 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.46.2"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "anyio" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/ce/20/08dfcd9c983f6a6f4a1000d934b9e6d626cff8d2eeb77a89a68eef20a2b7/starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5", size = 2580846, upload-time = "2025-04-13T13:56:17.942Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037, upload-time = "2025-04-13T13:56:16.21Z" },
-]
-
-[[package]]
-name = "text-unidecode"
-version = "1.3"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/ab/e2/e9a00f0ccb71718418230718b3d900e71a5d16e701a3dae079a21e9cd8f8/text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93", size = 76885, upload-time = "2019-08-30T21:36:45.405Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/a6/a5/c0b6468d3824fe3fde30dbb5e1f687b291608f9473681bbf7dabbf5a87d7/text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", size = 78154, upload-time = "2019-08-30T21:37:03.543Z" },
-]
-
-[[package]]
-name = "toml"
-version = "0.10.2"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253, upload-time = "2020-11-01T01:40:22.204Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" },
-]
-
-[[package]]
-name = "types-python-dateutil"
-version = "2.9.0.20250516"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/ef/88/d65ed807393285204ab6e2801e5d11fbbea811adcaa979a2ed3b67a5ef41/types_python_dateutil-2.9.0.20250516.tar.gz", hash = "sha256:13e80d6c9c47df23ad773d54b2826bd52dbbb41be87c3f339381c1700ad21ee5", size = 13943, upload-time = "2025-05-16T03:06:58.385Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/c5/3f/b0e8db149896005adc938a1e7f371d6d7e9eca4053a29b108978ed15e0c2/types_python_dateutil-2.9.0.20250516-py3-none-any.whl", hash = "sha256:2b2b3f57f9c6a61fba26a9c0ffb9ea5681c9b83e69cd897c6b5f668d9c0cab93", size = 14356, upload-time = "2025-05-16T03:06:57.249Z" },
-]
-
-[[package]]
-name = "typing-extensions"
-version = "4.13.2"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" },
-]
-
-[[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 = "urllib3"
-version = "2.4.0"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/8a/78/16493d9c386d8e60e442a35feac5e00f0913c0f4b7c217c11e8ec2ff53e0/urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466", size = 390672, upload-time = "2025-04-10T15:23:39.232Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813", size = 128680, upload-time = "2025-04-10T15:23:37.377Z" },
-]
-
-[[package]]
-name = "uvicorn"
-version = "0.34.2"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "click" },
- { name = "h11" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/a6/ae/9bbb19b9e1c450cf9ecaef06463e40234d98d95bf572fab11b4f19ae5ded/uvicorn-0.34.2.tar.gz", hash = "sha256:0e929828f6186353a80b58ea719861d2629d766293b6d19baf086ba31d4f3328", size = 76815, upload-time = "2025-04-19T06:02:50.101Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/b1/4b/4cef6ce21a2aaca9d852a6e84ef4f135d99fcd74fa75105e2fc0c8308acd/uvicorn-0.34.2-py3-none-any.whl", hash = "sha256:deb49af569084536d269fe0a6d67e3754f104cf03aba7c11c40f01aadf33c403", size = 62483, upload-time = "2025-04-19T06:02:48.42Z" },
-]
-
-[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 = "watchdog"
-version = "4.0.2"
-source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/4f/38/764baaa25eb5e35c9a043d4c4588f9836edfe52a708950f4b6d5f714fd42/watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270", size = 126587, upload-time = "2024-08-11T07:38:01.623Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/92/f5/ea22b095340545faea37ad9a42353b265ca751f543da3fb43f5d00cdcd21/watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a", size = 100342, upload-time = "2024-08-11T07:37:16.393Z" },
- { url = "https://files.pythonhosted.org/packages/cb/d2/8ce97dff5e465db1222951434e3115189ae54a9863aef99c6987890cc9ef/watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29", size = 92306, upload-time = "2024-08-11T07:37:17.997Z" },
- { url = "https://files.pythonhosted.org/packages/49/c4/1aeba2c31b25f79b03b15918155bc8c0b08101054fc727900f1a577d0d54/watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a", size = 92915, upload-time = "2024-08-11T07:37:19.967Z" },
- { url = "https://files.pythonhosted.org/packages/79/63/eb8994a182672c042d85a33507475c50c2ee930577524dd97aea05251527/watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b", size = 100343, upload-time = "2024-08-11T07:37:21.935Z" },
- { url = "https://files.pythonhosted.org/packages/ce/82/027c0c65c2245769580605bcd20a1dc7dfd6c6683c8c4e2ef43920e38d27/watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d", size = 92313, upload-time = "2024-08-11T07:37:23.314Z" },
- { url = "https://files.pythonhosted.org/packages/2a/89/ad4715cbbd3440cb0d336b78970aba243a33a24b1a79d66f8d16b4590d6a/watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7", size = 92919, upload-time = "2024-08-11T07:37:24.715Z" },
- { url = "https://files.pythonhosted.org/packages/8a/b1/25acf6767af6f7e44e0086309825bd8c098e301eed5868dc5350642124b9/watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83", size = 82947, upload-time = "2024-08-11T07:37:45.388Z" },
- { url = "https://files.pythonhosted.org/packages/e8/90/aebac95d6f954bd4901f5d46dcd83d68e682bfd21798fd125a95ae1c9dbf/watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c", size = 82942, upload-time = "2024-08-11T07:37:46.722Z" },
- { url = "https://files.pythonhosted.org/packages/15/3a/a4bd8f3b9381824995787488b9282aff1ed4667e1110f31a87b871ea851c/watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a", size = 82947, upload-time = "2024-08-11T07:37:48.941Z" },
- { url = "https://files.pythonhosted.org/packages/09/cc/238998fc08e292a4a18a852ed8274159019ee7a66be14441325bcd811dfd/watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73", size = 82946, upload-time = "2024-08-11T07:37:50.279Z" },
- { url = "https://files.pythonhosted.org/packages/80/f1/d4b915160c9d677174aa5fae4537ae1f5acb23b3745ab0873071ef671f0a/watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc", size = 82947, upload-time = "2024-08-11T07:37:51.55Z" },
- { url = "https://files.pythonhosted.org/packages/db/02/56ebe2cf33b352fe3309588eb03f020d4d1c061563d9858a9216ba004259/watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757", size = 82944, upload-time = "2024-08-11T07:37:52.855Z" },
- { url = "https://files.pythonhosted.org/packages/01/d2/c8931ff840a7e5bd5dcb93f2bb2a1fd18faf8312e9f7f53ff1cf76ecc8ed/watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8", size = 82947, upload-time = "2024-08-11T07:37:55.172Z" },
- { url = "https://files.pythonhosted.org/packages/d0/d8/cdb0c21a4a988669d7c210c75c6a2c9a0e16a3b08d9f7e633df0d9a16ad8/watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19", size = 82935, upload-time = "2024-08-11T07:37:56.668Z" },
- { url = "https://files.pythonhosted.org/packages/99/2e/b69dfaae7a83ea64ce36538cc103a3065e12c447963797793d5c0a1d5130/watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b", size = 82934, upload-time = "2024-08-11T07:37:57.991Z" },
- { url = "https://files.pythonhosted.org/packages/b0/0b/43b96a9ecdd65ff5545b1b13b687ca486da5c6249475b1a45f24d63a1858/watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c", size = 82933, upload-time = "2024-08-11T07:37:59.573Z" },
-]
-
-[[package]]
-name = "watchfiles"
-version = "1.0.5"
-source = { registry = "https://pypi.org/simple" }
-dependencies = [
- { name = "anyio" },
-]
-sdist = { url = "https://files.pythonhosted.org/packages/03/e2/8ed598c42057de7aa5d97c472254af4906ff0a59a66699d426fc9ef795d7/watchfiles-1.0.5.tar.gz", hash = "sha256:b7529b5dcc114679d43827d8c35a07c493ad6f083633d573d81c660abc5979e9", size = 94537, upload-time = "2025-04-08T10:36:26.722Z" }
-wheels = [
- { url = "https://files.pythonhosted.org/packages/2a/8c/4f0b9bdb75a1bfbd9c78fad7d8854369283f74fe7cf03eb16be77054536d/watchfiles-1.0.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5eb568c2aa6018e26da9e6c86f3ec3fd958cee7f0311b35c2630fa4217d17f2", size = 401511, upload-time = "2025-04-08T10:35:17.956Z" },
- { url = "https://files.pythonhosted.org/packages/dc/4e/7e15825def77f8bd359b6d3f379f0c9dac4eb09dd4ddd58fd7d14127179c/watchfiles-1.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0a04059f4923ce4e856b4b4e5e783a70f49d9663d22a4c3b3298165996d1377f", size = 392715, upload-time = "2025-04-08T10:35:19.202Z" },
- { url = "https://files.pythonhosted.org/packages/58/65/b72fb817518728e08de5840d5d38571466c1b4a3f724d190cec909ee6f3f/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e380c89983ce6e6fe2dd1e1921b9952fb4e6da882931abd1824c092ed495dec", size = 454138, upload-time = "2025-04-08T10:35:20.586Z" },
- { url = "https://files.pythonhosted.org/packages/3e/a4/86833fd2ea2e50ae28989f5950b5c3f91022d67092bfec08f8300d8b347b/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fe43139b2c0fdc4a14d4f8d5b5d967f7a2777fd3d38ecf5b1ec669b0d7e43c21", size = 458592, upload-time = "2025-04-08T10:35:21.87Z" },
- { url = "https://files.pythonhosted.org/packages/38/7e/42cb8df8be9a37e50dd3a818816501cf7a20d635d76d6bd65aae3dbbff68/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee0822ce1b8a14fe5a066f93edd20aada932acfe348bede8aa2149f1a4489512", size = 487532, upload-time = "2025-04-08T10:35:23.143Z" },
- { url = "https://files.pythonhosted.org/packages/fc/fd/13d26721c85d7f3df6169d8b495fcac8ab0dc8f0945ebea8845de4681dab/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a0dbcb1c2d8f2ab6e0a81c6699b236932bd264d4cef1ac475858d16c403de74d", size = 522865, upload-time = "2025-04-08T10:35:24.702Z" },
- { url = "https://files.pythonhosted.org/packages/a1/0d/7f9ae243c04e96c5455d111e21b09087d0eeaf9a1369e13a01c7d3d82478/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a2014a2b18ad3ca53b1f6c23f8cd94a18ce930c1837bd891262c182640eb40a6", size = 499887, upload-time = "2025-04-08T10:35:25.969Z" },
- { url = "https://files.pythonhosted.org/packages/8e/0f/a257766998e26aca4b3acf2ae97dff04b57071e991a510857d3799247c67/watchfiles-1.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6ae86d5cb647bf58f9f655fcf577f713915a5d69057a0371bc257e2553234", size = 454498, upload-time = "2025-04-08T10:35:27.353Z" },
- { url = "https://files.pythonhosted.org/packages/81/79/8bf142575a03e0af9c3d5f8bcae911ee6683ae93a625d349d4ecf4c8f7df/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1a7bac2bde1d661fb31f4d4e8e539e178774b76db3c2c17c4bb3e960a5de07a2", size = 630663, upload-time = "2025-04-08T10:35:28.685Z" },
- { url = "https://files.pythonhosted.org/packages/f1/80/abe2e79f610e45c63a70d271caea90c49bbf93eb00fa947fa9b803a1d51f/watchfiles-1.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ab626da2fc1ac277bbf752446470b367f84b50295264d2d313e28dc4405d663", size = 625410, upload-time = "2025-04-08T10:35:30.42Z" },
- { url = "https://files.pythonhosted.org/packages/91/6f/bc7fbecb84a41a9069c2c6eb6319f7f7df113adf113e358c57fc1aff7ff5/watchfiles-1.0.5-cp312-cp312-win32.whl", hash = "sha256:9f4571a783914feda92018ef3901dab8caf5b029325b5fe4558c074582815249", size = 277965, upload-time = "2025-04-08T10:35:32.023Z" },
- { url = "https://files.pythonhosted.org/packages/99/a5/bf1c297ea6649ec59e935ab311f63d8af5faa8f0b86993e3282b984263e3/watchfiles-1.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:360a398c3a19672cf93527f7e8d8b60d8275119c5d900f2e184d32483117a705", size = 291693, upload-time = "2025-04-08T10:35:33.225Z" },
- { url = "https://files.pythonhosted.org/packages/7f/7b/fd01087cc21db5c47e5beae507b87965db341cce8a86f9eb12bf5219d4e0/watchfiles-1.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:1a2902ede862969077b97523987c38db28abbe09fb19866e711485d9fbf0d417", size = 283287, upload-time = "2025-04-08T10:35:34.568Z" },
- { url = "https://files.pythonhosted.org/packages/c7/62/435766874b704f39b2fecd8395a29042db2b5ec4005bd34523415e9bd2e0/watchfiles-1.0.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0b289572c33a0deae62daa57e44a25b99b783e5f7aed81b314232b3d3c81a11d", size = 401531, upload-time = "2025-04-08T10:35:35.792Z" },
- { url = "https://files.pythonhosted.org/packages/6e/a6/e52a02c05411b9cb02823e6797ef9bbba0bfaf1bb627da1634d44d8af833/watchfiles-1.0.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a056c2f692d65bf1e99c41045e3bdcaea3cb9e6b5a53dcaf60a5f3bd95fc9763", size = 392417, upload-time = "2025-04-08T10:35:37.048Z" },
- { url = "https://files.pythonhosted.org/packages/3f/53/c4af6819770455932144e0109d4854437769672d7ad897e76e8e1673435d/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9dca99744991fc9850d18015c4f0438865414e50069670f5f7eee08340d8b40", size = 453423, upload-time = "2025-04-08T10:35:38.357Z" },
- { url = "https://files.pythonhosted.org/packages/cb/d1/8e88df58bbbf819b8bc5cfbacd3c79e01b40261cad0fc84d1e1ebd778a07/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:894342d61d355446d02cd3988a7326af344143eb33a2fd5d38482a92072d9563", size = 458185, upload-time = "2025-04-08T10:35:39.708Z" },
- { url = "https://files.pythonhosted.org/packages/ff/70/fffaa11962dd5429e47e478a18736d4e42bec42404f5ee3b92ef1b87ad60/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab44e1580924d1ffd7b3938e02716d5ad190441965138b4aa1d1f31ea0877f04", size = 486696, upload-time = "2025-04-08T10:35:41.469Z" },
- { url = "https://files.pythonhosted.org/packages/39/db/723c0328e8b3692d53eb273797d9a08be6ffb1d16f1c0ba2bdbdc2a3852c/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d6f9367b132078b2ceb8d066ff6c93a970a18c3029cea37bfd7b2d3dd2e5db8f", size = 522327, upload-time = "2025-04-08T10:35:43.289Z" },
- { url = "https://files.pythonhosted.org/packages/cd/05/9fccc43c50c39a76b68343484b9da7b12d42d0859c37c61aec018c967a32/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2e55a9b162e06e3f862fb61e399fe9f05d908d019d87bf5b496a04ef18a970a", size = 499741, upload-time = "2025-04-08T10:35:44.574Z" },
- { url = "https://files.pythonhosted.org/packages/23/14/499e90c37fa518976782b10a18b18db9f55ea73ca14641615056f8194bb3/watchfiles-1.0.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0125f91f70e0732a9f8ee01e49515c35d38ba48db507a50c5bdcad9503af5827", size = 453995, upload-time = "2025-04-08T10:35:46.336Z" },
- { url = "https://files.pythonhosted.org/packages/61/d9/f75d6840059320df5adecd2c687fbc18960a7f97b55c300d20f207d48aef/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:13bb21f8ba3248386337c9fa51c528868e6c34a707f729ab041c846d52a0c69a", size = 629693, upload-time = "2025-04-08T10:35:48.161Z" },
- { url = "https://files.pythonhosted.org/packages/fc/17/180ca383f5061b61406477218c55d66ec118e6c0c51f02d8142895fcf0a9/watchfiles-1.0.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:839ebd0df4a18c5b3c1b890145b5a3f5f64063c2a0d02b13c76d78fe5de34936", size = 624677, upload-time = "2025-04-08T10:35:49.65Z" },
- { url = "https://files.pythonhosted.org/packages/bf/15/714d6ef307f803f236d69ee9d421763707899d6298d9f3183e55e366d9af/watchfiles-1.0.5-cp313-cp313-win32.whl", hash = "sha256:4a8ec1e4e16e2d5bafc9ba82f7aaecfeec990ca7cd27e84fb6f191804ed2fcfc", size = 277804, upload-time = "2025-04-08T10:35:51.093Z" },
- { url = "https://files.pythonhosted.org/packages/a8/b4/c57b99518fadf431f3ef47a610839e46e5f8abf9814f969859d1c65c02c7/watchfiles-1.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:f436601594f15bf406518af922a89dcaab416568edb6f65c4e5bbbad1ea45c11", size = 291087, upload-time = "2025-04-08T10:35:52.458Z" },
-]
-
-[[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" },
-]