fastapi-mongo-base 0.10.0__tar.gz → 0.10.2__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.
- {fastapi_mongo_base-0.10.0/src/fastapi_mongo_base.egg-info → fastapi_mongo_base-0.10.2}/PKG-INFO +2 -2
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/pyproject.toml +2 -2
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/app_factory.py +14 -77
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/config.py +5 -9
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/db.py +1 -1
- fastapi_mongo_base-0.10.2/src/fastapi_mongo_base/core/middlewares.py +14 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/models.py +25 -55
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/schemas.py +30 -20
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/tasks.py +10 -4
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2/src/fastapi_mongo_base.egg-info}/PKG-INFO +2 -2
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base.egg-info/SOURCES.txt +1 -6
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base.egg-info/requires.txt +1 -1
- fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/cached.py +0 -115
- fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/core/middlewares.py +0 -72
- fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/utils/aionetwork.py +0 -90
- fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/utils/imagetools.py +0 -460
- fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/utils/ssh_handler.py +0 -51
- fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/utils/texttools.py +0 -216
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/LICENSE.txt +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/README.md +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/setup.cfg +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/__init__.py +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/__init__.py +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/enums.py +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/exceptions.py +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/routes.py +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/utils/__init__.py +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/utils/basic.py +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/utils/bsontools.py +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/utils/conditions.py +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base.egg-info/dependency_links.txt +0 -0
- {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base.egg-info/top_level.txt +0 -0
{fastapi_mongo_base-0.10.0/src/fastapi_mongo_base.egg-info → fastapi_mongo_base-0.10.2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-mongo-base
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.2
|
|
4
4
|
Summary: A simple boilerplate application, including models and schemas and abstract router, for FastAPI with MongoDB
|
|
5
5
|
Author-email: Mahdi Kiani <mahdikiany@gmail.com>
|
|
6
6
|
Maintainer-email: Mahdi Kiani <mahdikiany@gmail.com>
|
|
@@ -44,8 +44,8 @@ Description-Content-Type: text/markdown
|
|
|
44
44
|
License-File: LICENSE.txt
|
|
45
45
|
Requires-Dist: pydantic>=2.0.0
|
|
46
46
|
Requires-Dist: httpx>=0.24.0
|
|
47
|
-
Requires-Dist: pyjwt[crypto]
|
|
48
47
|
Requires-Dist: singleton_package
|
|
48
|
+
Requires-Dist: json-advanced
|
|
49
49
|
Requires-Dist: fastapi>=0.65.0
|
|
50
50
|
Requires-Dist: uvicorn[standard]>=0.13.0
|
|
51
51
|
Provides-Extra: image
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "fastapi-mongo-base"
|
|
7
|
-
version = "0.10.
|
|
7
|
+
version = "0.10.2"
|
|
8
8
|
description = "A simple boilerplate application, including models and schemas and abstract router, for FastAPI with MongoDB"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -30,8 +30,8 @@ classifiers = [
|
|
|
30
30
|
dependencies = [
|
|
31
31
|
"pydantic>=2.0.0",
|
|
32
32
|
"httpx>=0.24.0",
|
|
33
|
-
"pyjwt[crypto]",
|
|
34
33
|
"singleton_package",
|
|
34
|
+
"json-advanced",
|
|
35
35
|
"fastapi>=0.65.0",
|
|
36
36
|
"uvicorn[standard]>=0.13.0"
|
|
37
37
|
]
|
{fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/app_factory.py
RENAMED
|
@@ -4,7 +4,6 @@ from collections import deque
|
|
|
4
4
|
from contextlib import asynccontextmanager
|
|
5
5
|
|
|
6
6
|
import fastapi
|
|
7
|
-
from fastapi.middleware.cors import CORSMiddleware
|
|
8
7
|
from fastapi.staticfiles import StaticFiles
|
|
9
8
|
|
|
10
9
|
from fastapi_mongo_base.core import db, exceptions
|
|
@@ -16,20 +15,13 @@ except ImportError:
|
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
async def health(request: fastapi.Request):
|
|
19
|
-
return {
|
|
20
|
-
"status": "up",
|
|
21
|
-
"host": request.url.hostname,
|
|
22
|
-
# "project_name": settings.project_name,
|
|
23
|
-
# "host2": request.base_url.hostname,
|
|
24
|
-
# "original_host":request.headers.get("x-original-host", "!not found!"),
|
|
25
|
-
# "forwarded_host": request.headers.get("X-Forwarded-Host", "forwarded_host"),
|
|
26
|
-
# "forwarded_proto": request.headers.get("X-Forwarded-Proto", "forwarded_proto"),
|
|
27
|
-
# "forwarded_for": request.headers.get("X-Forwarded-For", "forwarded_for"),
|
|
28
|
-
}
|
|
18
|
+
return {"status": "up"}
|
|
29
19
|
|
|
30
20
|
|
|
31
21
|
@asynccontextmanager
|
|
32
|
-
async def lifespan(
|
|
22
|
+
async def lifespan(
|
|
23
|
+
*, app: fastapi.FastAPI, worker=None, init_functions=[], settings: Settings = None
|
|
24
|
+
):
|
|
33
25
|
"""Initialize application services."""
|
|
34
26
|
await db.init_mongo_db()
|
|
35
27
|
|
|
@@ -49,44 +41,18 @@ async def lifespan(app: fastapi.FastAPI, worker=None, init_functions=[], setting
|
|
|
49
41
|
logging.info("Shutdown complete")
|
|
50
42
|
|
|
51
43
|
|
|
52
|
-
def setup_exception_handlers(
|
|
53
|
-
app: fastapi.FastAPI,
|
|
54
|
-
usso_handler: bool = True,
|
|
55
|
-
ufaas_handler: bool = True,
|
|
56
|
-
**kwargs,
|
|
57
|
-
):
|
|
44
|
+
def setup_exception_handlers(*, app: fastapi.FastAPI, handlers: dict = None, **kwargs):
|
|
58
45
|
exception_handlers = exceptions.EXCEPTION_HANDLERS
|
|
59
|
-
if
|
|
60
|
-
|
|
61
|
-
from usso.fastapi.integration import (
|
|
62
|
-
EXCEPTION_HANDLERS as USSO_EXCEPTION_HANDLERS,
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
exception_handlers.update(USSO_EXCEPTION_HANDLERS)
|
|
66
|
-
except ImportError:
|
|
67
|
-
pass
|
|
68
|
-
if ufaas_handler:
|
|
69
|
-
try:
|
|
70
|
-
from ufaas.fastapi.integration import (
|
|
71
|
-
EXCEPTION_HANDLERS as UFAAS_EXCEPTION_HANDLERS,
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
exception_handlers.update(UFAAS_EXCEPTION_HANDLERS)
|
|
75
|
-
except ImportError:
|
|
76
|
-
pass
|
|
46
|
+
if handlers:
|
|
47
|
+
exception_handlers.update(handlers)
|
|
77
48
|
|
|
78
49
|
for exc_class, handler in exception_handlers.items():
|
|
79
50
|
app.exception_handler(exc_class)(handler)
|
|
80
51
|
|
|
81
52
|
|
|
82
|
-
def setup_middlewares(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
original_host_middleware: bool = False,
|
|
86
|
-
request_log_middleware: bool = False,
|
|
87
|
-
timer_middleware: bool = True,
|
|
88
|
-
**kwargs,
|
|
89
|
-
):
|
|
53
|
+
def setup_middlewares(*, app: fastapi.FastAPI, origins: list = None, **kwargs):
|
|
54
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
55
|
+
|
|
90
56
|
if origins:
|
|
91
57
|
app.add_middleware(
|
|
92
58
|
CORSMiddleware,
|
|
@@ -96,20 +62,6 @@ def setup_middlewares(
|
|
|
96
62
|
allow_headers=["*"],
|
|
97
63
|
)
|
|
98
64
|
|
|
99
|
-
if original_host_middleware:
|
|
100
|
-
from ufaas_fastapi_business.core.middlewares import OriginalHostMiddleware
|
|
101
|
-
|
|
102
|
-
app.add_middleware(OriginalHostMiddleware)
|
|
103
|
-
if request_log_middleware:
|
|
104
|
-
from .middlewares import RequestLoggingMiddleware
|
|
105
|
-
|
|
106
|
-
app.add_middleware(RequestLoggingMiddleware)
|
|
107
|
-
if timer_middleware:
|
|
108
|
-
from .middlewares import TimerMiddleware
|
|
109
|
-
|
|
110
|
-
app.add_middleware(TimerMiddleware)
|
|
111
|
-
|
|
112
|
-
|
|
113
65
|
def create_app(
|
|
114
66
|
settings: Settings = None,
|
|
115
67
|
*,
|
|
@@ -121,20 +73,12 @@ def create_app(
|
|
|
121
73
|
lifespan_func=None,
|
|
122
74
|
worker=None,
|
|
123
75
|
init_functions: list = [],
|
|
124
|
-
contact=
|
|
125
|
-
"name": "Mahdi Kiani",
|
|
126
|
-
"url": "https://github.com/mahdikiani/FastAPILaunchpad",
|
|
127
|
-
"email": "mahdikiany@gmail.com",
|
|
128
|
-
},
|
|
76
|
+
contact=None,
|
|
129
77
|
license_info={
|
|
130
78
|
"name": "MIT License",
|
|
131
79
|
"url": "https://github.com/mahdikiani/FastAPILaunchpad/blob/main/LICENSE",
|
|
132
80
|
},
|
|
133
|
-
|
|
134
|
-
ufaas_handler: bool = True,
|
|
135
|
-
original_host_middleware: bool = False,
|
|
136
|
-
request_log_middleware: bool = False,
|
|
137
|
-
timer_middleware: bool = True,
|
|
81
|
+
exception_handlers: dict = None,
|
|
138
82
|
log_route: bool = False,
|
|
139
83
|
health_route: bool = True,
|
|
140
84
|
**kwargs,
|
|
@@ -172,15 +116,8 @@ def create_app(
|
|
|
172
116
|
openapi_url=openapi_url,
|
|
173
117
|
)
|
|
174
118
|
|
|
175
|
-
setup_exception_handlers(app,
|
|
176
|
-
setup_middlewares(
|
|
177
|
-
app,
|
|
178
|
-
origins,
|
|
179
|
-
original_host_middleware,
|
|
180
|
-
request_log_middleware,
|
|
181
|
-
timer_middleware,
|
|
182
|
-
**kwargs,
|
|
183
|
-
)
|
|
119
|
+
setup_exception_handlers(app=app, handlers=exception_handlers, **kwargs)
|
|
120
|
+
setup_middlewares(app=app, origins=origins, **kwargs)
|
|
184
121
|
|
|
185
122
|
async def logs():
|
|
186
123
|
with open(settings.get_log_config()["info_log_path"], "rb") as f:
|
{fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/config.py
RENAMED
|
@@ -56,21 +56,15 @@ class Settings(metaclass=Singleton):
|
|
|
56
56
|
"level": console_level,
|
|
57
57
|
"formatter": "standard",
|
|
58
58
|
},
|
|
59
|
-
"file": {
|
|
60
|
-
"class": "logging.FileHandler",
|
|
61
|
-
"level": file_level,
|
|
62
|
-
"filename": cls.base_dir / "logs" / "info.log",
|
|
63
|
-
"formatter": "standard",
|
|
64
|
-
},
|
|
65
59
|
},
|
|
66
60
|
"loggers": {
|
|
67
61
|
"": {
|
|
68
|
-
"handlers": ["console"
|
|
62
|
+
"handlers": ["console"],
|
|
69
63
|
"level": "INFO",
|
|
70
64
|
"propagate": True,
|
|
71
65
|
},
|
|
72
66
|
"httpx": {
|
|
73
|
-
"handlers": ["console"
|
|
67
|
+
"handlers": ["console"],
|
|
74
68
|
"level": "WARNING",
|
|
75
69
|
"propagate": False,
|
|
76
70
|
},
|
|
@@ -81,6 +75,8 @@ class Settings(metaclass=Singleton):
|
|
|
81
75
|
|
|
82
76
|
@classmethod
|
|
83
77
|
def config_logger(cls):
|
|
84
|
-
|
|
78
|
+
log_config = cls.get_log_config()
|
|
79
|
+
if log_config["handlers"].get("file"):
|
|
80
|
+
(cls.base_dir / "logs").mkdir(parents=True, exist_ok=True)
|
|
85
81
|
|
|
86
82
|
logging.config.dictConfig(cls.get_log_config())
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import time
|
|
2
|
+
|
|
3
|
+
from fastapi import Request
|
|
4
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TimerMiddleware(BaseHTTPMiddleware):
|
|
8
|
+
async def dispatch(self, request: Request, call_next):
|
|
9
|
+
start_time = time.time()
|
|
10
|
+
response = await call_next(request)
|
|
11
|
+
end_time = time.time()
|
|
12
|
+
response.headers["X-Delivery-Time"] = str(end_time - start_time)
|
|
13
|
+
|
|
14
|
+
return response
|
|
@@ -3,16 +3,12 @@ import uuid
|
|
|
3
3
|
from datetime import date, datetime
|
|
4
4
|
from decimal import Decimal
|
|
5
5
|
|
|
6
|
+
import json_advanced
|
|
6
7
|
from beanie import Document, Insert, Replace, Save, SaveChanges, Update, before_event
|
|
7
8
|
from beanie.odm.queries.find import FindMany
|
|
8
9
|
from pydantic import ConfigDict
|
|
9
10
|
from pymongo import ASCENDING, IndexModel
|
|
10
11
|
|
|
11
|
-
try:
|
|
12
|
-
from json_advanced import loads
|
|
13
|
-
except ImportError:
|
|
14
|
-
from json import loads
|
|
15
|
-
|
|
16
12
|
try:
|
|
17
13
|
from server.config import Settings
|
|
18
14
|
except ImportError:
|
|
@@ -20,11 +16,10 @@ except ImportError:
|
|
|
20
16
|
|
|
21
17
|
from .schemas import (
|
|
22
18
|
BaseEntitySchema,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
TenantScopedEntitySchema,
|
|
20
|
+
TenantUserEntitySchema,
|
|
21
|
+
UserOwnedEntitySchema,
|
|
26
22
|
)
|
|
27
|
-
from .tasks import TaskMixin
|
|
28
23
|
|
|
29
24
|
|
|
30
25
|
class BaseEntity(BaseEntitySchema, Document):
|
|
@@ -68,7 +63,7 @@ class BaseEntity(BaseEntitySchema, Document):
|
|
|
68
63
|
value = value.strip()
|
|
69
64
|
try:
|
|
70
65
|
if value.startswith("[") and value.endswith("]"):
|
|
71
|
-
parsed = loads(value)
|
|
66
|
+
parsed = json_advanced.loads(value)
|
|
72
67
|
if isinstance(parsed, list):
|
|
73
68
|
return list(set(parsed))
|
|
74
69
|
return [parsed]
|
|
@@ -341,7 +336,7 @@ class BaseEntity(BaseEntitySchema, Document):
|
|
|
341
336
|
return item
|
|
342
337
|
|
|
343
338
|
|
|
344
|
-
class
|
|
339
|
+
class UserOwnedEntity(UserOwnedEntitySchema, BaseEntity):
|
|
345
340
|
|
|
346
341
|
class Settings(BaseEntity.Settings):
|
|
347
342
|
__abstract__ = True
|
|
@@ -349,62 +344,55 @@ class OwnedEntity(OwnedEntitySchema, BaseEntity):
|
|
|
349
344
|
indexes = BaseEntity.Settings.indexes + [IndexModel([("user_id", ASCENDING)])]
|
|
350
345
|
|
|
351
346
|
@classmethod
|
|
352
|
-
async def get_item(cls, uid, user_id, *args, **kwargs) -> "
|
|
347
|
+
async def get_item(cls, uid, user_id, *args, **kwargs) -> "UserOwnedEntity":
|
|
353
348
|
if user_id == None and kwargs.get("ignore_user_id") != True:
|
|
354
349
|
raise ValueError("user_id is required")
|
|
355
350
|
return await super().get_item(uid, user_id=user_id, *args, **kwargs)
|
|
356
351
|
|
|
357
352
|
|
|
358
|
-
class
|
|
353
|
+
class TenantScopedEntity(TenantScopedEntitySchema, BaseEntity):
|
|
359
354
|
|
|
360
355
|
class Settings(BaseEntity.Settings):
|
|
361
356
|
__abstract__ = True
|
|
362
357
|
|
|
363
|
-
indexes = BaseEntity.Settings.indexes + [
|
|
364
|
-
IndexModel([("business_name", ASCENDING)])
|
|
365
|
-
]
|
|
358
|
+
indexes = BaseEntity.Settings.indexes + [IndexModel([("tenant_id", ASCENDING)])]
|
|
366
359
|
|
|
367
360
|
@classmethod
|
|
368
|
-
async def get_item(cls, uid,
|
|
369
|
-
if
|
|
370
|
-
raise ValueError("
|
|
371
|
-
return await super().get_item(uid,
|
|
361
|
+
async def get_item(cls, uid, tenant_id, *args, **kwargs) -> "TenantScopedEntity":
|
|
362
|
+
if tenant_id == None:
|
|
363
|
+
raise ValueError("tenant_id is required")
|
|
364
|
+
return await super().get_item(uid, tenant_id=tenant_id, *args, **kwargs)
|
|
372
365
|
|
|
373
|
-
async def
|
|
366
|
+
async def get_tenant(self):
|
|
374
367
|
raise NotImplementedError
|
|
375
|
-
from apps.
|
|
368
|
+
from apps.tenant_mongo.models import Tenant
|
|
376
369
|
|
|
377
|
-
return await
|
|
370
|
+
return await Tenant.get_by_name(self.tenant_id)
|
|
378
371
|
|
|
379
372
|
|
|
380
|
-
class
|
|
373
|
+
class TenantUserEntity(TenantUserEntitySchema, BaseEntity):
|
|
381
374
|
|
|
382
|
-
class Settings(
|
|
375
|
+
class Settings(TenantScopedEntity.Settings):
|
|
383
376
|
__abstract__ = True
|
|
384
377
|
|
|
385
|
-
indexes =
|
|
378
|
+
indexes = TenantScopedEntity.Settings.indexes + [
|
|
386
379
|
IndexModel([("user_id", ASCENDING)])
|
|
387
380
|
]
|
|
388
381
|
|
|
389
382
|
@classmethod
|
|
390
383
|
async def get_item(
|
|
391
|
-
cls, uid,
|
|
392
|
-
) -> "
|
|
393
|
-
if
|
|
394
|
-
raise ValueError("
|
|
384
|
+
cls, uid, tenant_id, user_id, *args, **kwargs
|
|
385
|
+
) -> "TenantUserEntity":
|
|
386
|
+
if tenant_id == None:
|
|
387
|
+
raise ValueError("tenant_id is required")
|
|
395
388
|
# if user_id == None:
|
|
396
389
|
# raise ValueError("user_id is required")
|
|
397
390
|
return await super().get_item(
|
|
398
|
-
uid,
|
|
391
|
+
uid, tenant_id=tenant_id, user_id=user_id, *args, **kwargs
|
|
399
392
|
)
|
|
400
393
|
|
|
401
394
|
|
|
402
|
-
class
|
|
403
|
-
class Settings(BaseEntity.Settings):
|
|
404
|
-
__abstract__ = True
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
class ImmutableBase(BaseEntity):
|
|
395
|
+
class ImmutableMixin(BaseEntity):
|
|
408
396
|
model_config = ConfigDict(frozen=True)
|
|
409
397
|
|
|
410
398
|
class Settings(BaseEntity.Settings):
|
|
@@ -417,21 +405,3 @@ class ImmutableBase(BaseEntity):
|
|
|
417
405
|
@classmethod
|
|
418
406
|
async def delete_item(cls, item: "BaseEntity"):
|
|
419
407
|
raise ValueError("Immutable items cannot be deleted")
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
class ImmutableOwnedEntity(ImmutableBase, OwnedEntity):
|
|
423
|
-
|
|
424
|
-
class Settings(OwnedEntity.Settings):
|
|
425
|
-
__abstract__ = True
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
class ImmutableBusinessEntity(ImmutableBase, BusinessEntity):
|
|
429
|
-
|
|
430
|
-
class Settings(BusinessEntity.Settings):
|
|
431
|
-
__abstract__ = True
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
class ImmutableBusinessOwnedEntity(ImmutableBase, BusinessOwnedEntity):
|
|
435
|
-
|
|
436
|
-
class Settings(BusinessOwnedEntity.Settings):
|
|
437
|
-
__abstract__ = True
|
|
@@ -10,13 +10,30 @@ except ImportError:
|
|
|
10
10
|
from .core.config import Settings
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class BaseEntitySchema(BaseModel):
|
|
14
|
+
uid: str = Field(
|
|
15
|
+
default_factory=str(uuid.uuid4),
|
|
16
|
+
json_schema_extra={"index": True, "unique": True},
|
|
17
|
+
description="Unique identifier for the entity",
|
|
18
|
+
)
|
|
14
19
|
created_at: datetime = Field(
|
|
15
|
-
default_factory=datetime.now,
|
|
20
|
+
default_factory=datetime.now,
|
|
21
|
+
json_schema_extra={"index": True},
|
|
22
|
+
description="Date and time the entity was created",
|
|
23
|
+
)
|
|
24
|
+
updated_at: datetime = Field(
|
|
25
|
+
default_factory=datetime.now,
|
|
26
|
+
json_schema_extra={"index": True},
|
|
27
|
+
description="Date and time the entity was last updated",
|
|
28
|
+
)
|
|
29
|
+
is_deleted: bool = Field(
|
|
30
|
+
default=False,
|
|
31
|
+
description="Whether the entity has been deleted",
|
|
32
|
+
)
|
|
33
|
+
meta_data: dict | None = Field(
|
|
34
|
+
default=None,
|
|
35
|
+
description="Additional metadata for the entity",
|
|
16
36
|
)
|
|
17
|
-
updated_at: datetime = Field(default_factory=datetime.now)
|
|
18
|
-
is_deleted: bool = False
|
|
19
|
-
meta_data: dict | None = None
|
|
20
37
|
|
|
21
38
|
def __hash__(self):
|
|
22
39
|
return hash(self.model_dump_json())
|
|
@@ -48,19 +65,12 @@ class CoreEntitySchema(BaseModel):
|
|
|
48
65
|
def expired(self, days: int = 3):
|
|
49
66
|
return (datetime.now() - self.updated_at).days > days
|
|
50
67
|
|
|
51
|
-
|
|
52
|
-
class BaseEntitySchema(CoreEntitySchema):
|
|
53
|
-
uid: str = Field(
|
|
54
|
-
default_factory=str(uuid.uuid4),
|
|
55
|
-
json_schema_extra={"index": True, "unique": True},
|
|
56
|
-
)
|
|
57
|
-
|
|
58
68
|
@property
|
|
59
69
|
def item_url(self):
|
|
60
70
|
return f"https://{Settings.root_url}{Settings.base_path}/{self.__class__.__name__.lower()}s/{self.uid}"
|
|
61
71
|
|
|
62
72
|
|
|
63
|
-
class
|
|
73
|
+
class UserOwnedEntitySchema(BaseEntitySchema):
|
|
64
74
|
user_id: str
|
|
65
75
|
|
|
66
76
|
@classmethod
|
|
@@ -72,27 +82,27 @@ class OwnedEntitySchema(BaseEntitySchema):
|
|
|
72
82
|
return super().update_exclude_set() + ["user_id"]
|
|
73
83
|
|
|
74
84
|
|
|
75
|
-
class
|
|
76
|
-
|
|
85
|
+
class TenantScopedEntitySchema(BaseEntitySchema):
|
|
86
|
+
tenant_id: str
|
|
77
87
|
|
|
78
88
|
@classmethod
|
|
79
89
|
def create_exclude_set(cls) -> list[str]:
|
|
80
|
-
return super().create_exclude_set() + ["
|
|
90
|
+
return super().create_exclude_set() + ["tenant_id"]
|
|
81
91
|
|
|
82
92
|
@classmethod
|
|
83
93
|
def update_exclude_set(cls) -> list[str]:
|
|
84
|
-
return super().update_exclude_set() + ["
|
|
94
|
+
return super().update_exclude_set() + ["tenant_id"]
|
|
85
95
|
|
|
86
96
|
|
|
87
|
-
class
|
|
97
|
+
class TenantUserEntitySchema(TenantScopedEntitySchema, UserOwnedEntitySchema):
|
|
88
98
|
|
|
89
99
|
@classmethod
|
|
90
100
|
def create_exclude_set(cls) -> list[str]:
|
|
91
|
-
return list(set(super().create_exclude_set() + ["
|
|
101
|
+
return list(set(super().create_exclude_set() + ["tenant_id", "user_id"]))
|
|
92
102
|
|
|
93
103
|
@classmethod
|
|
94
104
|
def update_exclude_set(cls) -> list[str]:
|
|
95
|
-
return list(set(super().update_exclude_set() + ["
|
|
105
|
+
return list(set(super().update_exclude_set() + ["tenant_id", "user_id"]))
|
|
96
106
|
|
|
97
107
|
|
|
98
108
|
T = TypeVar("T", bound=BaseEntitySchema)
|
|
@@ -9,7 +9,7 @@ from pydantic import BaseModel, Field, field_serializer, field_validator
|
|
|
9
9
|
from singleton import Singleton
|
|
10
10
|
|
|
11
11
|
from .schemas import BaseEntitySchema
|
|
12
|
-
from .utils import
|
|
12
|
+
from .utils import basic
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class TaskStatusEnum(str, Enum):
|
|
@@ -117,7 +117,8 @@ class TaskMixin(BaseModel):
|
|
|
117
117
|
task_references: TaskReferenceList | None = None
|
|
118
118
|
task_start_at: datetime | None = None
|
|
119
119
|
task_end_at: datetime | None = None
|
|
120
|
-
task_order_score:
|
|
120
|
+
task_order_score: int = 0
|
|
121
|
+
webhook_custom_headers: dict | None = None
|
|
121
122
|
webhook_url: str | None = None
|
|
122
123
|
|
|
123
124
|
@classmethod
|
|
@@ -166,8 +167,10 @@ class TaskMixin(BaseModel):
|
|
|
166
167
|
async def emit_signals(cls, task_instance: "TaskMixin", *, sync=False, **kwargs):
|
|
167
168
|
|
|
168
169
|
async def webhook_call(*args, **kwargs):
|
|
170
|
+
import httpx
|
|
171
|
+
|
|
169
172
|
try:
|
|
170
|
-
await
|
|
173
|
+
await httpx.AsyncClient().post(*args, **kwargs)
|
|
171
174
|
except Exception as e:
|
|
172
175
|
import traceback
|
|
173
176
|
|
|
@@ -204,7 +207,10 @@ class TaskMixin(BaseModel):
|
|
|
204
207
|
webhook_call(
|
|
205
208
|
method="post",
|
|
206
209
|
url=webhook_url,
|
|
207
|
-
headers={
|
|
210
|
+
headers={
|
|
211
|
+
"Content-Type": "application/json",
|
|
212
|
+
**(task_instance.webhook_custom_headers or {}),
|
|
213
|
+
},
|
|
208
214
|
data=json.dumps(task_dict),
|
|
209
215
|
)
|
|
210
216
|
)
|
{fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2/src/fastapi_mongo_base.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fastapi-mongo-base
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.2
|
|
4
4
|
Summary: A simple boilerplate application, including models and schemas and abstract router, for FastAPI with MongoDB
|
|
5
5
|
Author-email: Mahdi Kiani <mahdikiany@gmail.com>
|
|
6
6
|
Maintainer-email: Mahdi Kiani <mahdikiany@gmail.com>
|
|
@@ -44,8 +44,8 @@ Description-Content-Type: text/markdown
|
|
|
44
44
|
License-File: LICENSE.txt
|
|
45
45
|
Requires-Dist: pydantic>=2.0.0
|
|
46
46
|
Requires-Dist: httpx>=0.24.0
|
|
47
|
-
Requires-Dist: pyjwt[crypto]
|
|
48
47
|
Requires-Dist: singleton_package
|
|
48
|
+
Requires-Dist: json-advanced
|
|
49
49
|
Requires-Dist: fastapi>=0.65.0
|
|
50
50
|
Requires-Dist: uvicorn[standard]>=0.13.0
|
|
51
51
|
Provides-Extra: image
|
{fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base.egg-info/SOURCES.txt
RENAMED
|
@@ -2,7 +2,6 @@ LICENSE.txt
|
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
4
|
src/fastapi_mongo_base/__init__.py
|
|
5
|
-
src/fastapi_mongo_base/cached.py
|
|
6
5
|
src/fastapi_mongo_base/models.py
|
|
7
6
|
src/fastapi_mongo_base/routes.py
|
|
8
7
|
src/fastapi_mongo_base/schemas.py
|
|
@@ -20,10 +19,6 @@ src/fastapi_mongo_base/core/enums.py
|
|
|
20
19
|
src/fastapi_mongo_base/core/exceptions.py
|
|
21
20
|
src/fastapi_mongo_base/core/middlewares.py
|
|
22
21
|
src/fastapi_mongo_base/utils/__init__.py
|
|
23
|
-
src/fastapi_mongo_base/utils/aionetwork.py
|
|
24
22
|
src/fastapi_mongo_base/utils/basic.py
|
|
25
23
|
src/fastapi_mongo_base/utils/bsontools.py
|
|
26
|
-
src/fastapi_mongo_base/utils/conditions.py
|
|
27
|
-
src/fastapi_mongo_base/utils/imagetools.py
|
|
28
|
-
src/fastapi_mongo_base/utils/ssh_handler.py
|
|
29
|
-
src/fastapi_mongo_base/utils/texttools.py
|
|
24
|
+
src/fastapi_mongo_base/utils/conditions.py
|