Coverage for tests/test_utils_package.py: 100%

119 statements  

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

1from pathlib import Path 1abcdefghijklmn

2 

3import pytest 1abcdefghijklmn

4from pytest import CaptureFixture 1abcdefghijklmn

5 

6from fastapi_cli.discover import get_import_data 1abcdefghijklmn

7from fastapi_cli.exceptions import FastAPICLIException 1abcdefghijklmn

8from tests.utils import changing_dir 1abcdefghijklmn

9 

10assets_path = Path(__file__).parent / "assets" 1abcdefghijklmn

11 

12 

13def test_package_app_root() -> None: 1abcdefghijklmn

14 with changing_dir(assets_path): 1CDEFGHIJKLMNOP

15 import_data = get_import_data(path=Path("package/mod/app.py")) 1CDEFGHIJKLMNOP

16 

17 assert import_data.import_string == "package.mod.app:app" 1CDEFGHIJKLMNOP

18 

19 assert import_data.module_data.extra_sys_path == assets_path 1CDEFGHIJKLMNOP

20 assert import_data.module_data.module_import_str == "package.mod.app" 1CDEFGHIJKLMNOP

21 

22 

23def test_package_api_root() -> None: 1abcdefghijklmn

24 with changing_dir(assets_path): 1QRSTUVWXYZ0123

25 import_data = get_import_data(path=Path("package/mod/api.py")) 1QRSTUVWXYZ0123

26 

27 assert import_data.import_string == "package.mod.api:api" 1QRSTUVWXYZ0123

28 

29 assert import_data.module_data.extra_sys_path == assets_path 1QRSTUVWXYZ0123

30 assert import_data.module_data.module_import_str == "package.mod.api" 1QRSTUVWXYZ0123

31 

32 

33def test_package_other_root() -> None: 1abcdefghijklmn

34 with changing_dir(assets_path): 1456789!#$%'()*

35 import_data = get_import_data(path=Path("package/mod/other.py")) 1456789!#$%'()*

36 

37 assert import_data.import_string == "package.mod.other:first_other" 1456789!#$%'()*

38 

39 assert import_data.module_data.extra_sys_path == assets_path 1456789!#$%'()*

40 assert import_data.module_data.module_import_str == "package.mod.other" 1456789!#$%'()*

41 

42 

43def test_package_app_mod() -> None: 1abcdefghijklmn

44 with changing_dir(assets_path / "package/mod"): 1+,-./:;=?@[]^_

45 import_data = get_import_data(path=Path("app.py")) 1+,-./:;=?@[]^_

46 

47 assert import_data.import_string == "package.mod.app:app" 1+,-./:;=?@[]^_

48 

49 assert import_data.module_data.extra_sys_path == assets_path 1+,-./:;=?@[]^_

50 assert import_data.module_data.module_import_str == "package.mod.app" 1+,-./:;=?@[]^_

51 

52 

53def test_package_api_mod() -> None: 1abcdefghijklmn

54 with changing_dir(assets_path / "package/mod"): 2` { | } ~ abbbcbdbebfbgbhbib

55 import_data = get_import_data(path=Path("api.py")) 2` { | } ~ abbbcbdbebfbgbhbib

56 

57 assert import_data.import_string == "package.mod.api:api" 2` { | } ~ abbbcbdbebfbgbhbib

58 

59 assert import_data.module_data.extra_sys_path == assets_path 2` { | } ~ abbbcbdbebfbgbhbib

