pyrustapi 0.3.34__tar.gz → 0.3.86__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.
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/Cargo.lock +1 -1
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/Cargo.toml +1 -1
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/PKG-INFO +1 -1
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/fastapi_compatibility_and_features.md +68 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/pyproject.toml +1 -1
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/__init__.py +1 -1
- pyrustapi-0.3.86/tests/test_python_ecosystem_compatibility.py +114 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/.github/workflows/CI.yml +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/.github/workflows/pages.yml +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/.github/workflows/release.yml +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/.github/workflows/static.yml +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/.gitignore +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/LICENSE +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/README.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/ROADMAP.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmark_dashboard.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/benchmark.sh +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/fastapi_app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/fastapi_cpu_app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/fastapi_edge_app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/fastapi_oha.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/large.json +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/mixed.json +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/rustapi_app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/rustapi_cpu_app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/rustapi_edge_app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/rustapi_multiworker_app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/rustapi_oha.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/rustapi_tier3_app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/tier_app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/data/validate.json +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/run_3tier_benchmark.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/run_comparison_benchmark.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/run_cpu_stability_benchmark.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/run_edgecase_benchmark.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/run_native_tier3_benchmark.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/run_real_oha_benchmark.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks/run_release_highspeed_benchmark.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/benchmarks.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/crud_benchmark/benchmark_db.sqlite +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/crud_benchmark/benchmark_db.sqlite-shm +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/crud_benchmark/benchmark_db.sqlite-wal +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/crud_benchmark/benchmark_results.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/crud_benchmark/fastapi_crud.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/crud_benchmark/run_crud_benchmark.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/crud_benchmark/rustapi_crud.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/3tier_architecture_and_benchmarks.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/DeepAnalytics.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/api-reference.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/benchmark_dashboard.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/benchmarks.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/database.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/database_engine.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/docs.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/getting-started.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/getting_started.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/index.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/mcp-server.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/mcp_server.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/native_business_logic.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/performance_and_benchmarks.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/power_primitives.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/pyrustapi-logo (1).png +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/report_01_.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/response_types.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/security-power-modules.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/docs/swagger_ui_and_dx_deviations.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/examples/app.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/index.html +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/performance-reports/cpu_intensive_stability_report.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/performance-reports/fastapi_vs_hybrid_vs_native.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/performance-reports/fastapi_vs_rustapi_comparison.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/performance-reports/fastapi_vs_rustapi_crud_benchmark.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/performance-reports/performance_and_benchmarks.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/performance-reports/rust_native_edgecases_report.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/performance-reports/three_tier_architecture_evaluation.md +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/pyrustapi-logo.png +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/pyrustapi/__init__.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/__init__.pyi +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/background.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/depends.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/encoders.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/exceptions.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/middleware/__init__.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/middleware/cors.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/openapi/__init__.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/openapi/docs.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/param_functions.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/py.typed +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/resolver.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/responses/__init__.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/router.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/rust.rs +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/security/__init__.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/sse.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/staticfiles.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/status.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/python/rustapi/uploads.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/scratch/.gitkeep +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/src/lib.rs +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/test-reports/junit.xml +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_3tier_architecture.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_basic.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_database_engine.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_fastapi_all_6_mismatches.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_fastapi_compatibility.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_file_uploads_and_dx.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_imports.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_native_routes.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_overrides_and_coercion.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_reload_and_logging.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_response_model.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_responses_and_req_json.py +0 -0
- {pyrustapi-0.3.34 → pyrustapi-0.3.86}/tests/test_rust_power_modules.py +0 -0
|
@@ -168,4 +168,72 @@ def get_item(
|
|
|
168
168
|
# Convert dataclass/Pydantic model to JSON dict
|
|
169
169
|
user_dict = jsonable_encoder(user)
|
|
170
170
|
return {"item_id": item_id, "query": q, "user": user_dict}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 7. Python Ecosystem Compatibility Matrix
|
|
176
|
+
|
|
177
|
+
`rustapi` is built to seamlessly integrate with standard Python database, machine learning, security, and utility libraries:
|
|
178
|
+
|
|
179
|
+
| Library Domain | Package | Verified Feature & Usage | Status |
|
|
180
|
+
| :--- | :--- | :--- | :--- |
|
|
181
|
+
| **Data Validation** | `pydantic` v2 | `BaseModel`, `Field`, `validator`, `EmailStr` in route bodies | ✅ Verified |
|
|
182
|
+
| **HTTP Clients** | `httpx`, `requests` | `httpx.AsyncClient` & `requests` testing, multi-part uploads & streams | ✅ Verified |
|
|
183
|
+
| **Databases & ORMs** | `sqlite3`, `sqlalchemy` | Session context managers & query execution inside `Depends(get_db)` | ✅ Verified |
|
|
184
|
+
| **Image Processing** | `PIL` / `Pillow` | Image decoding & matrix transformations on `UploadFile` streams | ✅ Verified |
|
|
185
|
+
| **JWT & Security** | `pyjwt`, `passlib`, `argon2` | `jwt.encode`, `jwt.decode`, password hashing inside auth endpoints | ✅ Verified |
|
|
186
|
+
| **Numeric & ML** | `numpy` | `np.array` operations on request payloads & image byte arrays | ✅ Verified |
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
import io
|
|
190
|
+
import jwt
|
|
191
|
+
import numpy as np
|
|
192
|
+
from PIL import Image
|
|
193
|
+
from pydantic import BaseModel, Field
|
|
194
|
+
from rustapi import FastAPI, Request, Depends, HTTPException
|
|
195
|
+
from rustapi.uploads import UploadFile
|
|
196
|
+
|
|
197
|
+
app = FastAPI()
|
|
198
|
+
|
|
199
|
+
class AnalysisModel(BaseModel):
|
|
200
|
+
project_name: str = Field(..., min_length=2)
|
|
201
|
+
|
|
202
|
+
@app.post("/analyze")
|
|
203
|
+
async def analyze(req: Request):
|
|
204
|
+
if "photo" not in req.files:
|
|
205
|
+
raise HTTPException(status_code=400, detail="No photo uploaded")
|
|
206
|
+
|
|
207
|
+
file_obj: UploadFile = req.files["photo"][0]
|
|
208
|
+
img_bytes = await file_obj.read() # Both await file.read() and file.read() work
|
|
209
|
+
|
|
210
|
+
# Process image with Pillow & NumPy
|
|
211
|
+
image = Image.open(io.BytesIO(img_bytes)).convert("L")
|
|
212
|
+
array = np.array(image)
|
|
213
|
+
brightness = float(np.mean(array))
|
|
214
|
+
|
|
215
|
+
# Encode JWT response
|
|
216
|
+
token = jwt.encode({"brightness": brightness}, "secret", algorithm="HS256")
|
|
217
|
+
return {"status": "success", "token": token}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 8. FastAPI Migration Mismatch Resolution (v0.3.34)
|
|
223
|
+
|
|
224
|
+
The following 6 FastAPI compatibility enhancements have been resolved natively in `pyrustapi` v0.3.34:
|
|
225
|
+
|
|
226
|
+
1. **Sub-Router Nesting (`APIRouter.include_router`)**:
|
|
227
|
+
`router.include_router(sub_router, prefix="/v1", tags=["sub"])` allows sub-routers to mount additional sub-routers with inherited path prefixes and tags.
|
|
228
|
+
2. **`FastAPI` Constructor Kwargs**:
|
|
229
|
+
`FastAPI(title="My API", description="...", version="1.0.0", openapi_url="/openapi.json", docs_url="/docs", redoc_url="/redoc")` accepts all standard metadata keyword arguments without constructor errors.
|
|
230
|
+
3. **Custom Exception Handlers (`@app.exception_handler`)**:
|
|
231
|
+
Register custom status code or exception class handlers via `@app.exception_handler(CustomException)`.
|
|
232
|
+
4. **`HTTPBearer()` Credentials Container**:
|
|
233
|
+
`security = HTTPBearer()` returns `HTTPAuthorizationCredentials(scheme="Bearer", credentials="...")` when passed to `Depends(security)`.
|
|
234
|
+
5. **Recursive Dependency Injection (`solve_dependency`)**:
|
|
235
|
+
Injects `request: Request` / `req` parameters automatically and recursively resolves nested `Depends(sub_dep)` calls.
|
|
236
|
+
6. **Dual Async / Sync `UploadFile` Methods**:
|
|
237
|
+
`UploadFile` methods (`file.read()`, `file.seek()`, `file.close()`) support both asynchronous (`await file.read()`) and synchronous (`file.read()`) execution, plus `.file` returns `io.BytesIO`.
|
|
238
|
+
|
|
171
239
|
```
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import sqlite3
|
|
3
|
+
import threading
|
|
4
|
+
import time
|
|
5
|
+
import requests
|
|
6
|
+
import jwt
|
|
7
|
+
import httpx
|
|
8
|
+
import numpy as np
|
|
9
|
+
from PIL import Image
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
from rustapi import FastAPI, Request, Depends, HTTPException, status
|
|
12
|
+
from rustapi.uploads import UploadFile
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# 1. Pydantic Model
|
|
16
|
+
class ImageAnalysisRequest(BaseModel):
|
|
17
|
+
project_name: str = Field(..., min_length=2)
|
|
18
|
+
threshold: float = Field(0.5, ge=0.0, le=1.0)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# 2. Database Setup (SQLite stdlib)
|
|
22
|
+
def init_db():
|
|
23
|
+
conn = sqlite3.connect(":memory:", check_same_thread=False)
|
|
24
|
+
conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT, token TEXT)")
|
|
25
|
+
conn.execute("INSERT INTO users (username, token) VALUES ('alice', 'secret_jwt_123')")
|
|
26
|
+
conn.commit()
|
|
27
|
+
return conn
|
|
28
|
+
|
|
29
|
+
db_conn = init_db()
|
|
30
|
+
|
|
31
|
+
# DB Dependency
|
|
32
|
+
def get_db():
|
|
33
|
+
return db_conn
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# 3. Application
|
|
37
|
+
app = FastAPI(title="Ecosystem Compatibility Test App")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@app.post("/analyze-image")
|
|
41
|
+
async def analyze_image(req: Request, db=Depends(get_db)):
|
|
42
|
+
# A. Parse form fields or JSON body with Pydantic
|
|
43
|
+
try:
|
|
44
|
+
json_body = await req.json()
|
|
45
|
+
except Exception:
|
|
46
|
+
json_body = {}
|
|
47
|
+
|
|
48
|
+
project_name = req.form.get("project_name") or json_body.get("project_name") or "default_project"
|
|
49
|
+
threshold = float(req.form.get("threshold") or json_body.get("threshold") or 0.5)
|
|
50
|
+
model = ImageAnalysisRequest(project_name=project_name, threshold=threshold)
|
|
51
|
+
|
|
52
|
+
# B. Query SQLite database
|
|
53
|
+
cursor = db.cursor()
|
|
54
|
+
cursor.execute("SELECT username FROM users WHERE token = 'secret_jwt_123'")
|
|
55
|
+
row = cursor.fetchone()
|
|
56
|
+
user = row[0] if row else "unknown"
|
|
57
|
+
|
|
58
|
+
# C. Read uploaded file & process image with PIL (Pillow) & NumPy
|
|
59
|
+
if "photo" not in req.files or not req.files["photo"]:
|
|
60
|
+
raise HTTPException(status_code=400, detail="No photo uploaded")
|
|
61
|
+
|
|
62
|
+
photo_file: UploadFile = req.files["photo"][0]
|
|
63
|
+
img_bytes = await photo_file.read()
|
|
64
|
+
|
|
65
|
+
image = Image.open(io.BytesIO(img_bytes)).convert("L")
|
|
66
|
+
img_array = np.array(image)
|
|
67
|
+
|
|
68
|
+
# Perform NumPy calculation (mean brightness)
|
|
69
|
+
mean_brightness = float(np.mean(img_array))
|
|
70
|
+
|
|
71
|
+
# D. JWT Encoding
|
|
72
|
+
payload = {"sub": user, "project": model.project_name, "brightness": mean_brightness}
|
|
73
|
+
encoded_token = jwt.encode(payload, "secret_key_999", algorithm="HS256")
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
"status": "success",
|
|
77
|
+
"user": user,
|
|
78
|
+
"project": model.project_name,
|
|
79
|
+
"mean_brightness": mean_brightness,
|
|
80
|
+
"jwt_token": encoded_token,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_python_ecosystem_compatibility():
|
|
85
|
+
port = 8996
|
|
86
|
+
thread = threading.Thread(target=lambda: app.run(host="127.0.0.1", port=port), daemon=True)
|
|
87
|
+
thread.start()
|
|
88
|
+
time.sleep(0.4)
|
|
89
|
+
|
|
90
|
+
# Generate sample 100x100 grayscale image in memory using PIL
|
|
91
|
+
img = Image.new("L", (100, 100), color=128)
|
|
92
|
+
img_byte_arr = io.BytesIO()
|
|
93
|
+
img.save(img_byte_arr, format="PNG")
|
|
94
|
+
png_bytes = img_byte_arr.getvalue()
|
|
95
|
+
|
|
96
|
+
# Call endpoint using HTTPX
|
|
97
|
+
with httpx.Client(base_url=f"http://127.0.0.1:{port}") as client:
|
|
98
|
+
files = {"photo": ("test_image.png", png_bytes, "image/png")}
|
|
99
|
+
data = {"project_name": "SkinAnalysis", "threshold": "0.75"}
|
|
100
|
+
|
|
101
|
+
response = client.post("/analyze-image", data=data, files=files)
|
|
102
|
+
assert response.status_code == 200
|
|
103
|
+
|
|
104
|
+
res_json = response.json()
|
|
105
|
+
assert res_json["status"] == "success"
|
|
106
|
+
assert res_json["user"] == "alice"
|
|
107
|
+
assert res_json["project"] == "SkinAnalysis"
|
|
108
|
+
assert res_json["mean_brightness"] == 128.0
|
|
109
|
+
|
|
110
|
+
# Decode JWT token to verify PyJWT compatibility
|
|
111
|
+
decoded = jwt.decode(res_json["jwt_token"], "secret_key_999", algorithms=["HS256"])
|
|
112
|
+
assert decoded["sub"] == "alice"
|
|
113
|
+
assert decoded["project"] == "SkinAnalysis"
|
|
114
|
+
assert decoded["brightness"] == 128.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyrustapi-0.3.34 → pyrustapi-0.3.86}/performance-reports/fastapi_vs_rustapi_crud_benchmark.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyrustapi-0.3.34 → pyrustapi-0.3.86}/performance-reports/three_tier_architecture_evaluation.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|