future-framework 2.0.0__tar.gz → 2.1.1__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.
- {future_framework-2.0.0 → future_framework-2.1.1}/PKG-INFO +2 -1
- {future_framework-2.0.0 → future_framework-2.1.1}/future/application.py +1 -1
- {future_framework-2.0.0 → future_framework-2.1.1}/future/databases/ElasticsearchDatabase.py +18 -3
- {future_framework-2.0.0 → future_framework-2.1.1}/future/databases/PostgresDatabase.py +16 -8
- {future_framework-2.0.0 → future_framework-2.1.1}/future/response.py +18 -62
- {future_framework-2.0.0 → future_framework-2.1.1}/future/seeder.py +62 -2
- {future_framework-2.0.0 → future_framework-2.1.1}/pyproject.toml +1 -1
- {future_framework-2.0.0 → future_framework-2.1.1}/LICENSE +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/README.md +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/__init__.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/Auth0Authentication.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/AzureADAuthentication.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/BasicAuthentication.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/KerberosAuthentication.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/KeycloakAuthentication.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/OAuth2Authentication.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/OpenIdConnectAuthentication.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/SAMLAuthentication.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/__init__.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/cli.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/controllers/DebugController.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/controllers/GraphQLController.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/controllers/OpenAPIController.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/controllers/WebSocketController.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/controllers/WelcomeController.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/controllers/__init__.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/database.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/databases/ClickhouseDatabase.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/databases/MongoDBDatabase.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/databases/MySQLDatabase.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/databases/RedisDatabase.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/databases/SQLiteDatabase.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/databases/__init__.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/exceptions.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/interfaces/IAuthentication.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/interfaces/IController.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/interfaces/IDatabase.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/interfaces/IMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/interfaces/IModel.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/interfaces/IPlugin.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/interfaces/ITask.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/interfaces/__init__.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/interfacing.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/lifespan.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/logger.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/BruteforcePreventionMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/CORSMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/CSRFMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/GZipMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/HTAccessConfuserMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/HeaderConfuserMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/RateLimitMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/ResponseCodeConfuserMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/SQLiConfuserMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/ScopeValidationMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/SessionMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/TestMiddlewareRequest.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/TestMiddlewareResponse.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/WebServerConfuserMiddleware.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/__init__.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/migrations.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/models/PostModel.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/models/Query.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/models/UserModel.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/models/__init__.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/openapi.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/plugins/ElasticsearchPlugin.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/plugins/__init__.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/request.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/routing.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/settings.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/tasks/CheckDNSTask.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/tasks/CheckDiskUsageTask.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/tasks/CheckHttpStatusTask.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/tasks/CheckMemoryUsageTask.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/tasks/CheckSSHBannerTask.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/tasks/CheckSystemUptimeTask.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/tasks/DailyBackupTask.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/tasks/SyncTaskExample.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/tasks/__init__.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/taskscheduler.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/testclient.py +0 -0
- {future_framework-2.0.0 → future_framework-2.1.1}/future/types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: future-framework
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: ASGI-based framework for web APIs
|
|
5
5
|
License: LICENSE
|
|
6
6
|
License-File: LICENSE
|
|
@@ -11,6 +11,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.13
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
14
15
|
Requires-Dist: aiomysql (>=0.2.0,<0.3.0)
|
|
15
16
|
Requires-Dist: aiosqlite (>=0.21.0,<0.22.0)
|
|
16
17
|
Requires-Dist: asynch (>=0.2.5,<0.3.0)
|
|
@@ -402,7 +402,7 @@ class Future:
|
|
|
402
402
|
try:
|
|
403
403
|
host_domain = request.host.split("/")[0] if "/" in request.host else request.host
|
|
404
404
|
if not self._validate_domain_access(host_domain):
|
|
405
|
-
raise HTTPException("
|
|
405
|
+
raise HTTPException("Not Found", 404)
|
|
406
406
|
|
|
407
407
|
debug = bool(self.config.get("APP_DEBUG")) if self.config else False
|
|
408
408
|
route_host = host_domain.rsplit(":", 1)[0] if debug and ":" in host_domain else host_domain
|
|
@@ -42,7 +42,10 @@ class ElasticsearchDatabase(IDatabase):
|
|
|
42
42
|
return None
|
|
43
43
|
if not result or "_source" not in result:
|
|
44
44
|
return None
|
|
45
|
-
|
|
45
|
+
source = dict(result["_source"] or {})
|
|
46
|
+
if result.get("_id") is not None and not source.get("id"):
|
|
47
|
+
source["id"] = result["_id"]
|
|
48
|
+
return model.__class__(**source)
|
|
46
49
|
|
|
47
50
|
async def all(self, model):
|
|
48
51
|
if self.client is None:
|
|
@@ -51,7 +54,13 @@ class ElasticsearchDatabase(IDatabase):
|
|
|
51
54
|
result = await self.client.search(index=model.tableize(), body={"query": {"match_all": {}}, "size": 10000})
|
|
52
55
|
except Exception:
|
|
53
56
|
return []
|
|
54
|
-
|
|
57
|
+
rows = []
|
|
58
|
+
for hit in result.get("hits", {}).get("hits", []):
|
|
59
|
+
source = dict(hit.get("_source") or {})
|
|
60
|
+
if hit.get("_id") is not None and not source.get("id"):
|
|
61
|
+
source["id"] = hit["_id"]
|
|
62
|
+
rows.append(model.__class__(**source))
|
|
63
|
+
return rows
|
|
55
64
|
|
|
56
65
|
async def get(self, model, wheres, limit=None, orders=None):
|
|
57
66
|
if self.client is None:
|
|
@@ -85,7 +94,13 @@ class ElasticsearchDatabase(IDatabase):
|
|
|
85
94
|
result = await self.client.search(index=model.tableize(), body=body)
|
|
86
95
|
except Exception:
|
|
87
96
|
return []
|
|
88
|
-
|
|
97
|
+
rows = []
|
|
98
|
+
for hit in result.get("hits", {}).get("hits", []):
|
|
99
|
+
source = dict(hit.get("_source") or {})
|
|
100
|
+
if hit.get("_id") is not None and not source.get("id"):
|
|
101
|
+
source["id"] = hit["_id"]
|
|
102
|
+
rows.append(model.__class__(**source))
|
|
103
|
+
return rows
|
|
89
104
|
|
|
90
105
|
async def delete(self, model):
|
|
91
106
|
if self.client is None:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from future.interfaces.IDatabase import IDatabase
|
|
2
|
-
from sqlalchemy import text
|
|
2
|
+
from sqlalchemy import BigInteger, String, bindparam, text
|
|
3
|
+
from sqlalchemy.dialects.postgresql import ARRAY
|
|
3
4
|
from sqlalchemy.ext.asyncio import create_async_engine
|
|
4
5
|
from urllib.parse import quote_plus
|
|
5
6
|
|
|
@@ -61,17 +62,21 @@ class PostgresDatabase(IDatabase):
|
|
|
61
62
|
table = model.tableize()
|
|
62
63
|
clauses = []
|
|
63
64
|
params = {}
|
|
65
|
+
array_binds = {}
|
|
64
66
|
for index, (column, operator, value) in enumerate(wheres):
|
|
65
67
|
if operator == "in":
|
|
66
68
|
values = list(value)
|
|
67
69
|
if not values:
|
|
68
70
|
return []
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
# One array bind avoids Postgres' ~32767 bind-variable limit.
|
|
72
|
+
key = f"v{index}"
|
|
73
|
+
clauses.append(f'"{column}" = ANY(:{key})')
|
|
74
|
+
params[key] = values
|
|
75
|
+
sample = values[0]
|
|
76
|
+
if isinstance(sample, int) and not isinstance(sample, bool):
|
|
77
|
+
array_binds[key] = ARRAY(BigInteger)
|
|
78
|
+
else:
|
|
79
|
+
array_binds[key] = ARRAY(String)
|
|
75
80
|
continue
|
|
76
81
|
if operator == "like":
|
|
77
82
|
key = f"v{index}"
|
|
@@ -90,8 +95,11 @@ class PostgresDatabase(IDatabase):
|
|
|
90
95
|
sql += " ORDER BY " + ", ".join(f'"{column}" {direction}' for column, direction in orders)
|
|
91
96
|
if limit is not None:
|
|
92
97
|
sql += f" LIMIT {int(limit)}"
|
|
98
|
+
stmt = text(sql)
|
|
99
|
+
for key, array_type in array_binds.items():
|
|
100
|
+
stmt = stmt.bindparams(bindparam(key, type_=array_type))
|
|
93
101
|
async with self.client.connect() as connection:
|
|
94
|
-
rows = (await connection.execute(
|
|
102
|
+
rows = (await connection.execute(stmt, params)).mappings().all()
|
|
95
103
|
return [model.__class__(**dict(row)) for row in rows]
|
|
96
104
|
|
|
97
105
|
async def delete(self, model):
|
|
@@ -30,7 +30,7 @@ class Response:
|
|
|
30
30
|
header_map["content-type"] = content_type
|
|
31
31
|
# Preserve Set-Cookie headers already appended via set_cookie
|
|
32
32
|
cookies = [pair for pair in self.headers if pair[0].lower() == b"set-cookie"]
|
|
33
|
-
self.headers = [[key.encode(), value.encode()] for key, value in header_map.items()]
|
|
33
|
+
self.headers = [[key.lower().encode(), value.encode()] for key, value in header_map.items()]
|
|
34
34
|
self.headers.extend(cookies)
|
|
35
35
|
return self
|
|
36
36
|
|
|
@@ -54,11 +54,6 @@ class Response:
|
|
|
54
54
|
def file(self, body: bytes = b"", status: int = 200, headers: dict[str, str] | None = None, content_type: str = "application/octet-stream") -> "Response":
|
|
55
55
|
return self._set(body=body, status=status, headers=headers, content_type=content_type)
|
|
56
56
|
|
|
57
|
-
def stream(self, chunks, status: int = 200, headers: dict[str, str] | None = None, content_type: str = "application/octet-stream") -> "StreamingResponse":
|
|
58
|
-
streamed = StreamingResponse(chunks, status=status, headers=headers, content_type=content_type)
|
|
59
|
-
streamed.headers.extend([pair for pair in self.headers if pair[0].lower() == b"set-cookie"])
|
|
60
|
-
return streamed
|
|
61
|
-
|
|
62
57
|
def image(self, body: bytes = b"", status: int = 200, headers: dict[str, str] | None = None, content_type: str = "image/png", file_path: str | None = None) -> "Response":
|
|
63
58
|
if file_path:
|
|
64
59
|
with open(file_path, "rb") as f:
|
|
@@ -149,72 +144,33 @@ class WebSocketResponse:
|
|
|
149
144
|
await self.send_text(f"Echo: {text}")
|
|
150
145
|
|
|
151
146
|
|
|
152
|
-
# Temporary wrappers for migration
|
|
153
|
-
class PlainTextResponse(Response):
|
|
154
|
-
def __init__(self, body: str = "", status: int = 200, headers: dict[str, str] | None = None) -> None:
|
|
155
|
-
super().__init__()
|
|
156
|
-
self.text(body, status=status, headers=headers)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
class JSONResponse(Response):
|
|
160
|
-
def __init__(self, data: Any = None, status: int = 200, headers: dict[str, str] | None = None) -> None:
|
|
161
|
-
super().__init__()
|
|
162
|
-
self.json(data, status=status, headers=headers)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
class EmptyResponse(Response):
|
|
166
|
-
def __init__(self, status: int = 204, headers: dict[str, str] | None = None) -> None:
|
|
167
|
-
super().__init__()
|
|
168
|
-
self.empty(status=status, headers=headers)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
class HTMLResponse(Response):
|
|
172
|
-
def __init__(self, html: str = "", status: int = 200, headers: dict[str, str] | None = None) -> None:
|
|
173
|
-
super().__init__()
|
|
174
|
-
self.html(html, status=status, headers=headers)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
class PNGResponse(Response):
|
|
178
|
-
def __init__(self, body: bytes = b"", status: int = 200, headers: dict[str, str] | None = None) -> None:
|
|
179
|
-
super().__init__()
|
|
180
|
-
self.image(body, status=status, headers=headers, content_type="image/png")
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
class ImageResponse(Response):
|
|
184
|
-
def __init__(
|
|
185
|
-
self, body: bytes = b"", status: int = 200, headers: dict[str, str] | None = None, image_content_type: str = "image/png", file_path: str | None = None
|
|
186
|
-
) -> None:
|
|
187
|
-
super().__init__()
|
|
188
|
-
self.image(body, status=status, headers=headers, content_type=image_content_type, file_path=file_path)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
class RedirectResponse(Response):
|
|
192
|
-
def __init__(self, url: str = "", status: int = 302, headers: dict[str, str] | None = None) -> None:
|
|
193
|
-
super().__init__()
|
|
194
|
-
if url:
|
|
195
|
-
self.redirect(url, status=status, headers=headers)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
class FileResponse(Response):
|
|
199
|
-
def __init__(self, body: bytes = b"", status: int = 200, headers: dict[str, str] | None = None) -> None:
|
|
200
|
-
super().__init__()
|
|
201
|
-
self.file(body, status=status, headers=headers)
|
|
202
|
-
|
|
203
|
-
|
|
204
147
|
class StreamingResponse(Response):
|
|
205
148
|
def __init__(self, body=(), status: int = 200, headers: dict[str, str] | None = None, content_type: Optional[str] = None) -> None:
|
|
206
149
|
super().__init__(body=b"", status=status, headers=headers, content_type=content_type or "application/octet-stream")
|
|
207
150
|
self._chunks = body
|
|
208
151
|
|
|
209
152
|
async def __call__(self, send: Any) -> None:
|
|
210
|
-
await send({"type": "http.response.start", "status": self.status, "headers": self.headers})
|
|
153
|
+
await send({"type": "http.response.start", "status": int(self.status), "headers": self.headers})
|
|
211
154
|
chunks = self._chunks
|
|
212
|
-
if isinstance(chunks, (bytes, str)):
|
|
155
|
+
if isinstance(chunks, (bytes, bytearray, memoryview, str)):
|
|
213
156
|
chunks = [chunks]
|
|
214
157
|
if hasattr(chunks, "__aiter__"):
|
|
215
158
|
async for chunk in chunks:
|
|
216
|
-
|
|
159
|
+
if isinstance(chunk, (bytes, bytearray, memoryview)):
|
|
160
|
+
body = bytes(chunk)
|
|
161
|
+
elif isinstance(chunk, str):
|
|
162
|
+
body = chunk.encode("utf-8")
|
|
163
|
+
else:
|
|
164
|
+
raise TypeError(f"stream chunk must be bytes or str, got {type(chunk).__name__}")
|
|
165
|
+
await send({"type": "http.response.body", "body": body, "more_body": True})
|
|
217
166
|
else:
|
|
218
167
|
for chunk in chunks:
|
|
219
|
-
|
|
168
|
+
if isinstance(chunk, (bytes, bytearray, memoryview)):
|
|
169
|
+
body = bytes(chunk)
|
|
170
|
+
elif isinstance(chunk, str):
|
|
171
|
+
body = chunk.encode("utf-8")
|
|
172
|
+
else:
|
|
173
|
+
raise TypeError(f"stream chunk must be bytes or str, got {type(chunk).__name__}")
|
|
174
|
+
await send({"type": "http.response.body", "body": body, "more_body": True})
|
|
220
175
|
await send({"type": "http.response.body", "body": b"", "more_body": False})
|
|
176
|
+
|
|
@@ -65,7 +65,7 @@ class SeedGenerator:
|
|
|
65
65
|
return model
|
|
66
66
|
raise ValueError(f"Model not found: {name}")
|
|
67
67
|
|
|
68
|
-
def value_expr(self, field, annotation):
|
|
68
|
+
def value_expr(self, field, annotation, model_name=None):
|
|
69
69
|
origin = get_origin(annotation)
|
|
70
70
|
if origin is Union or origin is UnionType:
|
|
71
71
|
args = [arg for arg in get_args(annotation) if arg is not type(None)]
|
|
@@ -73,10 +73,30 @@ class SeedGenerator:
|
|
|
73
73
|
type_name = getattr(annotation, "__name__", str(annotation))
|
|
74
74
|
if field == "id":
|
|
75
75
|
return "fake.uuid4()"
|
|
76
|
+
if field in ("timestamp", "published_at", "generated_at", "joined_at", "trades_synced_at", "last_login_at"):
|
|
77
|
+
return 'fake.date_time_between(start_date="-1y", end_date="now")'
|
|
76
78
|
if type_name == "datetime":
|
|
77
79
|
return "fake.date_time_this_year()"
|
|
80
|
+
if field == "historical_trades_offset":
|
|
81
|
+
return "0"
|
|
82
|
+
if field in ("follower_count", "following_count"):
|
|
83
|
+
return "fake.random_int(0, 5000)"
|
|
84
|
+
if field == "average_hold_time":
|
|
85
|
+
return "fake.random_int(1, 365)"
|
|
86
|
+
if field == "rating":
|
|
87
|
+
return "fake.random_int(0, 5)"
|
|
88
|
+
if field == "window_hours":
|
|
89
|
+
return "fake.random_int(1, 168)"
|
|
90
|
+
if field == "unique_traders":
|
|
91
|
+
return "fake.random_int(2, 20)"
|
|
78
92
|
if type_name == "int":
|
|
79
93
|
return "fake.random_int(1, 9999)"
|
|
94
|
+
if field == "price":
|
|
95
|
+
return "float(fake.pyfloat(min_value=5, max_value=1500, right_digits=2))"
|
|
96
|
+
if field == "percentage_change":
|
|
97
|
+
return "float(fake.pyfloat(min_value=-25, max_value=25, right_digits=2))"
|
|
98
|
+
if field == "strength":
|
|
99
|
+
return "float(fake.pyfloat(min_value=0, max_value=100, right_digits=2))"
|
|
80
100
|
if type_name == "float":
|
|
81
101
|
return "float(fake.pyfloat(min_value=1, max_value=100))"
|
|
82
102
|
if type_name == "bool":
|
|
@@ -85,6 +105,46 @@ class SeedGenerator:
|
|
|
85
105
|
return "str(fake.random_int(1000, 9999))"
|
|
86
106
|
if "email" in field:
|
|
87
107
|
return "fake.email()"
|
|
108
|
+
if field == "firstname":
|
|
109
|
+
return "fake.first_name()"
|
|
110
|
+
if field == "lastname":
|
|
111
|
+
return "fake.last_name()"
|
|
112
|
+
if field == "instrument_name":
|
|
113
|
+
return "fake.company()"
|
|
114
|
+
if field == "symbol":
|
|
115
|
+
return 'fake.lexify(text="????").upper()'
|
|
116
|
+
if field in ("logo_url", "image_url", "avatar_uri"):
|
|
117
|
+
return "fake.image_url()"
|
|
118
|
+
if field == "url":
|
|
119
|
+
return "fake.url()"
|
|
120
|
+
if field == "currency":
|
|
121
|
+
return 'fake.random_element(elements=("NOK", "SEK", "DKK", "EUR", "USD"))'
|
|
122
|
+
if field == "language":
|
|
123
|
+
return 'fake.random_element(elements=("nb", "sv", "da", "en"))'
|
|
124
|
+
if field == "trade_type" or field == "side":
|
|
125
|
+
return 'fake.random_element(elements=("BUY", "SELL"))'
|
|
126
|
+
if field == "percentage_change_interval":
|
|
127
|
+
return 'fake.random_element(elements=("UNKNOWN", "LESS_THAN_ONE", "ONE_TO_FIVE", "FIVE_TO_TEN", "TEN_TO_TWENTY", "TWENTY_TO_THIRTY", "OVER_ONE_HUNDRED"))'
|
|
128
|
+
if field == "group_type":
|
|
129
|
+
return 'fake.random_element(elements=("COMMON_SHARE", "FND", "ETF", "WARRANT", "OTHER"))'
|
|
130
|
+
if field == "kind":
|
|
131
|
+
return 'fake.random_element(elements=("instruments", "users"))'
|
|
132
|
+
if field == "members":
|
|
133
|
+
return "fake.json()"
|
|
134
|
+
if field == "title":
|
|
135
|
+
return "fake.sentence(nb_words=8)"
|
|
136
|
+
if field in ("summary", "reason"):
|
|
137
|
+
return "fake.sentence()"
|
|
138
|
+
if field == "password_hash":
|
|
139
|
+
return "fake.sha256()"
|
|
140
|
+
if field == "name" and model_name == "NordnetInstrumentModel":
|
|
141
|
+
return 'fake.random_element(elements=("Equinor", "Nordnet Global Indeks", "DNB Teknologi A", "T1 Energy", "Aker BP"))'
|
|
142
|
+
if field == "name" and model_name == "IndexModel":
|
|
143
|
+
return 'fake.random_element(elements=("Nordic Momentum", "Top Shareville Traders", "Consensus Buys", "Long-term Winners"))'
|
|
144
|
+
if field == "country":
|
|
145
|
+
return 'fake.random_element(elements=("NO", "SE", "DK", "FI"))'
|
|
146
|
+
if field == "slug":
|
|
147
|
+
return "fake.slug()"
|
|
88
148
|
if "name" in field or "username" in field:
|
|
89
149
|
return "fake.user_name()"
|
|
90
150
|
if field in ("description", "text", "body", "content") or field.endswith("_original") or field.endswith("_translated"):
|
|
@@ -103,7 +163,7 @@ class SeedGenerator:
|
|
|
103
163
|
current = non_null[0] if non_null else str
|
|
104
164
|
if isinstance(current, type) and issubclass(current, IModel):
|
|
105
165
|
continue
|
|
106
|
-
args.append(f" {field}={self.value_expr(field, annotation)},")
|
|
166
|
+
args.append(f" {field}={self.value_expr(field, annotation, name)},")
|
|
107
167
|
if args:
|
|
108
168
|
construct = f" await {name}(\n" + "\n".join(args) + f"\n ).save()"
|
|
109
169
|
else:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/Auth0Authentication.py
RENAMED
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/AzureADAuthentication.py
RENAMED
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/BasicAuthentication.py
RENAMED
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/KerberosAuthentication.py
RENAMED
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/KeycloakAuthentication.py
RENAMED
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/OAuth2Authentication.py
RENAMED
|
File without changes
|
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/authentication/SAMLAuthentication.py
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
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/HTAccessConfuserMiddleware.py
RENAMED
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/HeaderConfuserMiddleware.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/SQLiConfuserMiddleware.py
RENAMED
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/ScopeValidationMiddleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/TestMiddlewareRequest.py
RENAMED
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/TestMiddlewareResponse.py
RENAMED
|
File without changes
|
{future_framework-2.0.0 → future_framework-2.1.1}/future/middleware/WebServerConfuserMiddleware.py
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
|