vibetuner 2.8.3__py3-none-any.whl → 2.9.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of vibetuner might be problematic. Click here for more details.

vibetuner/cli/__init__.py CHANGED
@@ -9,6 +9,7 @@ import typer
9
9
  from rich.console import Console
10
10
 
11
11
  from vibetuner.cli.run import run_app
12
+ from vibetuner.cli.scaffold import scaffold_app
12
13
  from vibetuner.config import settings
13
14
  from vibetuner.logging import LogLevel, setup_logging
14
15
 
@@ -61,6 +62,7 @@ def callback(log_level: LogLevel | None = LOG_LEVEL_OPTION) -> None:
61
62
 
62
63
 
63
64
  app.add_typer(run_app, name="run")
65
+ app.add_typer(scaffold_app, name="scaffold")
64
66
 
65
67
  try:
66
68
  import_module("app.cli")
@@ -0,0 +1,189 @@
1
+ # ABOUTME: Scaffolding commands for creating new projects from the vibetuner template
2
+ # ABOUTME: Uses Copier to generate FastAPI+MongoDB+HTMX projects with interactive prompts
3
+ from pathlib import Path
4
+ from typing import Annotated
5
+
6
+ import copier
7
+ import typer
8
+ from rich.console import Console
9
+
10
+
11
+ console = Console()
12
+
13
+ scaffold_app = typer.Typer(
14
+ help="Create new projects from the vibetuner template", no_args_is_help=True
15
+ )
16
+
17
+
18
+ def get_template_path() -> Path:
19
+ """Get the path to the vibetuner template directory."""
20
+ # This file is at: vibetuner-py/src/vibetuner/cli/scaffold.py
21
+ # Template is at: ./ (root of repo)
22
+ current_file = Path(__file__).resolve()
23
+ # Go up: scaffold.py -> cli -> vibetuner -> src -> vibetuner-py -> repo_root
24
+ template_path = current_file.parent.parent.parent.parent.parent
25
+ return template_path
26
+
27
+
28
+ @scaffold_app.command(name="new")
29
+ def new(
30
+ destination: Annotated[
31
+ Path,
32
+ typer.Argument(
33
+ help="Destination directory for the new project",
34
+ exists=False,
35
+ ),
36
+ ],
37
+ template: Annotated[
38
+ str | None,
39
+ typer.Option(
40
+ "--template",
41
+ "-t",
42
+ help="Template source (git URL, local path, or github:user/repo). Defaults to local vibetuner template.",
43
+ ),
44
+ ] = None,
45
+ defaults: Annotated[
46
+ bool,
47
+ typer.Option(
48
+ "--defaults",
49
+ "-d",
50
+ help="Use default values for all prompts (non-interactive mode)",
51
+ ),
52
+ ] = False,
53
+ data: Annotated[
54
+ list[str] | None,
55
+ typer.Option(
56
+ "--data",
57
+ help="Override template variables in key=value format (can be used multiple times)",
58
+ ),
59
+ ] = None,
60
+ ) -> None:
61
+ """Create a new project from the vibetuner template.
62
+
63
+ Examples:
64
+
65
+ # Interactive mode (prompts for all values)
66
+ vibetuner scaffold new my-project
67
+
68
+ # Use defaults for all prompts
69
+ vibetuner scaffold new my-project --defaults
70
+
71
+ # Override specific values
72
+ vibetuner scaffold new my-project --data project_name="My App" --data python_version="3.13"
73
+
74
+ # Use a different template source
75
+ vibetuner scaffold new my-project --template gh:alltuner/vibetuner
76
+ vibetuner scaffold new my-project --template /path/to/template
77
+ """
78
+ # Determine template source
79
+ if template is None:
80
+ template_src = get_template_path()
81
+ console.print(f"[dim]Using local template: {template_src}[/dim]")
82
+ else:
83
+ template_src = template
84
+ console.print(f"[dim]Using template: {template_src}[/dim]")
85
+
86
+ # Parse data overrides
87
+ data_dict = {}
88
+ if data:
89
+ for item in data:
90
+ if "=" not in item:
91
+ console.print(f"[red]Error: Invalid data format '{item}'. Expected key=value[/red]")
92
+ raise typer.Exit(code=1)
93
+ key, value = item.split("=", 1)
94
+ data_dict[key] = value
95
+
96
+ # When using defaults, provide sensible default values for required fields
97
+ if defaults:
98
+ default_values = {
99
+ "company_name": "Acme Corp",
100
+ "author_name": "Developer",
101
+ "author_email": "dev@example.com",
102
+ "supported_languages": [],
103
+ }
104
+ # Merge: user overrides take precedence over defaults
105
+ data_dict = {**default_values, **data_dict}
106
+
107
+ # Run copier
108
+ try:
109
+ console.print(f"\n[green]Creating new project in: {destination}[/green]\n")
110
+
111
+ copier.run_copy(
112
+ src_path=str(template_src),
113
+ dst_path=destination,
114
+ data=data_dict if data_dict else None,
115
+ defaults=defaults,
116
+ quiet=defaults, # Suppress prompts when using defaults
117
+ unsafe=True, # Allow running post-generation tasks
118
+ )
119
+
120
+ console.print(f"\n[green]✓ Project created successfully![/green]")
121
+ console.print(f"\nNext steps:")
122
+ console.print(f" cd {destination}")
123
+ console.print(f" just dev")
124
+
125
+ except Exception as e:
126
+ console.print(f"[red]Error creating project: {e}[/red]")
127
+ raise typer.Exit(code=1)
128
+
129
+
130
+ @scaffold_app.command(name="update")
131
+ def update(
132
+ path: Annotated[
133
+ Path,
134
+ typer.Argument(
135
+ help="Path to the project to update",
136
+ ),
137
+ ] = Path.cwd(),
138
+ skip_answered: Annotated[
139
+ bool,
140
+ typer.Option(
141
+ "--skip-answered",
142
+ "-s",
143
+ help="Skip questions that have already been answered",
144
+ ),
145
+ ] = True,
146
+ ) -> None:
147
+ """Update an existing project to the latest template version.
148
+
149
+ This will update the project's files to match the latest template version,
150
+ while preserving your answers to the original questions.
151
+
152
+ Examples:
153
+
154
+ # Update current directory
155
+ vibetuner scaffold update
156
+
157
+ # Update specific directory
158
+ vibetuner scaffold update /path/to/project
159
+
160
+ # Re-prompt for all questions
161
+ vibetuner scaffold update --no-skip-answered
162
+ """
163
+ if not path.exists():
164
+ console.print(f"[red]Error: Directory does not exist: {path}[/red]")
165
+ raise typer.Exit(code=1)
166
+
167
+ # Check if it's a copier project
168
+ answers_file = path / ".copier-answers.yml"
169
+ if not answers_file.exists():
170
+ console.print(
171
+ f"[red]Error: Not a copier project (missing .copier-answers.yml)[/red]"
172
+ )
173
+ console.print(f"[yellow]Directory: {path}[/yellow]")
174
+ raise typer.Exit(code=1)
175
+
176
+ try:
177
+ console.print(f"\n[green]Updating project: {path}[/green]\n")
178
+
179
+ copier.run_update(
180
+ dst_path=path,
181
+ skip_answered=skip_answered,
182
+ unsafe=True, # Allow running post-generation tasks
183
+ )
184
+
185
+ console.print(f"\n[green]✓ Project updated successfully![/green]")
186
+
187
+ except Exception as e:
188
+ console.print(f"[red]Error updating project: {e}[/red]")
189
+ raise typer.Exit(code=1)
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.3
2
+ Name: vibetuner
3
+ Version: 2.9.1
4
+ Summary: Core Python framework and blessed dependencies for production-ready FastAPI + MongoDB + HTMX projects
5
+ Keywords: fastapi,mongodb,htmx,web-framework,scaffolding,oauth,background-jobs
6
+ Author: All Tuner Labs, S.L.
7
+ License: MIT
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Framework :: FastAPI
17
+ Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
18
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
19
+ Requires-Dist: aioboto3>=15.5.0
20
+ Requires-Dist: arel>=0.4.0
21
+ Requires-Dist: asyncer>=0.0.10
22
+ Requires-Dist: authlib>=1.6.5
23
+ Requires-Dist: beanie[zstd]>=2.0.0
24
+ Requires-Dist: click>=8.3.0
25
+ Requires-Dist: copier>=9.9.0,<9.9.1
26
+ Requires-Dist: email-validator>=2.3.0
27
+ Requires-Dist: fastapi[standard-no-fastapi-cloud-cli]>=0.121.0
28
+ Requires-Dist: granian[pname]>=2.5.6
29
+ Requires-Dist: httpx[http2]>=0.28.1
30
+ Requires-Dist: itsdangerous>=2.2.0
31
+ Requires-Dist: loguru>=0.7.3
32
+ Requires-Dist: pydantic[email]>=2.12.3
33
+ Requires-Dist: pydantic-extra-types[pycountry]>=2.10.6
34
+ Requires-Dist: pydantic-settings>=2.11.0
35
+ Requires-Dist: pyyaml>=6.0.3
36
+ Requires-Dist: redis[hiredis]>=7.0.1
37
+ Requires-Dist: rich>=14.2.0
38
+ Requires-Dist: sse-starlette>=3.0.3
39
+ Requires-Dist: starlette-babel>=1.0.3
40
+ Requires-Dist: starlette-htmx>=0.1.1
41
+ Requires-Dist: streaq[web]<6.0.0
42
+ Requires-Dist: typer-slim[standard]>=0.20.0
43
+ Requires-Dist: babel>=2.17.0 ; extra == 'dev'
44
+ Requires-Dist: cloudflare>=4.3.1 ; extra == 'dev'
45
+ Requires-Dist: djlint>=1.36.4 ; extra == 'dev'
46
+ Requires-Dist: dunamai>=1.25.0 ; extra == 'dev'
47
+ Requires-Dist: gh-bin>=2.81.0 ; extra == 'dev'
48
+ Requires-Dist: granian[pname,reload]>=2.5.6 ; extra == 'dev'
49
+ Requires-Dist: just-bin>=1.43.0 ; extra == 'dev'
50
+ Requires-Dist: pre-commit>=4.3.0 ; extra == 'dev'
51
+ Requires-Dist: pysemver>=0.5.0 ; extra == 'dev'
52
+ Requires-Dist: ruff>=0.14.3 ; extra == 'dev'
53
+ Requires-Dist: rumdl>=0.0.171 ; extra == 'dev'
54
+ Requires-Dist: semver>=3.0.4 ; extra == 'dev'
55
+ Requires-Dist: taplo>=0.9.3 ; extra == 'dev'
56
+ Requires-Dist: ty>=0.0.1a25 ; extra == 'dev'
57
+ Requires-Dist: types-aioboto3[s3,ses]>=15.5.0 ; extra == 'dev'
58
+ Requires-Dist: types-authlib>=1.6.5.20251005 ; extra == 'dev'
59
+ Requires-Dist: types-pyyaml>=6.0.12.20250915 ; extra == 'dev'
60
+ Requires-Dist: uv-bump>=0.3.1 ; extra == 'dev'
61
+ Requires-Python: >=3.11
62
+ Project-URL: Documentation, https://github.com/alltuner/vibetuner#readme
63
+ Project-URL: Homepage, https://github.com/alltuner/vibetuner
64
+ Project-URL: Issues, https://github.com/alltuner/vibetuner/issues
65
+ Project-URL: Repository, https://github.com/alltuner/vibetuner
66
+ Provides-Extra: dev
67
+ Description-Content-Type: text/markdown
68
+
69
+ # vibetuner
70
+
71
+ **Core Python framework and blessed dependencies for Vibetuner projects**
72
+
73
+ This package provides the complete Python framework and curated dependency set for building modern web applications with Vibetuner. It includes everything from FastAPI and MongoDB integration to authentication, background jobs, and CLI tools.
74
+
75
+ ## What is Vibetuner?
76
+
77
+ Vibetuner is a production-ready scaffolding tool for FastAPI + MongoDB + HTMX web applications. This package (`vibetuner`) is the Python component that provides:
78
+
79
+ - Complete web application framework built on FastAPI
80
+ - MongoDB integration with Beanie ODM
81
+ - OAuth and magic link authentication out of the box
82
+ - Background job processing with Redis + Streaq
83
+ - CLI framework with Typer
84
+ - Email services, blob storage, and more
85
+
86
+ **This package is designed to be used within projects generated by the Vibetuner scaffolding tool.** For standalone use, you'll need to set up the project structure manually.
87
+
88
+ ## Installation
89
+
90
+ ```bash
91
+ # In a Vibetuner-generated project (automatic)
92
+ uv sync
93
+
94
+ # Add to an existing project
95
+ uv add vibetuner
96
+
97
+ # With development dependencies
98
+ uv add vibetuner[dev]
99
+ ```
100
+
101
+ ## Quick Start
102
+
103
+ The recommended way to use Vibetuner is via the scaffolding tool:
104
+
105
+ ```bash
106
+ # Create a new project with all the framework code
107
+ uvx vibetuner scaffold new my-project
108
+ cd my-project
109
+ just dev
110
+ ```
111
+
112
+ This will generate a complete project with:
113
+ - Pre-configured FastAPI application
114
+ - Authentication system (OAuth + magic links)
115
+ - MongoDB models and configuration
116
+ - Frontend templates and asset pipeline
117
+ - Docker setup for development and production
118
+ - CLI commands and background job infrastructure
119
+
120
+ ## What's Included
121
+
122
+ ### Core Framework (`src/vibetuner/`)
123
+
124
+ - **`frontend/`**: FastAPI app, routes, middleware, auth
125
+ - **`models/`**: User, OAuth, email verification, blob storage models
126
+ - **`services/`**: Email (SES), blob storage (S3)
127
+ - **`tasks/`**: Background job infrastructure
128
+ - **`cli/`**: CLI framework with scaffold, run commands
129
+ - **`config.py`**: Pydantic settings management
130
+ - **`mongo.py`**: MongoDB/Beanie setup
131
+ - **`logging.py`**: Structured logging configuration
132
+
133
+ ### Blessed Dependencies
134
+
135
+ - **FastAPI** (0.121+): Modern, fast web framework
136
+ - **Beanie**: Async MongoDB ODM with Pydantic
137
+ - **Authlib**: OAuth 1.0/2.0 client
138
+ - **Granian**: High-performance ASGI server
139
+ - **Redis** + **Streaq**: Background task processing
140
+ - **Typer**: CLI framework
141
+ - **Rich**: Beautiful terminal output
142
+ - **Loguru**: Structured logging
143
+ - **Pydantic**: Data validation and settings
144
+
145
+ See [pyproject.toml](./pyproject.toml) for the complete dependency list.
146
+
147
+ ## CLI Tools
148
+
149
+ When installed, provides the `vibetuner` command:
150
+
151
+ ```bash
152
+ # Create new project from template
153
+ vibetuner scaffold new my-project
154
+ vibetuner scaffold new my-project --defaults
155
+
156
+ # Update existing project
157
+ vibetuner scaffold update
158
+
159
+ # Run development server (in generated projects)
160
+ vibetuner run dev frontend
161
+ vibetuner run dev worker
162
+
163
+ # Run production server (in generated projects)
164
+ vibetuner run prod frontend
165
+ vibetuner run prod worker
166
+ ```
167
+
168
+ ## Development Dependencies
169
+
170
+ The `[dev]` extra includes all tools needed for development:
171
+
172
+ - **Ruff**: Fast linting and formatting
173
+ - **djlint**: Template linting
174
+ - **Babel**: i18n message extraction
175
+ - **pre-commit**: Git hooks
176
+ - **Type stubs**: For aioboto3, authlib, PyYAML
177
+ - And more...
178
+
179
+ ## Usage in Generated Projects
180
+
181
+ In a Vibetuner-generated project, import from `vibetuner`:
182
+
183
+ ```python
184
+ # Use core models
185
+ from vibetuner.models import UserModel, OAuthAccountModel
186
+
187
+ # Use services
188
+ from vibetuner.services.email import send_email
189
+
190
+ # Use configuration
191
+ from vibetuner.config import settings
192
+
193
+ # Extend core routes
194
+ from vibetuner.frontend import app
195
+
196
+ # Add your routes
197
+ @app.get("/api/hello")
198
+ async def hello():
199
+ return {"message": "Hello World"}
200
+ ```
201
+
202
+ ## Documentation
203
+
204
+ For complete documentation, guides, and examples, see the main Vibetuner repository:
205
+
206
+ **📖 [Vibetuner Documentation](https://github.com/alltuner/vibetuner#readme)**
207
+
208
+ ## Package Ecosystem
209
+
210
+ Vibetuner consists of three packages that work together:
211
+
212
+ 1. **vibetuner** (this package): Python framework and dependencies
213
+ 2. **[@alltuner/vibetuner](https://www.npmjs.com/package/@alltuner/vibetuner)**: JavaScript/CSS build dependencies
214
+ 3. **Scaffolding template**: Copier template for project generation
215
+
216
+ All three are version-locked and tested together to ensure compatibility.
217
+
218
+ ## Contributing
219
+
220
+ Contributions welcome! See the main repository for contribution guidelines:
221
+
222
+ **🤝 [Contributing to Vibetuner](https://github.com/alltuner/vibetuner/blob/main/CONTRIBUTING.md)**
223
+
224
+ ## License
225
+
226
+ MIT License - Copyright (c) 2025 All Tuner Labs, S.L.
227
+
228
+ See [LICENSE](https://github.com/alltuner/vibetuner/blob/main/LICENSE) for details.
229
+
230
+ ## Links
231
+
232
+ - **Main Repository**: https://github.com/alltuner/vibetuner
233
+ - **Documentation**: https://github.com/alltuner/vibetuner#readme
234
+ - **Issues**: https://github.com/alltuner/vibetuner/issues
235
+ - **PyPI**: https://pypi.org/project/vibetuner/
236
+ - **npm Package**: https://www.npmjs.com/package/@alltuner/vibetuner
@@ -1,7 +1,8 @@
1
1
  vibetuner/__init__.py,sha256=rFIVCmxkKTT_g477V8biCw0lgpudyuUabXhYxg189lY,90
2
2
  vibetuner/__main__.py,sha256=Ye9oBAgXhcYQ4I4yZli3TIXF5lWQ9yY4tTPs4XnDDUY,29
3
- vibetuner/cli/__init__.py,sha256=-DM7TxG9FJKCjTXpNNVSKwtl_Nn3TEg_2OYRJNsLObY,1741
3
+ vibetuner/cli/__init__.py,sha256=bipsxcOO2uxLGq-7TYVZsEOiknY3M54Kjh2W4pUXPDg,1834
4
4
  vibetuner/cli/run.py,sha256=mHvZypizNfVwdLo7k8SvBO7HPUF4Vka9hjJlECZCGfA,5009
5
+ vibetuner/cli/scaffold.py,sha256=Fm6QPEPB0KsRGOBJz_HbR6mnQxA11_KpRQOSw5hW7VM,5950
5
6
  vibetuner/config.py,sha256=R3u23RHv5gcVuU27WEo-8MrSZYbqSNbALJJKR3ACaQQ,3714
6
7
  vibetuner/context.py,sha256=VdgfX-SFmVwiwKPFID4ElIRnFADTlagqsh9RKXNiLCs,725
7
8
  vibetuner/frontend/AGENTS.md,sha256=mds0nTl3RBblTA7EFhC9dxx86mn1FH5ESXNSj_1R1Jk,3253
@@ -79,6 +80,7 @@ vibetuner/templates/markdown/CLAUDE.md,sha256=jcvoQNazCj-t54s0gr-4_qyxLMP8iPf2ur
79
80
  vibetuner/templates.py,sha256=xRoMb_oyAI5x4kxfpg56UcLKkT8e9HVn-o3KFAu9ISE,5094
80
81
  vibetuner/time.py,sha256=3_DtveCCzI20ocTnAlTh2u7FByUXtINaUoQZO-_uZow,1188
81
82
  vibetuner/versioning.py,sha256=UAHGoNsv3QEPAJgHyt_Q8I26SW7ng2FnZlX2-0M6r6U,156
82
- vibetuner-2.8.3.dist-info/WHEEL,sha256=5w2T7AS2mz1-rW9CNagNYWRCaB0iQqBMYLwKdlgiR4Q,78
83
- vibetuner-2.8.3.dist-info/METADATA,sha256=RT4aN5-l8lL4n_1ybXh5_yScbic1jSdnKp6HzWH2EUA,1956
84
- vibetuner-2.8.3.dist-info/RECORD,,
83
+ vibetuner-2.9.1.dist-info/WHEEL,sha256=5w2T7AS2mz1-rW9CNagNYWRCaB0iQqBMYLwKdlgiR4Q,78
84
+ vibetuner-2.9.1.dist-info/entry_points.txt,sha256=aKIj9YCCXizjYupx9PeWkUJePg3ncHke_LTS5rmCsfs,49
85
+ vibetuner-2.9.1.dist-info/METADATA,sha256=EY8HWtayYDABK9eJqTO0-7OiWIDDPPN9iZEdRnsm9yI,8042
86
+ vibetuner-2.9.1.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ vibetuner = vibetuner.cli:app
3
+
@@ -1,48 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: vibetuner
3
- Version: 2.8.3
4
- Summary: Blessed Python dependencies for Vibetuner projects
5
- Requires-Dist: aioboto3>=15.5.0
6
- Requires-Dist: arel>=0.4.0
7
- Requires-Dist: asyncer>=0.0.10
8
- Requires-Dist: authlib>=1.6.5
9
- Requires-Dist: beanie[zstd]>=2.0.0
10
- Requires-Dist: click>=8.3.0
11
- Requires-Dist: email-validator>=2.3.0
12
- Requires-Dist: fastapi[standard-no-fastapi-cloud-cli]>=0.121.0
13
- Requires-Dist: granian[pname]>=2.5.6
14
- Requires-Dist: httpx[http2]>=0.28.1
15
- Requires-Dist: itsdangerous>=2.2.0
16
- Requires-Dist: loguru>=0.7.3
17
- Requires-Dist: pydantic[email]>=2.12.3
18
- Requires-Dist: pydantic-extra-types[pycountry]>=2.10.6
19
- Requires-Dist: pydantic-settings>=2.11.0
20
- Requires-Dist: pyyaml>=6.0.3
21
- Requires-Dist: redis[hiredis]>=7.0.1
22
- Requires-Dist: rich>=14.2.0
23
- Requires-Dist: sse-starlette>=3.0.3
24
- Requires-Dist: starlette-babel>=1.0.3
25
- Requires-Dist: starlette-htmx>=0.1.1
26
- Requires-Dist: streaq[web]<6.0.0
27
- Requires-Dist: typer-slim[standard]>=0.20.0
28
- Requires-Dist: babel>=2.17.0 ; extra == 'dev'
29
- Requires-Dist: cloudflare>=4.3.1 ; extra == 'dev'
30
- Requires-Dist: copier>=9.9.0,<9.9.1 ; extra == 'dev'
31
- Requires-Dist: djlint>=1.36.4 ; extra == 'dev'
32
- Requires-Dist: dunamai>=1.25.0 ; extra == 'dev'
33
- Requires-Dist: gh-bin>=2.81.0 ; extra == 'dev'
34
- Requires-Dist: granian[pname,reload]>=2.5.6 ; extra == 'dev'
35
- Requires-Dist: just-bin>=1.43.0 ; extra == 'dev'
36
- Requires-Dist: pre-commit>=4.3.0 ; extra == 'dev'
37
- Requires-Dist: pysemver>=0.5.0 ; extra == 'dev'
38
- Requires-Dist: ruff>=0.14.3 ; extra == 'dev'
39
- Requires-Dist: rumdl>=0.0.171 ; extra == 'dev'
40
- Requires-Dist: semver>=3.0.4 ; extra == 'dev'
41
- Requires-Dist: taplo>=0.9.3 ; extra == 'dev'
42
- Requires-Dist: ty>=0.0.1a25 ; extra == 'dev'
43
- Requires-Dist: types-aioboto3[s3,ses]>=15.5.0 ; extra == 'dev'
44
- Requires-Dist: types-authlib>=1.6.5.20251005 ; extra == 'dev'
45
- Requires-Dist: types-pyyaml>=6.0.12.20250915 ; extra == 'dev'
46
- Requires-Dist: uv-bump>=0.3.1 ; extra == 'dev'
47
- Requires-Python: >=3.11
48
- Provides-Extra: dev