Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: add factory support
  • Loading branch information
rasputyashka committed Sep 24, 2025
commit a81980f13e74ee18491cd7e6a253e1312b582dad
5 changes: 3 additions & 2 deletions src/fastapi_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,14 @@ def _run(
toolkit.print(root_tree, tag="module")
toolkit.print_line()

imported_object_type = "factory" if is_factory else "app"
toolkit.print(
"Importing the FastAPI app object from the module with the following code:",
f"Importing the FastAPI {imported_object_type} object from the module with the following code:",
tag="code",
)
toolkit.print_line()
toolkit.print(
f"[underline]from [bold]{module_data.module_import_str}[/bold] import [bold]{import_data.app_name}[/bold]"
f"[underline]from [bold]{module_data.module_import_str}[/bold] import [bold]{import_data.candidate_name}[/bold]"
)
toolkit.print_line()

Expand Down
28 changes: 11 additions & 17 deletions src/fastapi_cli/discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ def get_module_data_from_path(path: Path) -> ModuleData:
)


def get_app_name(
*, mod_data: ModuleData, app_name: Union[str, None] = None, is_factory: bool = False
) -> str:
def get_app_name(*, mod_data: ModuleData, app_name: Union[str, None] = None) -> str:
try:
mod = importlib.import_module(mod_data.module_import_str)
except (ImportError, ValueError) as e:
Expand All @@ -88,26 +86,19 @@ def get_app_name(
f"Could not find app name {app_name} in {mod_data.module_import_str}"
)
app = getattr(mod, app_name)
if not isinstance(app, FastAPI) and not is_factory:
if not isinstance(app, FastAPI):
raise FastAPICLIException(
f"The app name {app_name} in {mod_data.module_import_str} doesn't seem to be a FastAPI app"
)
else:
if not callable(app) and is_factory:
raise FastAPICLIException(
f"The app factory {app_name} in {mod_data.module_import_str} doesn't seem to be a function"
)
return app_name
for preferred_name in ["app", "api"]:
if preferred_name in object_names_set:
obj = getattr(mod, preferred_name)
if isinstance(obj, FastAPI) and not is_factory:
if isinstance(obj, FastAPI):
return preferred_name
for name in object_names:
obj = getattr(mod, name)
if isinstance(obj, FastAPI) and not is_factory:
return name
elif callable(name) and is_factory:
if isinstance(obj, FastAPI):
return name
raise FastAPICLIException(
"Could not find FastAPI app or app factory in module, try using --app"
Expand All @@ -116,13 +107,16 @@ def get_app_name(

@dataclass
class ImportData:
app_name: str
# candidate is an app or a factory
candidate_name: str
module_data: ModuleData
import_string: str


def get_import_data(
*, path: Union[Path, None] = None, app_name: Union[str, None] = None
*,
path: Union[Path, None] = None,
app_name: Union[str, None] = None,
) -> ImportData:
if not path:
path = get_default_path()
Expand All @@ -139,7 +133,7 @@ def get_import_data(
import_string = f"{mod_data.module_import_str}:{use_app_name}"

return ImportData(
app_name=use_app_name, module_data=mod_data, import_string=import_string
candidate_name=use_app_name, module_data=mod_data, import_string=import_string
)


Expand All @@ -156,7 +150,7 @@ def get_import_data_from_import_string(import_string: str) -> ImportData:
sys.path.insert(0, str(here))

return ImportData(
app_name=app_name,
candidate_name=app_name,
module_data=ModuleData(
module_import_str=module_str,
extra_sys_path=here,
Expand Down
Loading