celery-fastapi 0.1.1__tar.gz → 0.1.3__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.
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/PKG-INFO +1 -1
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/celery_fastapi/cli.py +37 -1
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/celery_fastapi/core.py +9 -6
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/celery_fastapi/server.py +2 -2
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/pyproject.toml +1 -1
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/LICENSE +0 -0
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/README.md +0 -0
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/celery_fastapi/__init__.py +0 -0
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/celery_fastapi/app.py +0 -0
- {celery_fastapi-0.1.1 → celery_fastapi-0.1.3}/celery_fastapi/py.typed +0 -0
|
@@ -72,6 +72,30 @@ app = typer.Typer(
|
|
|
72
72
|
console = Console()
|
|
73
73
|
|
|
74
74
|
|
|
75
|
+
def _create_app_from_env() -> Any:
|
|
76
|
+
"""
|
|
77
|
+
Factory function to create FastAPI app from environment variables.
|
|
78
|
+
|
|
79
|
+
This is used when running with multiple workers or reload enabled,
|
|
80
|
+
as uvicorn requires an import string in these cases.
|
|
81
|
+
"""
|
|
82
|
+
from celery_fastapi.app import create_app
|
|
83
|
+
|
|
84
|
+
celery_app = os.environ.get("CELERY_FASTAPI_CELERY_APP")
|
|
85
|
+
prefix = os.environ.get("CELERY_FASTAPI_PREFIX", "")
|
|
86
|
+
root_path = os.environ.get("CELERY_FASTAPI_ROOT_PATH", "")
|
|
87
|
+
|
|
88
|
+
if not celery_app:
|
|
89
|
+
raise ValueError("CELERY_FASTAPI_CELERY_APP environment variable not set")
|
|
90
|
+
|
|
91
|
+
return create_app(
|
|
92
|
+
celery_app,
|
|
93
|
+
title="Celery FastAPI",
|
|
94
|
+
prefix=prefix,
|
|
95
|
+
fastapi_kwargs={"root_path": root_path} if root_path else None,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
75
99
|
def version_callback(value: bool) -> None:
|
|
76
100
|
"""Print version and exit."""
|
|
77
101
|
if value:
|
|
@@ -374,7 +398,19 @@ def serve(
|
|
|
374
398
|
console.print("[dim]Press CTRL+C to stop[/]\n")
|
|
375
399
|
|
|
376
400
|
# Run the server
|
|
377
|
-
|
|
401
|
+
# When using workers > 1 or reload, we need to use an import string
|
|
402
|
+
if workers > 1 or reload:
|
|
403
|
+
# Set environment variables for the factory to use
|
|
404
|
+
os.environ["CELERY_FASTAPI_CELERY_APP"] = celery_app
|
|
405
|
+
os.environ["CELERY_FASTAPI_PREFIX"] = prefix
|
|
406
|
+
if root_path:
|
|
407
|
+
os.environ["CELERY_FASTAPI_ROOT_PATH"] = root_path
|
|
408
|
+
|
|
409
|
+
# Use the factory function as an import string
|
|
410
|
+
uvicorn.run("celery_fastapi.cli:_create_app_from_env", **uvicorn_config)
|
|
411
|
+
else:
|
|
412
|
+
# Single worker, can use app instance directly
|
|
413
|
+
uvicorn.run(fastapi_app, **uvicorn_config)
|
|
378
414
|
|
|
379
415
|
|
|
380
416
|
@app.command()
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""Core functionality for Celery FastAPI."""
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
+
from collections.abc import Callable
|
|
4
5
|
from datetime import datetime
|
|
5
|
-
from typing import Any,
|
|
6
|
+
from typing import Any, get_type_hints
|
|
6
7
|
|
|
7
8
|
from celery import Celery
|
|
8
9
|
from celery.result import AsyncResult
|
|
@@ -222,7 +223,7 @@ def _create_task_payload_model(
|
|
|
222
223
|
model_name = f"{task_name.replace('.', '_').title().replace('_', '')}Payload"
|
|
223
224
|
|
|
224
225
|
# Create and return the dynamic model
|
|
225
|
-
model: type[BaseModel] = create_model(model_name, **field_definitions)
|
|
226
|
+
model: type[BaseModel] = create_model(model_name, **field_definitions)
|
|
226
227
|
model.__doc__ = f"Payload for {task_name} task. Default queue: {default_queue}"
|
|
227
228
|
|
|
228
229
|
# Set model config for examples
|
|
@@ -324,7 +325,7 @@ class CeleryFastAPIBridge:
|
|
|
324
325
|
|
|
325
326
|
# Store the registered task names from THIS app only
|
|
326
327
|
self._app_task_names: set[str] = set()
|
|
327
|
-
for name in self.celery_app.tasks
|
|
328
|
+
for name in self.celery_app.tasks:
|
|
328
329
|
if self.task_filter(name):
|
|
329
330
|
self._app_task_names.add(name)
|
|
330
331
|
|
|
@@ -403,7 +404,9 @@ class CeleryFastAPIBridge:
|
|
|
403
404
|
celery_option_names = set(CELERY_OPTIONS_FIELDS.keys())
|
|
404
405
|
task_kwargs: dict[str, Any] = {}
|
|
405
406
|
|
|
406
|
-
|
|
407
|
+
# Access model_fields from the class, not the instance (Pydantic V2.11+)
|
|
408
|
+
payload_fields = type(payload).model_fields # type: ignore[attr-defined]
|
|
409
|
+
for field_name in payload_fields:
|
|
407
410
|
if field_name not in celery_option_names:
|
|
408
411
|
value = getattr(payload, field_name, None)
|
|
409
412
|
if value is not None:
|
|
@@ -751,8 +754,8 @@ class CeleryFastAPIBridge:
|
|
|
751
754
|
routes: list[dict[str, str]] = []
|
|
752
755
|
for route in self.fastapi_app.routes:
|
|
753
756
|
if hasattr(route, "path") and hasattr(route, "methods"):
|
|
754
|
-
path =
|
|
755
|
-
methods =
|
|
757
|
+
path = route.path
|
|
758
|
+
methods = route.methods
|
|
756
759
|
for method in methods:
|
|
757
760
|
if method != "HEAD":
|
|
758
761
|
routes.append({"path": path, "method": method})
|
|
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
|
|
|
10
10
|
|
|
11
11
|
def create_gunicorn_app(
|
|
12
12
|
app: Any, options: dict[str, Any] | None = None
|
|
13
|
-
) ->
|
|
13
|
+
) -> BaseApplication:
|
|
14
14
|
"""Create a Gunicorn application instance.
|
|
15
15
|
|
|
16
16
|
Args:
|
|
@@ -31,7 +31,7 @@ def create_gunicorn_app(
|
|
|
31
31
|
"Install with: pip install celery-fastapi[gunicorn]"
|
|
32
32
|
) from exc
|
|
33
33
|
|
|
34
|
-
class _GunicornApp(BaseApplication):
|
|
34
|
+
class _GunicornApp(BaseApplication):
|
|
35
35
|
"""Internal Gunicorn application wrapper."""
|
|
36
36
|
|
|
37
37
|
def __init__(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|