"""Executable application entrypoint is defined here.""" import os import tempfile import typing as tp from pathlib import Path import click import uvicorn from dotenv import load_dotenv from .config import {{ProjectName}}Config @click.group() def cli(): "{{project_name}} service executable script" @cli.command("config-example") @click.option( "--config_path", envvar="CONFIG_PATH", default="config.yaml", type=click.Path(dir_okay=False, path_type=Path), show_default=True, show_envvar=True, help="Path to YAML configuration file", ) def get_config_example(config_path: Path): config = {{ProjectName}}Config.get_example() config.dump(config_path) @cli.command("launch") @click.option( "--config_path", envvar="CONFIG_PATH", default="config.yaml", type=click.Path(exists=True, dir_okay=False, path_type=Path), show_default=True, show_envvar=True, help="Path to YAML configuration file", ) def launch( config_path: Path, ): """ {{project_description}} Performs configuration via config and command line + environment variables overrides. """ print( "This is a simple method to run the API. You might want to use" " 'uvicorn {{project_slug}}.fastapi_init:app' instead to configure more uvicorn options." ) config = {{ProjectName}}Config.load(config_path) with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_yaml_config_path = temp_file.name config.dump(temp_yaml_config_path) with tempfile.NamedTemporaryFile(delete=False) as temp_file: temp_envfile_path = temp_file.name with open(temp_envfile_path, "w", encoding="utf-8") as env_file: env_file.write(f"CONFIG_PATH={temp_yaml_config_path}\n") try: uvicorn_config = { "host": config.app.uvicorn.host, "port": config.app.uvicorn.port, "forwarded_allow_ips": config.app.uvicorn.forwarded_allow_ips, "log_level": config.observability.logging.root_logger_level.lower(), "env_file": temp_envfile_path, "access_log": False, } if config.app.debug: try: _run_uvicorn(uvicorn_config | {"reload": True}) except: # pylint: disable=bare-except print("Retrying with Uvicorn reload disabled") _run_uvicorn(uvicorn_config) else: _run_uvicorn(uvicorn_config) finally: if os.path.exists(temp_envfile_path): os.remove(temp_envfile_path) if os.path.exists(temp_yaml_config_path): os.remove(temp_yaml_config_path) def _run_uvicorn(configuration: dict[str, tp.Any]) -> tp.NoReturn: uvicorn.run( "{{project_slug}}.fastapi_init:app", **configuration, ) if __name__ in ("__main__", "{{project_slug}}.__main__"): load_dotenv(os.environ.get("ENVFILE", ".env")) cli() # pylint: disable=no-value-for-parameter