60 assert import_data.module_data.module_import_str == "package.mod.api" 2` { | } ~ abbbcbdbebfbgbhbib

61 

62 

63def test_package_other_mod() -> None: 1abcdefghijklmn

64 with changing_dir(assets_path / "package/mod"): 2jbkblbmbnbobpbqbrbsbtbubvbwb

65 import_data = get_import_data(path=Path("other.py")) 2jbkblbmbnbobpbqbrbsbtbubvbwb

66 

67 assert import_data.import_string == "package.mod.other:first_other" 2jbkblbmbnbobpbqbrbsbtbubvbwb

68 

69 assert import_data.module_data.extra_sys_path == assets_path 2jbkblbmbnbobpbqbrbsbtbubvbwb

70 assert import_data.module_data.module_import_str == "package.mod.other" 2jbkblbmbnbobpbqbrbsbtbubvbwb

71 

72 

73def test_package_app_above() -> None: 1abcdefghijklmn

74 with changing_dir(assets_path.parent): 2xbybzbAbBbCbDbEbFbGbHbIbJbKb

75 import_data = get_import_data(path=Path("assets/package/mod/app.py")) 2xbybzbAbBbCbDbEbFbGbHbIbJbKb

76 

77 assert import_data.import_string == "package.mod.app:app" 2xbybzbAbBbCbDbEbFbGbHbIbJbKb

78 

79 assert import_data.module_data.extra_sys_path == assets_path 2xbybzbAbBbCbDbEbFbGbHbIbJbKb

80 assert import_data.module_data.module_import_str == "package.mod.app" 2xbybzbAbBbCbDbEbFbGbHbIbJbKb

81 

82 

83def test_package_api_parent() -> None: 1abcdefghijklmn

84 with changing_dir(assets_path.parent): 2LbMbNbObPbQbRbSbTbUbVbWbXbYb

85 import_data = get_import_data(path=Path("assets/package/mod/api.py")) 2LbMbNbObPbQbRbSbTbUbVbWbXbYb

86 

87 assert import_data.import_string == "package.mod.api:api" 2LbMbNbObPbQbRbSbTbUbVbWbXbYb

88 

89 assert import_data.module_data.extra_sys_path == assets_path 2LbMbNbObPbQbRbSbTbUbVbWbXbYb

90 assert import_data.module_data.module_import_str == "package.mod.api" 2LbMbNbObPbQbRbSbTbUbVbWbXbYb

91 

92 

93def test_package_other_parent() -> None: 1abcdefghijklmn

94 with changing_dir(assets_path.parent): 2Zb0b1b2b3b4b5b6b7b8b9b!b#b$b

95 import_data = get_import_data(path=Path("assets/package/mod/other.py")) 2Zb0b1b2b3b4b5b6b7b8b9b!b#b$b

96 

97 assert import_data.import_string == "package.mod.other:first_other" 2Zb0b1b2b3b4b5b6b7b8b9b!b#b$b

98 

99 assert import_data.module_data.extra_sys_path == assets_path 2Zb0b1b2b3b4b5b6b7b8b9b!b#b$b

100 assert import_data.module_data.module_import_str == "package.mod.other" 2Zb0b1b2b3b4b5b6b7b8b9b!b#b$b

101 

102 

103def test_package_mod_init_inside() -> None: 1abcdefghijklmn

104 with changing_dir(assets_path / "package/mod"): 2%b'b(b)b*b+b,b-b.b/b:b;b=b?b

105 import_data = get_import_data(path=Path("__init__.py")) 2%b'b(b)b*b+b,b-b.b/b:b;b=b?b

106 assert import_data.import_string == "package.mod:app" 2%b'b(b)b*b+b,b-b.b/b:b;b=b?b

107 

108 assert import_data.module_data.extra_sys_path == assets_path 2%b'b(b)b*b+b,b-b.b/b:b;b=b?b

109 assert import_data.module_data.module_import_str == "package.mod" 2%b'b(b)b*b+b,b-b.b/b:b;b=b?b

110 

111 

112def test_package_mod_dir() -> None: 1abcdefghijklmn

113 with changing_dir(assets_path): 2@b[b]b^b_b`b{b|b}b~bacbcccdc

114 import_data = get_import_data(path=Path("package/mod")) 2@b[b]b^b_b`b{b|b}b~bacbcccdc

115 

116 assert import_data.import_string == "package.mod:app" 2@b[b]b^b_b`b{b|b}b~bacbcccdc

117 

118 assert import_data.module_data.extra_sys_path == assets_path 2@b[b]b^b_b`b{b|b}b~bacbcccdc

119 assert import_data.module_data.module_import_str == "package.mod" 2@b[b]b^b_b`b{b|b}b~bacbcccdc

120 

121 

122def test_package_init_inside() -> None: 1abcdefghijklmn

123 with changing_dir(assets_path / "package"): 2ecfcgchcicjckclcmcncocpcqcrc

124 import_data = get_import_data(path=Path("__init__.py")) 2ecfcgchcicjckclcmcncocpcqcrc

125 

126 assert import_data.import_string == "package:app" 2ecfcgchcicjckclcmcncocpcqcrc

127 

128 assert import_data.module_data.extra_sys_path == assets_path 2ecfcgchcicjckclcmcncocpcqcrc

129 assert import_data.module_data.module_import_str == "package" 2ecfcgchcicjckclcmcncocpcqcrc

130 

131 

132def test_package_dir_inside_package() -> None: 1abcdefghijklmn

133 with changing_dir(assets_path / "package/mod"): 2sctcucvcwcxcyczcAcBcCcDcEcFc

134 import_data = get_import_data(path=Path("../")) 2sctcucvcwcxcyczcAcBcCcDcEcFc

135 

