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.
Files changed (32) hide show
  1. {fastapi_mongo_base-0.10.0/src/fastapi_mongo_base.egg-info → fastapi_mongo_base-0.10.2}/PKG-INFO +2 -2
  2. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/pyproject.toml +2 -2
  3. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/app_factory.py +14 -77
  4. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/config.py +5 -9
  5. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/db.py +1 -1
  6. fastapi_mongo_base-0.10.2/src/fastapi_mongo_base/core/middlewares.py +14 -0
  7. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/models.py +25 -55
  8. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/schemas.py +30 -20
  9. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/tasks.py +10 -4
  10. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2/src/fastapi_mongo_base.egg-info}/PKG-INFO +2 -2
  11. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base.egg-info/SOURCES.txt +1 -6
  12. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base.egg-info/requires.txt +1 -1
  13. fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/cached.py +0 -115
  14. fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/core/middlewares.py +0 -72
  15. fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/utils/aionetwork.py +0 -90
  16. fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/utils/imagetools.py +0 -460
  17. fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/utils/ssh_handler.py +0 -51
  18. fastapi_mongo_base-0.10.0/src/fastapi_mongo_base/utils/texttools.py +0 -216
  19. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/LICENSE.txt +0 -0
  20. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/README.md +0 -0
  21. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/setup.cfg +0 -0
  22. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/__init__.py +0 -0
  23. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/__init__.py +0 -0
  24. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/enums.py +0 -0
  25. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/core/exceptions.py +0 -0
  26. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/routes.py +0 -0
  27. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/utils/__init__.py +0 -0
  28. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/utils/basic.py +0 -0
  29. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/utils/bsontools.py +0 -0
  30. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base/utils/conditions.py +0 -0
  31. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base.egg-info/dependency_links.txt +0 -0
  32. {fastapi_mongo_base-0.10.0 → fastapi_mongo_base-0.10.2}/src/fastapi_mongo_base.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-mongo-base
3
- Version: 0.10.0
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.0"
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
  ]
@@ -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(app: fastapi.FastAPI, worker=None, init_functions=[], settings: Settings = None): # type: ignore
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 usso_handler:
60
- try:
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
- app: fastapi.FastAPI,
84
- origins: list = None,
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
- usso_handler: bool = True,
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, usso_handler, ufaas_handler, **kwargs)
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:
@@ -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", "file"],
62
+ "handlers": ["console"],
69
63
  "level": "INFO",
70
64
  "propagate": True,
71
65
  },
72
66
  "httpx": {
73
- "handlers": ["console", "file"],
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
- (cls.base_dir / "logs").mkdir(parents=True, exist_ok=True)
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())
@@ -21,7 +21,7 @@ async def init_mongo_db():
21
21
  cls
22
22
  for cls in basic.get_all_subclasses(BaseEntity)
23
23
  if not (
24
- hasattr(cls, "Settings")
24
+ "Settings" in cls.__dict__
25
25
  and getattr(cls.Settings, "__abstract__", False)
26
26
  )
27
27
  ],
@@ -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
- BusinessEntitySchema,
24
- BusinessOwnedEntitySchema,
25
- OwnedEntitySchema,
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 OwnedEntity(OwnedEntitySchema, BaseEntity):
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) -> "OwnedEntity":
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 BusinessEntity(BusinessEntitySchema, BaseEntity):
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, business_name, *args, **kwargs) -> "BusinessEntity":
369
- if business_name == None:
370
- raise ValueError("business_name is required")
371
- return await super().get_item(uid, business_name=business_name, *args, **kwargs)
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 get_business(self):
366
+ async def get_tenant(self):
374
367
  raise NotImplementedError
375
- from apps.business_mongo.models import Business
368
+ from apps.tenant_mongo.models import Tenant
376
369
 
377
- return await Business.get_by_name(self.business_name)
370
+ return await Tenant.get_by_name(self.tenant_id)
378
371
 
379
372
 
380
- class BusinessOwnedEntity(BusinessOwnedEntitySchema, BaseEntity):
373
+ class TenantUserEntity(TenantUserEntitySchema, BaseEntity):
381
374
 
382
- class Settings(BusinessEntity.Settings):
375
+ class Settings(TenantScopedEntity.Settings):
383
376
  __abstract__ = True
384
377
 
385
- indexes = BusinessEntity.Settings.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, business_name, user_id, *args, **kwargs
392
- ) -> "BusinessOwnedEntity":
393
- if business_name == None:
394
- raise ValueError("business_name is required")
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, business_name=business_name, user_id=user_id, *args, **kwargs
391
+ uid, tenant_id=tenant_id, user_id=user_id, *args, **kwargs
399
392
  )
400
393
 
401
394
 
402
- class BaseEntityTaskMixin(BaseEntity, TaskMixin):
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 CoreEntitySchema(BaseModel):
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, json_schema_extra={"index": True}
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 OwnedEntitySchema(BaseEntitySchema):
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 BusinessEntitySchema(BaseEntitySchema):
76
- business_name: str
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() + ["business_name"]
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() + ["business_name"]
94
+ return super().update_exclude_set() + ["tenant_id"]
85
95
 
86
96
 
87
- class BusinessOwnedEntitySchema(OwnedEntitySchema, BusinessEntitySchema):
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() + ["business_name", "user_id"]))
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() + ["business_name", "user_id"]))
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 aionetwork, basic
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: float = 0.0
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 aionetwork.aio_request(*args, **kwargs)
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={"Content-Type": "application/json"},
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
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastapi-mongo-base
3
- Version: 0.10.0
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
@@ -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
@@ -1,7 +1,7 @@
1
1
  pydantic>=2.0.0
2
2
  httpx>=0.24.0
3
- pyjwt[crypto]
4
3
  singleton_package
4
+ json-advanced
5
5
  fastapi>=0.65.0
6
6
  uvicorn[standard]>=0.13.0
7
7