Coverage for src/fastapi_cloud_cli/commands/apps/unlink.py: 100%

36 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-11-09 00:25 +0000

1import logging 1abcdefg

2from pathlib import Path 1abcdefg

3from typing import Annotated, Any 1abcdefg

4 

5import typer 1abcdefg

6from pydantic import BaseModel, Field 1abcdefg

7from rich.text import Text 1abcdefg

8from rich_toolkit import RichToolkit 1abcdefg

9 

10from fastapi_cloud_cli._app import cloud_app 1abcdefg

11from fastapi_cloud_cli.commands.apps._app import apps_app 1abcdefg

12from fastapi_cloud_cli.utils.cli import FastAPIRichToolkit, get_rich_toolkit 1abcdefg

13from fastapi_cloud_cli.utils.execution import JsonOutputOption 1abcdefg

14 

15logger = logging.getLogger(__name__) 1abcdefg

16 

17 

18class UnlinkOutput(BaseModel): 1abcdefg

19 unlinked: bool 1abcdefg

20 path: Annotated[Path, Field(exclude=True)] 1abcdefg

21 removed_path: Path 1abcdefg

22 path_provided: Annotated[bool, Field(exclude=True)] = False 1abcdefg

23 

24 

25def _render_unlink_output(data: UnlinkOutput, toolkit: RichToolkit) -> None: 1abhcdiefgj

26 removed_path = ( 1klhmnoipqrstju

27 data.removed_path 

28 if data.path_provided 

29 else data.removed_path.relative_to(Path.cwd()) 

30 ) 

31 

32 toolkit.print("Removed app link", emoji="🔗") 1klhmnoipqrstju

33 toolkit.print_line() 1klhmnoipqrstju

34 toolkit.print(Text(f"Deleted {removed_path}", style="dim")) 1klhmnoipqrstju

35 

36 

37def _fail_not_linked(toolkit: FastAPIRichToolkit) -> None: 1abcdefg

38 toolkit.fail( 1vwxyzABCDEFGHI

39 "not_linked", 

40 "No app is linked to this directory.", 

41 hint="Run `fastapi cloud link` to link an app.", 

42 ) 

43 

44 

45@cloud_app.command("unlink") 1abcdefg

46@apps_app.command("unlink") 1abcdefg

47def unlink_app( 1abXcdYefgZ

48 path: Annotated[ 

49 Path | None, 

50 typer.Option( 

51 "--path", 

52 help="Directory to unlink.", 

53 ), 

54 ] = None, 

55 json_output: JsonOutputOption = False, 

56) -> Any: 

57 """ 

58 Unlink by deleting the `.fastapicloud/cloud.json` file. 

59 """ 

60 path_to_unlink = path or Path.cwd() 1JvkKlwLxhMmyNznOoAPBiQpCRDqSrETFsUtGVHjWuI

61 config_path = path_to_unlink / ".fastapicloud/cloud.json" 1JvkKlwLxhMmyNznOoAPBiQpCRDqSrETFsUtGVHjWuI

62 

63 with get_rich_toolkit(json_output=json_output) as toolkit: 1JvkKlwLxhMmyNznOoAPBiQpCRDqSrETFsUtGVHjWuI

64 if not config_path.exists(): 1JvkKlwLxhMmyNznOoAPBiQpCRDqSrETFsUtGVHjWuI

65 logger.debug(f"Configuration file not found: {config_path}") 1vwxyzABCDEFGHI

66 _fail_not_linked(toolkit) 1vwxyzABCDEFGHI

67 

68 config_path.unlink() 1JkKlLhMmNnOoPiQpRqSrTsUtVjWu

69 logger.debug(f"Deleted configuration file: {config_path}") 1JkKlLhMmNnOoPiQpRqSrTsUtVjWu

70 

71 toolkit.success( 1JkKlLhMmNnOoPiQpRqSrTsUtVjWu

72 UnlinkOutput( 

73 unlinked=True, 

74 path=path_to_unlink, 

75 removed_path=config_path, 

76 path_provided=path is not None, 

77 ), 

78 render_output=_render_unlink_output, 

79 )