spry-core 0.1.0__tar.gz
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.
- spry_core-0.1.0/LICENSE +21 -0
- spry_core-0.1.0/PKG-INFO +426 -0
- spry_core-0.1.0/README.md +386 -0
- spry_core-0.1.0/pyproject.toml +57 -0
- spry_core-0.1.0/setup.cfg +4 -0
- spry_core-0.1.0/src/spry/__init__.py +95 -0
- spry_core-0.1.0/src/spry/app.py +741 -0
- spry_core-0.1.0/src/spry/auth.py +264 -0
- spry_core-0.1.0/src/spry/cli.py +428 -0
- spry_core-0.1.0/src/spry/config.py +167 -0
- spry_core-0.1.0/src/spry/controllers.py +97 -0
- spry_core-0.1.0/src/spry/cors.py +57 -0
- spry_core-0.1.0/src/spry/csrf.py +46 -0
- spry_core-0.1.0/src/spry/db/__init__.py +11 -0
- spry_core-0.1.0/src/spry/db/backend.py +129 -0
- spry_core-0.1.0/src/spry/db/backends/__init__.py +50 -0
- spry_core-0.1.0/src/spry/db/backends/mariadb.py +7 -0
- spry_core-0.1.0/src/spry/db/backends/mysql.py +72 -0
- spry_core-0.1.0/src/spry/db/backends/postgres.py +86 -0
- spry_core-0.1.0/src/spry/db/backends/sqlite.py +62 -0
- spry_core-0.1.0/src/spry/db/backends/sqlserver.py +91 -0
- spry_core-0.1.0/src/spry/db/column_type.py +9 -0
- spry_core-0.1.0/src/spry/db/url.py +55 -0
- spry_core-0.1.0/src/spry/debug.py +134 -0
- spry_core-0.1.0/src/spry/di.py +172 -0
- spry_core-0.1.0/src/spry/events.py +48 -0
- spry_core-0.1.0/src/spry/http.py +308 -0
- spry_core-0.1.0/src/spry/i18n.py +73 -0
- spry_core-0.1.0/src/spry/middleware.py +22 -0
- spry_core-0.1.0/src/spry/openapi.py +288 -0
- spry_core-0.1.0/src/spry/orm.py +737 -0
- spry_core-0.1.0/src/spry/results.py +26 -0
- spry_core-0.1.0/src/spry/routing.py +149 -0
- spry_core-0.1.0/src/spry/scaffold.py +72 -0
- spry_core-0.1.0/src/spry/session.py +122 -0
- spry_core-0.1.0/src/spry/tasks.py +63 -0
- spry_core-0.1.0/src/spry/templates/api/Dockerfile.tmpl +30 -0
- spry_core-0.1.0/src/spry/templates/api/README.md.tmpl +29 -0
- spry_core-0.1.0/src/spry/templates/api/appsettings.json.tmpl +9 -0
- spry_core-0.1.0/src/spry/templates/api/docker-compose.yml.tmpl +17 -0
- spry_core-0.1.0/src/spry/templates/api/main.py.tmpl +8 -0
- spry_core-0.1.0/src/spry/templates/api/pyproject.toml.tmpl +15 -0
- spry_core-0.1.0/src/spry/templates/api/src/__PACKAGE_NAME__/__init__.py.tmpl +3 -0
- spry_core-0.1.0/src/spry/templates/api/src/__PACKAGE_NAME__/app.py.tmpl +25 -0
- spry_core-0.1.0/src/spry/templates/api/src/__PACKAGE_NAME__/controllers.py.tmpl +44 -0
- spry_core-0.1.0/src/spry/templates/api/src/__PACKAGE_NAME__/data.py.tmpl +19 -0
- spry_core-0.1.0/src/spry/templates/api/src/__PACKAGE_NAME__/seed.py.tmpl +9 -0
- spry_core-0.1.0/src/spry/templates/mvc/Dockerfile.tmpl +30 -0
- spry_core-0.1.0/src/spry/templates/mvc/README.md.tmpl +109 -0
- spry_core-0.1.0/src/spry/templates/mvc/appsettings.json.tmpl +13 -0
- spry_core-0.1.0/src/spry/templates/mvc/docker-compose.yml.tmpl +17 -0
- spry_core-0.1.0/src/spry/templates/mvc/main.py.tmpl +8 -0
- spry_core-0.1.0/src/spry/templates/mvc/pyproject.toml.tmpl +15 -0
- spry_core-0.1.0/src/spry/templates/mvc/src/__PACKAGE_NAME__/__init__.py.tmpl +3 -0
- spry_core-0.1.0/src/spry/templates/mvc/src/__PACKAGE_NAME__/app.py.tmpl +36 -0
- spry_core-0.1.0/src/spry/templates/mvc/src/__PACKAGE_NAME__/controllers.py.tmpl +130 -0
- spry_core-0.1.0/src/spry/templates/mvc/src/__PACKAGE_NAME__/data.py.tmpl +25 -0
- spry_core-0.1.0/src/spry/templates/mvc/src/__PACKAGE_NAME__/seed.py.tmpl +19 -0
- spry_core-0.1.0/src/spry/templates/mvc/static/site.css.tmpl +352 -0
- spry_core-0.1.0/src/spry/templates/mvc/views/account/login.html.tmpl +22 -0
- spry_core-0.1.0/src/spry/templates/mvc/views/home/_todo_card.html.tmpl +19 -0
- spry_core-0.1.0/src/spry/templates/mvc/views/home/index.html.tmpl +93 -0
- spry_core-0.1.0/src/spry/templates/mvc/views/shared/_alert.html.tmpl +1 -0
- spry_core-0.1.0/src/spry/templates/mvc/views/shared/_empty_state.html.tmpl +7 -0
- spry_core-0.1.0/src/spry/templates/mvc/views/shared/_layout.html.tmpl +13 -0
- spry_core-0.1.0/src/spry/testing.py +168 -0
- spry_core-0.1.0/src/spry/throttling.py +66 -0
- spry_core-0.1.0/src/spry/validation.py +160 -0
- spry_core-0.1.0/src/spry/validators.py +122 -0
- spry_core-0.1.0/src/spry/views.py +582 -0
- spry_core-0.1.0/src/spry_core.egg-info/PKG-INFO +426 -0
- spry_core-0.1.0/src/spry_core.egg-info/SOURCES.txt +91 -0
- spry_core-0.1.0/src/spry_core.egg-info/dependency_links.txt +1 -0
- spry_core-0.1.0/src/spry_core.egg-info/entry_points.txt +2 -0
- spry_core-0.1.0/src/spry_core.egg-info/requires.txt +21 -0
- spry_core-0.1.0/src/spry_core.egg-info/top_level.txt +1 -0
- spry_core-0.1.0/tests/test_application.py +109 -0
- spry_core-0.1.0/tests/test_auth.py +71 -0
- spry_core-0.1.0/tests/test_auth_advanced.py +109 -0
- spry_core-0.1.0/tests/test_auto_discovery.py +86 -0
- spry_core-0.1.0/tests/test_cli.py +41 -0
- spry_core-0.1.0/tests/test_config.py +81 -0
- spry_core-0.1.0/tests/test_db_backends.py +117 -0
- spry_core-0.1.0/tests/test_di.py +67 -0
- spry_core-0.1.0/tests/test_http.py +139 -0
- spry_core-0.1.0/tests/test_openapi.py +85 -0
- spry_core-0.1.0/tests/test_orm.py +67 -0
- spry_core-0.1.0/tests/test_routing.py +92 -0
- spry_core-0.1.0/tests/test_scaffold.py +23 -0
- spry_core-0.1.0/tests/test_security_middleware.py +148 -0
- spry_core-0.1.0/tests/test_validation.py +195 -0
- spry_core-0.1.0/tests/test_views.py +44 -0
- spry_core-0.1.0/tests/test_views_engine.py +171 -0
spry_core-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Spry contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
spry_core-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spry-core
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Opinionated Python web framework with an EF Core-inspired ORM
|
|
5
|
+
Author-email: Reni Dantas <reni@spry.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://spry.dev
|
|
8
|
+
Project-URL: Repository, https://github.com/anomalyco/spry
|
|
9
|
+
Project-URL: Documentation, https://spry.dev/docs
|
|
10
|
+
Project-URL: Changelog, https://github.com/anomalyco/spry/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: web,framework,orm,api,mvc,wsgi,asgi,aspnet-core-inspired,python-web
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
19
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Provides-Extra: postgres
|
|
25
|
+
Requires-Dist: psycopg2-binary; extra == "postgres"
|
|
26
|
+
Provides-Extra: mysql
|
|
27
|
+
Requires-Dist: pymysql; extra == "mysql"
|
|
28
|
+
Provides-Extra: mariadb
|
|
29
|
+
Requires-Dist: pymysql; extra == "mariadb"
|
|
30
|
+
Provides-Extra: sqlserver
|
|
31
|
+
Requires-Dist: pyodbc; extra == "sqlserver"
|
|
32
|
+
Provides-Extra: jinja2
|
|
33
|
+
Requires-Dist: jinja2>=3.0; extra == "jinja2"
|
|
34
|
+
Provides-Extra: all
|
|
35
|
+
Requires-Dist: psycopg2-binary; extra == "all"
|
|
36
|
+
Requires-Dist: pymysql; extra == "all"
|
|
37
|
+
Requires-Dist: pyodbc; extra == "all"
|
|
38
|
+
Requires-Dist: jinja2>=3.0; extra == "all"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# Spry
|
|
42
|
+
|
|
43
|
+
Spry é um framework Python opinado para quem quer sair do boilerplate rápido sem cair em muita magia.
|
|
44
|
+
|
|
45
|
+
Ele pega algumas ideias do ASP.NET Core e adapta para um fluxo mais pythonic:
|
|
46
|
+
|
|
47
|
+
- `AppBuilder` para bootstrap, configuração e DI
|
|
48
|
+
- Descoberta automática de controllers no pacote da aplicação
|
|
49
|
+
- `ControllerBase` para API e `Controller` para MVC
|
|
50
|
+
- `DbContext` e `DbSet` inspirados no EF Core
|
|
51
|
+
- Middleware por pipeline
|
|
52
|
+
- Validação de payload com resposta `422`
|
|
53
|
+
- Suporte WSGI e ASGI no mesmo app
|
|
54
|
+
- Scaffold de projeto com templates `api` e `mvc`
|
|
55
|
+
- CLI para `new`, `run`, `watch`, `migrate` e `seed`
|
|
56
|
+
|
|
57
|
+
## Requirements
|
|
58
|
+
|
|
59
|
+
- Python `3.11+`
|
|
60
|
+
- `pip`
|
|
61
|
+
|
|
62
|
+
## Quick start
|
|
63
|
+
|
|
64
|
+
Instale o framework localmente:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install -e .
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Crie uma API:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
spry new taskboard
|
|
74
|
+
cd taskboard
|
|
75
|
+
spry run --app taskboard.app:create_app
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Crie um projeto MVC:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
spry new backoffice --template mvc
|
|
82
|
+
cd backoffice
|
|
83
|
+
spry run --app backoffice.app:create_app
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Hot reload
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
spry watch --app taskboard.app:create_app
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## First manual app
|
|
93
|
+
|
|
94
|
+
O menor exemplo útil com Spry hoje:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from dataclasses import dataclass
|
|
98
|
+
|
|
99
|
+
from spry import AppBuilder, ControllerBase, DbContext, controller, dbset, get, key, post
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@dataclass(slots=True)
|
|
103
|
+
class Todo:
|
|
104
|
+
id: int | None = key()
|
|
105
|
+
title: str = ""
|
|
106
|
+
done: bool = False
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class AppDbContext(DbContext):
|
|
110
|
+
todos = dbset(Todo)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@controller("/todos")
|
|
114
|
+
class TodosController(ControllerBase):
|
|
115
|
+
def __init__(self, db: AppDbContext) -> None:
|
|
116
|
+
self.db = db
|
|
117
|
+
|
|
118
|
+
@get("/")
|
|
119
|
+
def list(self):
|
|
120
|
+
return self.db.todos.all()
|
|
121
|
+
|
|
122
|
+
@post("/")
|
|
123
|
+
def create(self, todo: Todo):
|
|
124
|
+
self.db.todos.add(todo)
|
|
125
|
+
self.db.save_changes()
|
|
126
|
+
return self.created(f"/todos/{todo.id}", todo)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
builder = AppBuilder()
|
|
130
|
+
builder.add_db_context(AppDbContext)
|
|
131
|
+
app = builder.build()
|
|
132
|
+
app.run()
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Você não precisa registrar controllers manualmente. O `AppBuilder` descobre automaticamente classes decoradas com `@controller` no pacote da aplicação.
|
|
136
|
+
|
|
137
|
+
## API vs MVC
|
|
138
|
+
|
|
139
|
+
Use `ControllerBase` quando:
|
|
140
|
+
|
|
141
|
+
- O retorno principal é JSON
|
|
142
|
+
- O app é uma API
|
|
143
|
+
- Você quer helpers como `self.created()`, `self.not_found()` e `self.no_content()`
|
|
144
|
+
|
|
145
|
+
Use `Controller` quando:
|
|
146
|
+
|
|
147
|
+
- O app serve HTML
|
|
148
|
+
- Você quer `self.view(...)`, `self.partial_view(...)` e `self.redirect(...)`
|
|
149
|
+
- O projeto segue MVC server-side
|
|
150
|
+
|
|
151
|
+
## Creating a project
|
|
152
|
+
|
|
153
|
+
### Templates
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
spry new taskboard # template api (padrão)
|
|
157
|
+
spry new backoffice --template mvc
|
|
158
|
+
spry new inventory --output ./projetos
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Template `api`:
|
|
162
|
+
|
|
163
|
+
- `main.py` — entrypoint para desenvolvimento
|
|
164
|
+
- `appsettings.json` — host, porta e configuração de banco
|
|
165
|
+
- `src/<app>/app.py` — composição do `AppBuilder`
|
|
166
|
+
- `src/<app>/controllers.py` — controllers HTTP
|
|
167
|
+
- `src/<app>/data.py` — entidades e `DbContext`
|
|
168
|
+
- `src/<app>/seed.py` — carga inicial de dados
|
|
169
|
+
|
|
170
|
+
Template `mvc`:
|
|
171
|
+
|
|
172
|
+
- Tudo do template `api`
|
|
173
|
+
- `views/` — layouts, páginas e partials
|
|
174
|
+
- `static/site.css` — estilos da interface
|
|
175
|
+
|
|
176
|
+
### Conventions the framework assumes
|
|
177
|
+
|
|
178
|
+
- Controllers são classes decoradas com `@controller`
|
|
179
|
+
- A descoberta automática olha para o pacote da aplicação
|
|
180
|
+
- `DbContext` é tipicamente registrado com `builder.add_db_context(...)`
|
|
181
|
+
- Para MVC, views ficam em arquivos dentro de `views/`
|
|
182
|
+
- Middlewares devem ser pequenos e focados em preocupações transversais
|
|
183
|
+
|
|
184
|
+
## CLI reference
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
spry new <nome> [--template api|mvc] [--output <pasta>]
|
|
188
|
+
spry run --app modulo:factory [--host 127.0.0.1] [--port 8000]
|
|
189
|
+
spry watch --app modulo:factory [--path extra]
|
|
190
|
+
spry migrate add <nome> --context modulo:DbContext [--output migrations]
|
|
191
|
+
spry migrate apply --database app.db [--input migrations]
|
|
192
|
+
spry seed --entry modulo:funcao [--context modulo:DbContext] [--database app.db]
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Database, migrations and seed
|
|
196
|
+
|
|
197
|
+
Gerar SQL inicial a partir do `DbContext`:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
spry migrate add initial --context taskboard.data:AppDbContext
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Aplicar migrações:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
spry migrate apply --database taskboard.db
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Executar seed:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
spry seed --entry taskboard.seed:seed --context taskboard.data:AppDbContext --database taskboard.db
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Fluxo completo local:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
spry migrate add initial --context taskboard.data:AppDbContext
|
|
219
|
+
spry migrate apply --database taskboard.db
|
|
220
|
+
spry seed --entry taskboard.seed:seed --context taskboard.data:AppDbContext --database taskboard.db
|
|
221
|
+
spry run --app taskboard.app:create_app
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Production
|
|
225
|
+
|
|
226
|
+
### WSGI server (recommended)
|
|
227
|
+
|
|
228
|
+
A `Application` do Spry é um callable WSGI compatível com qualquer servidor WSGI.
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Gunicorn
|
|
232
|
+
pip install gunicorn
|
|
233
|
+
gunicorn taskboard.app:create_app -w 4 -b 0.0.0.0:8000
|
|
234
|
+
|
|
235
|
+
# Waitress (Windows-friendly)
|
|
236
|
+
pip install waitress
|
|
237
|
+
waitress-serve taskboard.app:create_app
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### ASGI server
|
|
241
|
+
|
|
242
|
+
Para ambientes que requerem async, Spry também é um callable ASGI válido.
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Uvicorn
|
|
246
|
+
pip install uvicorn
|
|
247
|
+
uvicorn taskboard.app:create_app --host 0.0.0.0 --port 8000 --workers 4
|
|
248
|
+
|
|
249
|
+
# Hypercorn
|
|
250
|
+
pip install hypercorn
|
|
251
|
+
hypercorn taskboard.app:create_app --bind 0.0.0.0:8000 --workers 4
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Health check
|
|
255
|
+
|
|
256
|
+
Toda aplicação Spry expõe automaticamente `GET /health`:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
curl http://localhost:8000/health
|
|
260
|
+
# {"status":"ok","version":"0.1.0","uptime_seconds":42}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### CORS
|
|
264
|
+
|
|
265
|
+
Para consumir a API de um browser SPA, configure CORS:
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
builder.add_cors(origins=["https://meuapp.com"])
|
|
269
|
+
# ou para desenvolvimento:
|
|
270
|
+
builder.add_cors(origins=["*"], credentials=False)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Security
|
|
274
|
+
|
|
275
|
+
**Secret key:** A configuração `auth.secret_key` é obrigatória em produção. Não use o valor padrão:
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{
|
|
279
|
+
"auth": {
|
|
280
|
+
"secret_key": "substitua-por-uma-chave-forte-aqui",
|
|
281
|
+
"cookie_name": "meuapp_auth"
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Request body limit:** O padrão é 10 MB. Ajuste conforme necessário:
|
|
287
|
+
|
|
288
|
+
```python
|
|
289
|
+
builder.set_max_body_size(50 * 1024 * 1024) # 50 MB
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**Debug mode:** Em produção, desative o debug para não vazar stack traces:
|
|
293
|
+
|
|
294
|
+
```json
|
|
295
|
+
{ "server": { "debug": false } }
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Ou programaticamente:
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
builder.set_debug(False)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Environment config
|
|
305
|
+
|
|
306
|
+
O Spry carrega `appsettings.json` e sobrescreve com variáveis de ambiente prefixadas com `APP__`:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
APP__database__url=postgresql://usuario:senha@host/db spry run --app app:create_app
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Troubleshooting
|
|
313
|
+
|
|
314
|
+
### ModuleNotFoundError ao rodar um projeto gerado
|
|
315
|
+
|
|
316
|
+
Normalmente acontece por um destes motivos:
|
|
317
|
+
|
|
318
|
+
- Você está rodando fora da pasta do projeto e o `PYTHONPATH` não inclui o `src` correto
|
|
319
|
+
- O `--app` não bate com o nome do pacote gerado
|
|
320
|
+
|
|
321
|
+
Exemplo correto:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
spry run --app taskboard.app:create_app
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Se estiver trabalhando com o framework e o app lado a lado:
|
|
328
|
+
|
|
329
|
+
```powershell
|
|
330
|
+
$env:PYTHONPATH="$PSScriptRoot\..\src;$PSScriptRoot\taskboard\src"
|
|
331
|
+
python -m spry.cli run --app taskboard.app:create_app
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Controller não responde rota
|
|
335
|
+
|
|
336
|
+
Checklist:
|
|
337
|
+
|
|
338
|
+
- A classe tem `@controller("/prefixo")`
|
|
339
|
+
- O método tem `@get`, `@post`, `@put`, `@patch` ou `@delete`
|
|
340
|
+
- O controller está dentro do pacote da aplicação
|
|
341
|
+
- A rota chamada bate com o prefixo + método
|
|
342
|
+
|
|
343
|
+
### Payload retorna 422
|
|
344
|
+
|
|
345
|
+
Isso significa que o binding do payload para a dataclass falhou.
|
|
346
|
+
|
|
347
|
+
Cheque:
|
|
348
|
+
|
|
349
|
+
- Campos obrigatórios ausentes
|
|
350
|
+
- Tipos inválidos
|
|
351
|
+
- Nomes de propriedades divergentes do DTO esperado
|
|
352
|
+
|
|
353
|
+
### MVC não encontra view
|
|
354
|
+
|
|
355
|
+
Cheque:
|
|
356
|
+
|
|
357
|
+
- Se `builder.add_views(...)` foi chamado
|
|
358
|
+
- Se os arquivos existem dentro da pasta `views/`
|
|
359
|
+
- Se o nome passado em `self.view("home/index")` bate com `views/home/index.html`
|
|
360
|
+
|
|
361
|
+
## Contributing and branch strategy
|
|
362
|
+
|
|
363
|
+
Contribuições são bem-vindas! Leia o [`CONTRIBUTING.md`](CONTRIBUTING.md) para setup, estilo de código e processo de PR.
|
|
364
|
+
|
|
365
|
+
### Branch naming
|
|
366
|
+
|
|
367
|
+
| Branch | Base | Merge para | Descrição |
|
|
368
|
+
|--------|------|------------|-----------|
|
|
369
|
+
| `feat/*` | `main` | `main` via PR | Nova funcionalidade |
|
|
370
|
+
| `fix/*` | `main` | `main` via PR | Correção de bug |
|
|
371
|
+
| `docs/*` | `main` | `main` via PR | Documentação |
|
|
372
|
+
| `chore/*` | `main` | `main` via PR | Manutenção (CI, dependências) |
|
|
373
|
+
|
|
374
|
+
### Release flow
|
|
375
|
+
|
|
376
|
+
1. Crie uma branch `release/vX.Y.Z` a partir de `main`
|
|
377
|
+
2. Ajuste versão e changelog
|
|
378
|
+
3. Merge para `main` e crie uma tag `vX.Y.Z`
|
|
379
|
+
4. O GitHub Release é criado a partir da tag
|
|
380
|
+
|
|
381
|
+
### CI
|
|
382
|
+
|
|
383
|
+
O workflow de CI roda em todos os PRs para `main` com Python 3.11, 3.12 e 3.13 em Linux, Windows e macOS.
|
|
384
|
+
|
|
385
|
+
## Repository structure
|
|
386
|
+
|
|
387
|
+
- `src/spry` — núcleo do framework
|
|
388
|
+
- `src/spry/templates/api` — template de API
|
|
389
|
+
- `src/spry/templates/mvc` — template MVC server-side
|
|
390
|
+
- `examples/taskboard` — exemplo de API usando o framework
|
|
391
|
+
- `docs` — site de documentação do framework
|
|
392
|
+
- `tests` — suite de testes
|
|
393
|
+
|
|
394
|
+
## Developing locally
|
|
395
|
+
|
|
396
|
+
Instale em modo editável:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
pip install -e .
|
|
400
|
+
pip install -e ".[all]" # dependências opcionais
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Rodando os exemplos
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
pip install -e .
|
|
407
|
+
cd examples/taskboard
|
|
408
|
+
spy run --app taskboard.app:create_app
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Rodando os testes
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
python -m unittest discover -s tests
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Documentação local
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
cd docs
|
|
421
|
+
spry run --app spry_docs.app:create_app --host 127.0.0.1 --port 8010
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Documentation site
|
|
425
|
+
|
|
426
|
+
O site de documentação fica em `docs/` e cobre guias mais visuais e organizados por assunto.
|