fluxpy-framework 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.
- fluxpy_framework-0.1.0/CODE_OF_CONDUCT.md +30 -0
- fluxpy_framework-0.1.0/CONTRIBUTING.md +111 -0
- fluxpy_framework-0.1.0/LICENSE +21 -0
- fluxpy_framework-0.1.0/MANIFEST.in +8 -0
- fluxpy_framework-0.1.0/PKG-INFO +364 -0
- fluxpy_framework-0.1.0/README.md +328 -0
- fluxpy_framework-0.1.0/docs/architecture.md +256 -0
- fluxpy_framework-0.1.0/docs/getting_started.md +326 -0
- fluxpy_framework-0.1.0/docs/internals.md +258 -0
- fluxpy_framework-0.1.0/examples/example_app.py +234 -0
- fluxpy_framework-0.1.0/examples/fullstack_app.py +250 -0
- fluxpy_framework-0.1.0/examples/taskflow_demo.py +1238 -0
- fluxpy_framework-0.1.0/flux/__init__.py +54 -0
- fluxpy_framework-0.1.0/flux/__main__.py +4 -0
- fluxpy_framework-0.1.0/flux/auth/__init__.py +14 -0
- fluxpy_framework-0.1.0/flux/auth/auth.py +332 -0
- fluxpy_framework-0.1.0/flux/benchmarking.py +290 -0
- fluxpy_framework-0.1.0/flux/cli.py +199 -0
- fluxpy_framework-0.1.0/flux/client/__init__.py +16 -0
- fluxpy_framework-0.1.0/flux/client/client.py +165 -0
- fluxpy_framework-0.1.0/flux/client/response.py +104 -0
- fluxpy_framework-0.1.0/flux/client/retry.py +80 -0
- fluxpy_framework-0.1.0/flux/client/session.py +315 -0
- fluxpy_framework-0.1.0/flux/config/__init__.py +4 -0
- fluxpy_framework-0.1.0/flux/config/settings.py +189 -0
- fluxpy_framework-0.1.0/flux/core/__init__.py +36 -0
- fluxpy_framework-0.1.0/flux/core/connection.py +214 -0
- fluxpy_framework-0.1.0/flux/core/headers.py +147 -0
- fluxpy_framework-0.1.0/flux/core/json.py +84 -0
- fluxpy_framework-0.1.0/flux/core/parser.py +388 -0
- fluxpy_framework-0.1.0/flux/core/pool.py +209 -0
- fluxpy_framework-0.1.0/flux/core/streaming.py +168 -0
- fluxpy_framework-0.1.0/flux/observability/__init__.py +18 -0
- fluxpy_framework-0.1.0/flux/observability/metrics.py +257 -0
- fluxpy_framework-0.1.0/flux/openapi/__init__.py +4 -0
- fluxpy_framework-0.1.0/flux/openapi/generator.py +215 -0
- fluxpy_framework-0.1.0/flux/orm/__init__.py +13 -0
- fluxpy_framework-0.1.0/flux/orm/migrations.py +112 -0
- fluxpy_framework-0.1.0/flux/orm/model.py +517 -0
- fluxpy_framework-0.1.0/flux/plugins/__init__.py +10 -0
- fluxpy_framework-0.1.0/flux/plugins/plugin.py +194 -0
- fluxpy_framework-0.1.0/flux/py.typed +0 -0
- fluxpy_framework-0.1.0/flux/scaffold.py +285 -0
- fluxpy_framework-0.1.0/flux/schema/__init__.py +4 -0
- fluxpy_framework-0.1.0/flux/schema/schema.py +404 -0
- fluxpy_framework-0.1.0/flux/security/__init__.py +20 -0
- fluxpy_framework-0.1.0/flux/security/security.py +254 -0
- fluxpy_framework-0.1.0/flux/server/__init__.py +39 -0
- fluxpy_framework-0.1.0/flux/server/app.py +319 -0
- fluxpy_framework-0.1.0/flux/server/context.py +62 -0
- fluxpy_framework-0.1.0/flux/server/di.py +191 -0
- fluxpy_framework-0.1.0/flux/server/middleware.py +153 -0
- fluxpy_framework-0.1.0/flux/server/request.py +180 -0
- fluxpy_framework-0.1.0/flux/server/response.py +281 -0
- fluxpy_framework-0.1.0/flux/server/router.py +163 -0
- fluxpy_framework-0.1.0/flux/tasks/__init__.py +4 -0
- fluxpy_framework-0.1.0/flux/tasks/queue.py +262 -0
- fluxpy_framework-0.1.0/flux/templates/__init__.py +15 -0
- fluxpy_framework-0.1.0/flux/templates/engine.py +184 -0
- fluxpy_framework-0.1.0/flux/websocket/__init__.py +4 -0
- fluxpy_framework-0.1.0/flux/websocket/websocket.py +258 -0
- fluxpy_framework-0.1.0/fluxpy_framework.egg-info/PKG-INFO +364 -0
- fluxpy_framework-0.1.0/fluxpy_framework.egg-info/SOURCES.txt +75 -0
- fluxpy_framework-0.1.0/fluxpy_framework.egg-info/dependency_links.txt +1 -0
- fluxpy_framework-0.1.0/fluxpy_framework.egg-info/entry_points.txt +3 -0
- fluxpy_framework-0.1.0/fluxpy_framework.egg-info/requires.txt +16 -0
- fluxpy_framework-0.1.0/fluxpy_framework.egg-info/top_level.txt +1 -0
- fluxpy_framework-0.1.0/pyproject.toml +61 -0
- fluxpy_framework-0.1.0/setup.cfg +7 -0
- fluxpy_framework-0.1.0/tests/test_auth.py +74 -0
- fluxpy_framework-0.1.0/tests/test_integration.py +184 -0
- fluxpy_framework-0.1.0/tests/test_middleware.py +88 -0
- fluxpy_framework-0.1.0/tests/test_orm.py +140 -0
- fluxpy_framework-0.1.0/tests/test_parser.py +70 -0
- fluxpy_framework-0.1.0/tests/test_router.py +79 -0
- fluxpy_framework-0.1.0/tests/test_schema.py +100 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We are committed to making participation in this project a welcoming experience for everyone, regardless of background, experience level, gender, identity, nationality, ethnicity, religion, or any other personal characteristic.
|
|
6
|
+
|
|
7
|
+
## Our Standards
|
|
8
|
+
|
|
9
|
+
**Positive behaviour includes:**
|
|
10
|
+
|
|
11
|
+
- Using welcoming and inclusive language
|
|
12
|
+
- Being respectful of differing viewpoints and experience
|
|
13
|
+
- Gracefully accepting constructive feedback
|
|
14
|
+
- Focusing on what is best for the community
|
|
15
|
+
- Showing empathy toward other community members
|
|
16
|
+
|
|
17
|
+
**Unacceptable behaviour includes:**
|
|
18
|
+
|
|
19
|
+
- Harassment or discriminatory language of any kind
|
|
20
|
+
- Personal attacks or insults
|
|
21
|
+
- Trolling or deliberately disruptive behaviour
|
|
22
|
+
- Publishing others' private information without permission
|
|
23
|
+
|
|
24
|
+
## Enforcement
|
|
25
|
+
|
|
26
|
+
Instances of unacceptable behaviour may be reported by opening a private issue or contacting the maintainers directly. All reports will be reviewed and addressed promptly.
|
|
27
|
+
|
|
28
|
+
## Attribution
|
|
29
|
+
|
|
30
|
+
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Contributing to FluxPy
|
|
2
|
+
|
|
3
|
+
Thanks for your interest! FluxPy is primarily a learning and exploration project, but thoughtful contributions are very welcome.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What We're Looking For
|
|
8
|
+
|
|
9
|
+
- **Bug fixes** — especially in the HTTP parser, router, ORM, or DI system
|
|
10
|
+
- **Performance improvements** — with benchmarks showing the difference
|
|
11
|
+
- **New layers** — following the pattern of existing layers (zero mandatory deps)
|
|
12
|
+
- **Tests** — more coverage is always welcome
|
|
13
|
+
- **Documentation** — clarifications, examples, or new guides
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Getting Started
|
|
18
|
+
|
|
19
|
+
**1. Fork and clone**
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
git clone https://github.com/sidx0/fluxpy
|
|
23
|
+
cd fluxpy
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**2. Set up a dev environment**
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python -m venv venv
|
|
30
|
+
source venv/bin/activate # Windows: venv\Scripts\activate
|
|
31
|
+
pip install -e ".[dev]"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**3. Run the tests**
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pytest tests/ -v
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**4. Run one of the examples to confirm everything works**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
python examples/example_app.py
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Making Changes
|
|
49
|
+
|
|
50
|
+
**Create a branch**
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
git checkout -b fix/parser-edge-case
|
|
54
|
+
# or
|
|
55
|
+
git checkout -b feature/http2-support
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Write tests** — tests live in `tests/`. Use `pytest-asyncio` for async tests:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
import pytest
|
|
62
|
+
from flux import Flux
|
|
63
|
+
|
|
64
|
+
@pytest.mark.asyncio
|
|
65
|
+
async def test_my_feature():
|
|
66
|
+
app = Flux()
|
|
67
|
+
...
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Keep the zero-dependency principle** — the core framework and all built-in layers must work with Python stdlib only. Optional dependencies (PyJWT, Jinja2) are fine as opt-in extras in `pyproject.toml`.
|
|
71
|
+
|
|
72
|
+
**Run tests**
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
pytest tests/ -v
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Pull Request Checklist
|
|
81
|
+
|
|
82
|
+
- [ ] Tests pass (`pytest tests/`)
|
|
83
|
+
- [ ] New behaviour has test coverage
|
|
84
|
+
- [ ] No new mandatory dependencies added
|
|
85
|
+
- [ ] Code follows existing style (type hints, async/await, docstrings)
|
|
86
|
+
- [ ] PR description explains what changed and why
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Code Style
|
|
91
|
+
|
|
92
|
+
- Type hints everywhere (Python 3.10+ syntax — `str | None` not `Optional[str]`)
|
|
93
|
+
- `async def` for anything that does I/O
|
|
94
|
+
- Docstrings on public-facing classes and functions
|
|
95
|
+
- Keep modules small and focused
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Reporting Bugs
|
|
100
|
+
|
|
101
|
+
Open an issue with:
|
|
102
|
+
- FluxPy version (`fluxpy version`)
|
|
103
|
+
- Python version and OS
|
|
104
|
+
- Minimal reproducible example
|
|
105
|
+
- Full traceback
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Questions
|
|
110
|
+
|
|
111
|
+
Open a GitHub Discussion or issue — happy to help.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Flux 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.
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fluxpy_framework
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A zero-dependency async Python web framework
|
|
5
|
+
Project-URL: Homepage, https://github.com/sidx0/fluxpy
|
|
6
|
+
Project-URL: Repository, https://github.com/sidx0/fluxpy
|
|
7
|
+
Project-URL: Documentation, https://github.com/sidx0/fluxpy/tree/main/docs
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/sidx0/fluxpy/issues
|
|
9
|
+
Keywords: web,framework,asyncio,http,async,backend
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Framework :: AsyncIO
|
|
19
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
21
|
+
Classifier: Operating System :: OS Independent
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
Provides-Extra: jwt
|
|
25
|
+
Requires-Dist: PyJWT>=2.8; extra == "jwt"
|
|
26
|
+
Provides-Extra: templates
|
|
27
|
+
Requires-Dist: Jinja2>=3.1; extra == "templates"
|
|
28
|
+
Provides-Extra: all
|
|
29
|
+
Requires-Dist: PyJWT>=2.8; extra == "all"
|
|
30
|
+
Requires-Dist: Jinja2>=3.1; extra == "all"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.4; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
34
|
+
Requires-Dist: PyJWT>=2.8; extra == "dev"
|
|
35
|
+
Requires-Dist: Jinja2>=3.1; extra == "dev"
|
|
36
|
+
|
|
37
|
+
<div align="center">
|
|
38
|
+
|
|
39
|
+
# ⚡ FluxPy
|
|
40
|
+
|
|
41
|
+
**A zero-dependency async Python web framework built from scratch**
|
|
42
|
+
*No Starlette. No Pydantic. No Uvicorn. Just Python.*
|
|
43
|
+
|
|
44
|
+
[](https://python.org)
|
|
45
|
+
[](LICENSE)
|
|
46
|
+
[](pyproject.toml)
|
|
47
|
+
[](flux/core/)
|
|
48
|
+
[](https://github.com/sidx0/fluxpy/actions/workflows/tests.yml)
|
|
49
|
+
[](https://pypi.org/project/fluxpy/)
|
|
50
|
+
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
FluxPy is an experimental async Python web framework that implements the **entire HTTP stack from scratch** — HTTP parser, header container, connection pool, router, middleware pipeline, DI engine, ORM, auth, WebSocket, and more — using only Python's standard library.
|
|
56
|
+
|
|
57
|
+
The goal: make every layer inspectable and educational while staying fast enough to be interesting. The loopback client bypasses TCP entirely for same-process calls, hitting **124,000 requests/sec** on raw dispatch. No Gunicorn required — FluxPy hosts itself.
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from flux import Flux
|
|
61
|
+
|
|
62
|
+
app = Flux()
|
|
63
|
+
|
|
64
|
+
@app.get("/")
|
|
65
|
+
async def hello():
|
|
66
|
+
return {"message": "⚡ Hello from FluxPy"}
|
|
67
|
+
|
|
68
|
+
app.run(port=8000)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install fluxpy
|
|
73
|
+
flux new myproject
|
|
74
|
+
cd myproject && python main.py
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Why FluxPy Exists
|
|
80
|
+
|
|
81
|
+
Most Python frameworks sit on top of ASGI servers (Uvicorn, Hypercorn) and shared libraries (Starlette, Pydantic). That's right for production — but it makes it hard to understand what's actually happening at the HTTP level.
|
|
82
|
+
|
|
83
|
+
FluxPy implements the entire stack from scratch. Every layer is readable, benchmarkable, and hackable. It's also fast: **12× faster than Flask** on in-process dispatch, **31× faster** on URL routing.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Features
|
|
88
|
+
|
|
89
|
+
### Core Engine
|
|
90
|
+
- **HTTP/1.1 parser** — `memoryview` slices for zero-copy header parsing
|
|
91
|
+
- **Compiled regex router** — typed path params (`{id:int}`, `{slug:str}`, `{uid:uuid}`)
|
|
92
|
+
- **Async connection pool** — keep-alive, idle reaping, per-host semaphores
|
|
93
|
+
- **Loopback client** — same-process calls skip TCP/serialise entirely (~23× faster)
|
|
94
|
+
- **Non-recursive middleware pipeline** — safe for any chain depth
|
|
95
|
+
|
|
96
|
+
### Full-Stack Layers (zero mandatory dependencies)
|
|
97
|
+
|
|
98
|
+
| Layer | What it gives you |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `flux.orm` | Async SQLite ORM — `Model`, `QuerySet`, auto-migrations, transactions |
|
|
101
|
+
| `flux.auth` | JWT tokens, PBKDF2 passwords, `@requires_auth`, `@requires_role` |
|
|
102
|
+
| `flux.schema` | Pydantic-style validation auto-injected via DI; `422` on bad input |
|
|
103
|
+
| `flux.openapi` | Auto-generated OpenAPI 3.0; Swagger UI at `/docs`; ReDoc at `/redoc` |
|
|
104
|
+
| `flux.websocket` | RFC 6455 WebSocket — `@app.websocket()`, fragmented frame support |
|
|
105
|
+
| `flux.tasks` | Async priority task queue, retry with backoff, DI-injectable |
|
|
106
|
+
| `flux.observability` | Prometheus counters & histograms, structured logging, `/metrics` |
|
|
107
|
+
| `flux.config` | Type-annotated `Settings` — reads `.env` + env vars with coercion |
|
|
108
|
+
| `flux.security` | Token-bucket rate limiter, CSRF, security headers, `sanitize_html()` |
|
|
109
|
+
| `flux.templates` | Jinja2 integration + built-in stdlib fallback engine |
|
|
110
|
+
| `flux.plugins` | Plugin lifecycle — `on_install` / `on_startup` / `on_shutdown` |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Quick Start
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pip install fluxpy
|
|
118
|
+
flux new myproject
|
|
119
|
+
cd myproject
|
|
120
|
+
python main.py
|
|
121
|
+
# Open http://localhost:8000
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Or clone and run the full TaskFlow demo (task manager with auth, ORM, background jobs, live UI):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
git clone https://github.com/sidx0/fluxpy
|
|
128
|
+
cd fluxpy
|
|
129
|
+
python examples/taskflow_demo.py
|
|
130
|
+
# Open http://localhost:8000 → login: admin / admin123
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Examples
|
|
136
|
+
|
|
137
|
+
### Typed path parameters + DI
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from flux import Flux, JSONResponse
|
|
141
|
+
from flux.auth import AuthConfig, AuthUser, requires_auth
|
|
142
|
+
|
|
143
|
+
app = Flux()
|
|
144
|
+
app.auth = AuthConfig(secret="my-secret")
|
|
145
|
+
|
|
146
|
+
@app.get("/users/{id:int}")
|
|
147
|
+
async def get_user(id: int):
|
|
148
|
+
return {"id": id}
|
|
149
|
+
|
|
150
|
+
@app.get("/me")
|
|
151
|
+
@requires_auth
|
|
152
|
+
async def me(user: AuthUser):
|
|
153
|
+
return {"id": user.id, "username": user.username}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Schema validation (auto-422)
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from flux.schema import Schema, Field
|
|
160
|
+
|
|
161
|
+
class CreatePost(Schema):
|
|
162
|
+
title: str = Field(min_length=1, max_length=200)
|
|
163
|
+
body: str = Field(default="")
|
|
164
|
+
priority: int = Field(default=1, min_value=1, max_value=5)
|
|
165
|
+
|
|
166
|
+
@app.post("/posts")
|
|
167
|
+
async def create(data: CreatePost): # body auto-parsed + validated
|
|
168
|
+
return {"title": data.title} # 422 returned if invalid
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### ORM
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from flux.orm import Database, Model, Integer, String, auto_migrate
|
|
175
|
+
|
|
176
|
+
db = Database("sqlite:///app.db")
|
|
177
|
+
|
|
178
|
+
class Post(Model):
|
|
179
|
+
id = Integer(primary_key=True)
|
|
180
|
+
title = String(nullable=False)
|
|
181
|
+
status = String(default="draft")
|
|
182
|
+
|
|
183
|
+
Post.bind(db)
|
|
184
|
+
|
|
185
|
+
@app.on_startup
|
|
186
|
+
async def startup():
|
|
187
|
+
await auto_migrate(Post)
|
|
188
|
+
|
|
189
|
+
# In handlers:
|
|
190
|
+
post = await Post.create(title="Hello FluxPy")
|
|
191
|
+
posts = await Post.filter(status="draft").order_by("-id").limit(10).all()
|
|
192
|
+
count = await Post.all().count()
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Background tasks
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from flux.tasks import TaskQueue
|
|
199
|
+
|
|
200
|
+
tq = TaskQueue(workers=4)
|
|
201
|
+
app.di.register(TaskQueue, lambda: tq)
|
|
202
|
+
|
|
203
|
+
@app.on_startup
|
|
204
|
+
async def startup():
|
|
205
|
+
await tq.start()
|
|
206
|
+
|
|
207
|
+
@app.post("/register")
|
|
208
|
+
async def register(data: RegInput, tq: TaskQueue):
|
|
209
|
+
user = await User.create(...)
|
|
210
|
+
await tq.enqueue(send_welcome_email, user.email)
|
|
211
|
+
return JSONResponse(user.to_dict(), status_code=201)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### WebSocket
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from flux.websocket import WebSocket, WebSocketDisconnect
|
|
218
|
+
|
|
219
|
+
@app.websocket("/ws/chat")
|
|
220
|
+
async def chat(ws: WebSocket):
|
|
221
|
+
await ws.accept()
|
|
222
|
+
try:
|
|
223
|
+
while True:
|
|
224
|
+
msg = await ws.receive_text()
|
|
225
|
+
await ws.send_json({"echo": msg})
|
|
226
|
+
except WebSocketDisconnect:
|
|
227
|
+
pass
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Full-stack skeleton
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
from flux import Flux
|
|
234
|
+
from flux.auth import AuthConfig
|
|
235
|
+
from flux.plugins import CORSPlugin
|
|
236
|
+
from flux.observability import observability_middleware, mount_metrics
|
|
237
|
+
from flux.security import RateLimiter, security_headers_middleware
|
|
238
|
+
|
|
239
|
+
app = Flux(title="My API", version="1.0.0")
|
|
240
|
+
app.auth = AuthConfig(secret="change-me-in-production")
|
|
241
|
+
|
|
242
|
+
app.install(CORSPlugin(allow_origins="*"))
|
|
243
|
+
app.add_middleware(observability_middleware)
|
|
244
|
+
app.add_middleware(RateLimiter(requests_per_second=100))
|
|
245
|
+
app.add_middleware(security_headers_middleware)
|
|
246
|
+
mount_metrics(app)
|
|
247
|
+
app.mount_docs() # /docs + /redoc
|
|
248
|
+
|
|
249
|
+
app.run(port=8000)
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Benchmarks
|
|
255
|
+
|
|
256
|
+
All benchmarks run in-process (no real TCP):
|
|
257
|
+
|
|
258
|
+
| Operation | Throughput | Mean latency |
|
|
259
|
+
|---|---|---|
|
|
260
|
+
| HTTP parse — GET | 140,026/s | 7.1 µs |
|
|
261
|
+
| HTTP parse — POST + JSON | 124,527/s | 8.0 µs |
|
|
262
|
+
| Route match (cache hit) | 986,564/s | 1.0 µs |
|
|
263
|
+
| JSONResponse build | 222,480/s | 4.5 µs |
|
|
264
|
+
| **Full loopback dispatch** | **39,171/s** | **25.5 µs** |
|
|
265
|
+
|
|
266
|
+
**vs Flask** (in-process, same machine):
|
|
267
|
+
|
|
268
|
+
| Metric | Flask | FluxPy | Speedup |
|
|
269
|
+
|---|---|---|---|
|
|
270
|
+
| GET dispatch | 5,831/s | 70,142/s | **12×** |
|
|
271
|
+
| URL routing | 206,654/s | 6,367,537/s | **31×** |
|
|
272
|
+
| Memory/request | 12 KB | 4 KB | **3× less** |
|
|
273
|
+
| Import time | 255 ms | 16 ms | **16× faster** |
|
|
274
|
+
|
|
275
|
+
Run the benchmarks yourself:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
python -m flux benchmark
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## CLI
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
fluxpy new myapp # scaffold a complete project
|
|
287
|
+
fluxpy run myapp:app # start the dev server
|
|
288
|
+
fluxpy run myapp:app --reload # with hot reload
|
|
289
|
+
fluxpy routes myapp:app # list all registered routes
|
|
290
|
+
fluxpy version
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Project Structure
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
fluxpy/
|
|
299
|
+
├── flux/ # framework source
|
|
300
|
+
│ ├── core/ # HTTP parser, headers, connection pool
|
|
301
|
+
│ ├── server/ # router, middleware, DI, request/response
|
|
302
|
+
│ ├── client/ # async HTTP client + loopback
|
|
303
|
+
│ ├── orm/ # async SQLite ORM
|
|
304
|
+
│ ├── auth/ # JWT + PBKDF2 + RBAC
|
|
305
|
+
│ ├── schema/ # validation engine
|
|
306
|
+
│ ├── openapi/ # spec generator + Swagger/ReDoc
|
|
307
|
+
│ ├── websocket/ # RFC 6455 + fragmented frame support
|
|
308
|
+
│ ├── tasks/ # priority task queue
|
|
309
|
+
│ ├── observability/ # Prometheus + structured logging
|
|
310
|
+
│ ├── config/ # env-based settings
|
|
311
|
+
│ ├── security/ # rate limiting, headers, CSRF
|
|
312
|
+
│ ├── templates/ # Jinja2 + stdlib fallback
|
|
313
|
+
│ └── plugins/ # plugin lifecycle system
|
|
314
|
+
├── examples/
|
|
315
|
+
│ ├── example_app.py # minimal hello-world
|
|
316
|
+
│ ├── fullstack_app.py # all layers demonstrated
|
|
317
|
+
│ └── taskflow_demo.py # full task manager SPA
|
|
318
|
+
├── tests/ # pytest test suite (100% passing)
|
|
319
|
+
└── docs/
|
|
320
|
+
├── architecture.md # internals deep-dive
|
|
321
|
+
├── getting_started.md # tutorial from zero
|
|
322
|
+
└── internals.md # parser, DI, loopback explained
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Documentation
|
|
328
|
+
|
|
329
|
+
- [Getting Started](docs/getting_started.md) — build your first FluxPy app
|
|
330
|
+
- [Architecture](docs/architecture.md) — how the HTTP engine works
|
|
331
|
+
- [Internals](docs/internals.md) — parser, DI, loopback, JWT without PyJWT
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Requirements
|
|
336
|
+
|
|
337
|
+
- Python 3.10+
|
|
338
|
+
- No mandatory dependencies
|
|
339
|
+
- Optional: `PyJWT` (JWT tokens), `Jinja2` (templates)
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
pip install fluxpy # core only (stdlib)
|
|
343
|
+
pip install "fluxpy[jwt]" # + PyJWT
|
|
344
|
+
pip install "fluxpy[templates]" # + Jinja2
|
|
345
|
+
pip install "fluxpy[all]" # + both
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Contributing
|
|
351
|
+
|
|
352
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). Issues and PRs welcome.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## License
|
|
357
|
+
|
|
358
|
+
MIT — see [LICENSE](LICENSE).
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
<div align="center">
|
|
363
|
+
<sub>Built by <a href="https://github.com/sidx0">sidx0</a> · Python · asyncio · zero dependencies</sub>
|
|
364
|
+
</div>
|