136 assert import_data.import_string == "package:app" 2sctcucvcwcxcyczcAcBcCcDcEcFc

137 assert import_data.module_data.extra_sys_path == assets_path 2sctcucvcwcxcyczcAcBcCcDcEcFc

138 assert import_data.module_data.module_import_str == "package" 2sctcucvcwcxcyczcAcBcCcDcEcFc

139 

140 

141def test_package_dir_above_package() -> None: 1abcdefghijklmn

142 with changing_dir(assets_path.parent): 2GcHcIcJcKcLcMcNcOcPcQcRcScTc

143 import_data = get_import_data(path=Path("assets/package")) 2GcHcIcJcKcLcMcNcOcPcQcRcScTc

144 

145 assert import_data.import_string == "package:app" 2GcHcIcJcKcLcMcNcOcPcQcRcScTc

146 

147 assert import_data.module_data.extra_sys_path == assets_path 2GcHcIcJcKcLcMcNcOcPcQcRcScTc

148 assert import_data.module_data.module_import_str == "package" 2GcHcIcJcKcLcMcNcOcPcQcRcScTc

149 

150 

151def test_package_dir_explicit_app() -> None: 1abcdefghijklmn

152 with changing_dir(assets_path): 2UcVcWcXcYcZc0c1c2c3c4c5c6c7c

153 import_data = get_import_data(path=Path("package"), app_name="api") 2UcVcWcXcYcZc0c1c2c3c4c5c6c7c

154 

155 assert import_data.import_string == "package:api" 2UcVcWcXcYcZc0c1c2c3c4c5c6c7c

156 

157 assert import_data.module_data.extra_sys_path == assets_path 2UcVcWcXcYcZc0c1c2c3c4c5c6c7c

158 assert import_data.module_data.module_import_str == "package" 2UcVcWcXcYcZc0c1c2c3c4c5c6c7c

159 

160 

161def test_broken_package_dir(capsys: CaptureFixture[str]) -> None: 1abcdefghijklmn

162 with changing_dir(assets_path): 1opqrstuvwxyzAB

163 # TODO (when deprecating Python 3.8): remove ValueError 

164 with pytest.raises((ImportError, ValueError)): 1opqrstuvwxyzAB

165 get_import_data(path=Path("broken_package/mod/app.py")) 1opqrstuvwxyzAB

166 

167 captured = capsys.readouterr() 1opqrstuvwxyzAB

168 assert "Import error:" in captured.out 1opqrstuvwxyzAB

169 assert "Ensure all the package directories have an __init__.py file" in captured.out 1opqrstuvwxyzAB

170 

171 

172def test_package_dir_no_app() -> None: 1abcdefghijklmn

173 with changing_dir(assets_path): 28c9c!c#c$c%c'c(c)c*c+c,c-c.c

174 with pytest.raises(FastAPICLIException) as e: 28c9c!c#c$c%c'c(c)c*c+c,c-c.c

175 get_import_data(path=Path("package/core/utils.py")) 28c9c!c#c$c%c'c(c)c*c+c,c-c.c

176 assert ( 28c9c!c#c$c%c'c(c)c*c+c,c-c.c

177 "Could not find FastAPI app in module, try using --app" in e.value.args[0] 

178 ) 

179 

180 

181def test_package_dir_object_not_an_app() -> None: 1abcdefghijklmn

182 with changing_dir(assets_path): 2/c:c;c=c?c@c[c]c^c_c`c{c|c}c

183 with pytest.raises(FastAPICLIException) as e: 2/c:c;c=c?c@c[c]c^c_c`c{c|c}c

184 get_import_data( 2/c:c;c=c?c@c[c]c^c_c`c{c|c}c

185 path=Path("package/core/utils.py"), app_name="get_hello_world" 

186 ) 

187 assert ( 2/c:c;c=c?c@c[c]c^c_c`c{c|c}c

188 "The app name get_hello_world in package.core.utils doesn't seem to be a FastAPI app" 

189 in e.value.args[0] 

190 ) 

191 

192 

193def test_package_dir_object_app_name_not_found() -> None: 1abcdefghijklmn

194 with changing_dir(assets_path): 2~cadbdcdddedfdgdhdidjdkdldmd

195 with pytest.raises(FastAPICLIException) as e: 2~cadbdcdddedfdgdhdidjdkdldmd

196 get_import_data(path=Path("package"), app_name="non_existent_app") 2~cadbdcdddedfdgdhdidjdkdldmd

197 assert "Could not find app name non_existent_app in package" in e.value.args[0] 2~cadbdcdddedfdgdhdidjdkdldmd