fastapi-cli 0.0.10__tar.gz → 0.0.12__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.
Files changed (72) hide show
  1. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/PKG-INFO +1 -1
  2. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/pyproject.toml +1 -1
  3. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/requirements-tests.txt +2 -2
  4. fastapi_cli-0.0.12/src/fastapi_cli/__init__.py +1 -0
  5. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/src/fastapi_cli/cli.py +32 -7
  6. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/src/fastapi_cli/discover.py +23 -0
  7. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/test_cli.py +168 -0
  8. fastapi_cli-0.0.12/tests/test_discover.py +58 -0
  9. fastapi_cli-0.0.10/src/fastapi_cli/__init__.py +0 -1
  10. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/LICENSE +0 -0
  11. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/README.md +0 -0
  12. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/pdm_build.py +0 -0
  13. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/requirements-github-actions.txt +0 -0
  14. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/requirements.txt +0 -0
  15. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/scripts/format.sh +0 -0
  16. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/scripts/lint.sh +0 -0
  17. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/scripts/test-cov-html.sh +0 -0
  18. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/scripts/test.sh +0 -0
  19. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/src/fastapi_cli/__main__.py +0 -0
  20. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/src/fastapi_cli/exceptions.py +0 -0
  21. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/src/fastapi_cli/logging.py +0 -0
  22. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/src/fastapi_cli/py.typed +0 -0
  23. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/src/fastapi_cli/utils/__init__.py +0 -0
  24. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/src/fastapi_cli/utils/cli.py +0 -0
  25. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/__init__.py +0 -0
  26. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/broken_package/mod/__init__.py +0 -0
  27. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/broken_package/mod/app.py +0 -0
  28. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/broken_package/utils.py +0 -0
  29. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_api/api.py +0 -0
  30. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app/api.py +0 -0
  31. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app/app.py +0 -0
  32. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_api/app/__init__.py +0 -0
  33. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_api/app/api.py +0 -0
  34. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_app/app/__init__.py +0 -0
  35. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_app/app/api.py +0 -0
  36. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_app/app/app.py +0 -0
  37. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_main/app/__init__.py +0 -0
  38. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_main/app/api.py +0 -0
  39. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_main/app/app.py +0 -0
  40. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_main/app/main.py +0 -0
  41. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_non_default/app/__init__.py +0 -0
  42. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_app_dir_non_default/app/nondefault.py +0 -0
  43. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_main/api.py +0 -0
  44. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_main/app.py +0 -0
  45. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/default_main/main.py +0 -0
  46. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/default_files/non_default/nonstandard.py +0 -0
  47. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/nested_package/__init__.py +0 -0
  48. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/nested_package/package/__init__.py +0 -0
  49. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/nested_package/package/core/__init__.py +0 -0
  50. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/nested_package/package/core/utils.py +0 -0
  51. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/nested_package/package/mod/__init__.py +0 -0
  52. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/nested_package/package/mod/api.py +0 -0
  53. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/nested_package/package/mod/app.py +0 -0
  54. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/nested_package/package/mod/other.py +0 -0
  55. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/package/__init__.py +0 -0
  56. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/package/core/__init__.py +0 -0
  57. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/package/core/utils.py +0 -0
  58. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/package/mod/__init__.py +0 -0
  59. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/package/mod/api.py +0 -0
  60. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/package/mod/app.py +0 -0
  61. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/package/mod/other.py +0 -0
  62. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/single_file_api.py +0 -0
  63. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/single_file_app.py +0 -0
  64. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/assets/single_file_other.py +0 -0
  65. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/conftest.py +0 -0
  66. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/test_requirements.py +0 -0
  67. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/test_utils_cli.py +0 -0
  68. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/test_utils_default_dir.py +0 -0
  69. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/test_utils_default_file.py +0 -0
  70. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/test_utils_package.py +0 -0
  71. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/test_utils_single_file.py +0 -0
  72. {fastapi_cli-0.0.10 → fastapi_cli-0.0.12}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastapi-cli
3
- Version: 0.0.10
3
+ Version: 0.0.12
4
4
  Summary: Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀
5
5
  Author-Email: =?utf-8?q?Sebasti=C3=A1n_Ram=C3=ADrez?= <tiangolo@gmail.com>
6
6
  License: MIT
@@ -35,7 +35,7 @@ dependencies = [
35
35
  "uvicorn[standard] >= 0.15.0",
36
36
  "rich-toolkit >= 0.14.8",
37
37
  ]
38
- version = "0.0.10"
38
+ version = "0.0.12"
39
39
 
40
40
  [project.license]
41
41
  text = "MIT"
@@ -2,8 +2,8 @@
2
2
 
3
3
  pytest >=4.4.0,<9.0.0
4
4
  coverage[toml] >=6.2,<8.0
5
- mypy ==1.14.0
6
- ruff ==0.12.11
5
+ mypy ==1.14.1
6
+ ruff ==0.13.0
7
7
  # Needed explicitly by fastapi-cli-slim
8
8
  fastapi-slim
9
9
  uvicorn
@@ -0,0 +1 @@
1
+ __version__ = "0.0.12"
@@ -7,7 +7,7 @@ from rich import print
7
7
  from rich.tree import Tree
8
8
  from typing_extensions import Annotated
9
9
 
10
- from fastapi_cli.discover import get_import_data
10
+ from fastapi_cli.discover import get_import_data, get_import_data_from_import_string
11
11
  from fastapi_cli.exceptions import FastAPICLIException
12
12
 
13
13
  from . import __version__
@@ -95,6 +95,7 @@ def _run(
95
95
  root_path: str = "",
96
96
  command: str,
97
97
  app: Union[str, None] = None,
98
+ entrypoint: Union[str, None] = None,
98
99
  proxy_headers: bool = False,
99
100
  forwarded_allow_ips: Union[str, None] = None,
100
101
  ) -> None:
@@ -109,7 +110,10 @@ def _run(
109
110
  )
110
111
 
111
112
  try:
112
- import_data = get_import_data(path=path, app_name=app)
113
+ if entrypoint:
114
+ import_data = get_import_data_from_import_string(entrypoint)
115
+ else:
116
+ import_data = get_import_data(path=path, app_name=app)
113
117
  except FastAPICLIException as e:
114
118
  toolkit.print_line()
115
119
  toolkit.print(f"[error]{e}")
@@ -124,10 +128,11 @@ def _run(
124
128
  toolkit.print(f"Importing from {module_data.extra_sys_path}")
125
129
  toolkit.print_line()
126
130
 
127
- root_tree = _get_module_tree(module_data.module_paths)
131
+ if module_data.module_paths:
132
+ root_tree = _get_module_tree(module_data.module_paths)
128
133
 
129
- toolkit.print(root_tree, tag="module")
130
- toolkit.print_line()
134
+ toolkit.print(root_tree, tag="module")
135
+ toolkit.print_line()
131
136
 
132
137
  toolkit.print(
133
138
  "Importing the FastAPI app object from the module with the following code:",
@@ -201,7 +206,8 @@ def dev(
201
206
  port: Annotated[
202
207
  int,
203
208
  typer.Option(
204
- help="The port to serve on. You would normally have a termination proxy on top (another program) handling HTTPS on port [blue]443[/blue] and HTTP on port [blue]80[/blue], transferring the communication to your app."
209
+ help="The port to serve on. You would normally have a termination proxy on top (another program) handling HTTPS on port [blue]443[/blue] and HTTP on port [blue]80[/blue], transferring the communication to your app.",
210
+ envvar="PORT",
205
211
  ),
206
212
  ] = 8000,
207
213
  reload: Annotated[
@@ -222,6 +228,14 @@ def dev(
222
228
  help="The name of the variable that contains the [bold]FastAPI[/bold] app in the imported module or package. If not provided, it is detected automatically."
223
229
  ),
224
230
  ] = None,
231
+ entrypoint: Annotated[
232
+ Union[str, None],
233
+ typer.Option(
234
+ "--entrypoint",
235
+ "-e",
236
+ help="The FastAPI app import string in the format 'some.importable_module:app_name'.",
237
+ ),
238
+ ] = None,
225
239
  proxy_headers: Annotated[
226
240
  bool,
227
241
  typer.Option(
@@ -267,6 +281,7 @@ def dev(
267
281
  reload=reload,
268
282
  root_path=root_path,
269
283
  app=app,
284
+ entrypoint=entrypoint,
270
285
  command="dev",
271
286
  proxy_headers=proxy_headers,
272
287
  forwarded_allow_ips=forwarded_allow_ips,
@@ -291,7 +306,8 @@ def run(
291
306
  port: Annotated[
292
307
  int,
293
308
  typer.Option(
294
- help="The port to serve on. You would normally have a termination proxy on top (another program) handling HTTPS on port [blue]443[/blue] and HTTP on port [blue]80[/blue], transferring the communication to your app."
309
+ help="The port to serve on. You would normally have a termination proxy on top (another program) handling HTTPS on port [blue]443[/blue] and HTTP on port [blue]80[/blue], transferring the communication to your app.",
310
+ envvar="PORT",
295
311
  ),
296
312
  ] = 8000,
297
313
  reload: Annotated[
@@ -318,6 +334,14 @@ def run(
318
334
  help="The name of the variable that contains the [bold]FastAPI[/bold] app in the imported module or package. If not provided, it is detected automatically."
319
335
  ),
320
336
  ] = None,
337
+ entrypoint: Annotated[
338
+ Union[str, None],
339
+ typer.Option(
340
+ "--entrypoint",
341
+ "-e",
342
+ help="The FastAPI app import string in the format 'some.importable_module:app_name'.",
343
+ ),
344
+ ] = None,
321
345
  proxy_headers: Annotated[
322
346
  bool,
323
347
  typer.Option(
@@ -364,6 +388,7 @@ def run(
364
388
  workers=workers,
365
389
  root_path=root_path,
366
390
  app=app,
391
+ entrypoint=entrypoint,
367
392
  command="run",
368
393
  proxy_headers=proxy_headers,
369
394
  forwarded_allow_ips=forwarded_allow_ips,
@@ -130,3 +130,26 @@ def get_import_data(
130
130
  return ImportData(
131
131
  app_name=use_app_name, module_data=mod_data, import_string=import_string
132
132
  )
133
+
134
+
135
+ def get_import_data_from_import_string(import_string: str) -> ImportData:
136
+ module_str, _, app_name = import_string.partition(":")
137
+
138
+ if not module_str or not app_name:
139
+ raise FastAPICLIException(
140
+ "Import string must be in the format module.submodule:app_name"
141
+ )
142
+
143
+ here = Path(".").resolve()
144
+
145
+ sys.path.insert(0, str(here))
146
+
147
+ return ImportData(
148
+ app_name=app_name,
149
+ module_data=ModuleData(
150
+ module_import_str=module_str,
151
+ extra_sys_path=here,
152
+ module_paths=[],
153
+ ),
154
+ import_string=import_string,
155
+ )
@@ -122,6 +122,73 @@ def test_dev_args() -> None:
122
122
  )
123
123
 
124
124
 
125
+ def test_dev_env_vars() -> None:
126
+ with changing_dir(assets_path):
127
+ with patch.object(uvicorn, "run") as mock_run:
128
+ result = runner.invoke(
129
+ app, ["dev", "single_file_app.py"], env={"PORT": "8111"}
130
+ )
131
+ assert result.exit_code == 0, result.output
132
+ assert mock_run.called
133
+ assert mock_run.call_args
134
+ assert mock_run.call_args.kwargs == {
135
+ "app": "single_file_app:app",
136
+ "host": "127.0.0.1",
137
+ "port": 8111,
138
+ "reload": True,
139
+ "workers": None,
140
+ "root_path": "",
141
+ "proxy_headers": True,
142
+ "forwarded_allow_ips": None,
143
+ "log_config": get_uvicorn_log_config(),
144
+ }
145
+ assert "Using import string: single_file_app:app" in result.output
146
+ assert "Starting development server 🚀" in result.output
147
+ assert "Server started at http://127.0.0.1:8111" in result.output
148
+ assert "Documentation at http://127.0.0.1:8111/docs" in result.output
149
+ assert (
150
+ "Running in development mode, for production use: fastapi run"
151
+ in result.output
152
+ )
153
+
154
+
155
+ def test_dev_env_vars_and_args() -> None:
156
+ with changing_dir(assets_path):
157
+ with patch.object(uvicorn, "run") as mock_run:
158
+ result = runner.invoke(
159
+ app,
160
+ [
161
+ "dev",
162
+ "single_file_app.py",
163
+ "--port",
164
+ "8080",
165
+ ],
166
+ env={"PORT": "8111"},
167
+ )
168
+ assert result.exit_code == 0, result.output
169
+ assert mock_run.called
170
+ assert mock_run.call_args
171
+ assert mock_run.call_args.kwargs == {
172
+ "app": "single_file_app:app",
173
+ "host": "127.0.0.1",
174
+ "port": 8080,
175
+ "reload": True,
176
+ "workers": None,
177
+ "root_path": "",
178
+ "proxy_headers": True,
179
+ "forwarded_allow_ips": None,
180
+ "log_config": get_uvicorn_log_config(),
181
+ }
182
+ assert "Using import string: single_file_app:app" in result.output
183
+ assert "Starting development server 🚀" in result.output
184
+ assert "Server started at http://127.0.0.1:8080" in result.output
185
+ assert "Documentation at http://127.0.0.1:8080/docs" in result.output
186
+ assert (
187
+ "Running in development mode, for production use: fastapi run"
188
+ in result.output
189
+ )
190
+
191
+
125
192
  def test_run() -> None:
126
193
  with changing_dir(assets_path):
127
194
  with patch.object(uvicorn, "run") as mock_run:
@@ -223,6 +290,65 @@ def test_run_args() -> None:
223
290
  )
224
291
 
225
292
 
293
+ def test_run_env_vars() -> None:
294
+ with changing_dir(assets_path):
295
+ with patch.object(uvicorn, "run") as mock_run:
296
+ result = runner.invoke(
297
+ app, ["run", "single_file_app.py"], env={"PORT": "8111"}
298
+ )
299
+ assert result.exit_code == 0, result.output
300
+ assert mock_run.called
301
+ assert mock_run.call_args
302
+ assert mock_run.call_args.kwargs == {
303
+ "app": "single_file_app:app",
304
+ "host": "0.0.0.0",
305
+ "port": 8111,
306
+ "reload": False,
307
+ "workers": None,
308
+ "root_path": "",
309
+ "proxy_headers": True,
310
+ "forwarded_allow_ips": None,
311
+ "log_config": get_uvicorn_log_config(),
312
+ }
313
+ assert "Using import string: single_file_app:app" in result.output
314
+ assert "Starting production server 🚀" in result.output
315
+ assert "Server started at http://0.0.0.0:8111" in result.output
316
+ assert "Documentation at http://0.0.0.0:8111/docs" in result.output
317
+
318
+
319
+ def test_run_env_vars_and_args() -> None:
320
+ with changing_dir(assets_path):
321
+ with patch.object(uvicorn, "run") as mock_run:
322
+ result = runner.invoke(
323
+ app,
324
+ [
325
+ "run",
326
+ "single_file_app.py",
327
+ "--port",
328
+ "8080",
329
+ ],
330
+ env={"PORT": "8111"},
331
+ )
332
+ assert result.exit_code == 0, result.output
333
+ assert mock_run.called
334
+ assert mock_run.call_args
335
+ assert mock_run.call_args.kwargs == {
336
+ "app": "single_file_app:app",
337
+ "host": "0.0.0.0",
338
+ "port": 8080,
339
+ "reload": False,
340
+ "workers": None,
341
+ "root_path": "",
342
+ "proxy_headers": True,
343
+ "forwarded_allow_ips": None,
344
+ "log_config": get_uvicorn_log_config(),
345
+ }
346
+ assert "Using import string: single_file_app:app" in result.output
347
+ assert "Starting production server 🚀" in result.output
348
+ assert "Server started at http://0.0.0.0:8080" in result.output
349
+ assert "Documentation at http://0.0.0.0:8080/docs" in result.output
350
+
351
+
226
352
  def test_run_error() -> None:
227
353
  with changing_dir(assets_path):
228
354
  result = runner.invoke(app, ["run", "non_existing_file.py"])
@@ -285,6 +411,48 @@ def test_version() -> None:
285
411
  assert "FastAPI CLI version:" in result.output
286
412
 
287
413
 
414
+ def test_dev_with_import_string() -> None:
415
+ with changing_dir(assets_path):
416
+ with patch.object(uvicorn, "run") as mock_run:
417
+ result = runner.invoke(app, ["dev", "--entrypoint", "single_file_app:api"])
418
+ assert result.exit_code == 0, result.output
419
+ assert mock_run.called
420
+ assert mock_run.call_args
421
+ assert mock_run.call_args.kwargs == {
422
+ "app": "single_file_app:api",
423
+ "forwarded_allow_ips": None,
424
+ "host": "127.0.0.1",
425
+ "port": 8000,
426
+ "reload": True,
427
+ "workers": None,
428
+ "root_path": "",
429
+ "proxy_headers": True,
430
+ "log_config": get_uvicorn_log_config(),
431
+ }
432
+ assert "Using import string: single_file_app:api" in result.output
433
+
434
+
435
+ def test_run_with_import_string() -> None:
436
+ with changing_dir(assets_path):
437
+ with patch.object(uvicorn, "run") as mock_run:
438
+ result = runner.invoke(app, ["run", "--entrypoint", "single_file_app:app"])
439
+ assert result.exit_code == 0, result.output
440
+ assert mock_run.called
441
+ assert mock_run.call_args
442
+ assert mock_run.call_args.kwargs == {
443
+ "app": "single_file_app:app",
444
+ "forwarded_allow_ips": None,
445
+ "host": "0.0.0.0",
446
+ "port": 8000,
447
+ "reload": False,
448
+ "workers": None,
449
+ "root_path": "",
450
+ "proxy_headers": True,
451
+ "log_config": get_uvicorn_log_config(),
452
+ }
453
+ assert "Using import string: single_file_app:app" in result.output
454
+
455
+
288
456
  def test_script() -> None:
289
457
  result = subprocess.run(
290
458
  [sys.executable, "-m", "coverage", "run", "-m", "fastapi_cli", "--help"],
@@ -0,0 +1,58 @@
1
+ from pathlib import Path
2
+
3
+ import pytest
4
+
5
+ from fastapi_cli.discover import (
6
+ ImportData,
7
+ get_import_data_from_import_string,
8
+ )
9
+ from fastapi_cli.exceptions import FastAPICLIException
10
+
11
+ assets_path = Path(__file__).parent / "assets"
12
+
13
+
14
+ def test_get_import_data_from_import_string_valid() -> None:
15
+ result = get_import_data_from_import_string("module.submodule:app")
16
+
17
+ assert isinstance(result, ImportData)
18
+ assert result.app_name == "app"
19
+ assert result.import_string == "module.submodule:app"
20
+ assert result.module_data.module_import_str == "module.submodule"
21
+ assert result.module_data.extra_sys_path == Path(".").resolve()
22
+ assert result.module_data.module_paths == []
23
+
24
+
25
+ def test_get_import_data_from_import_string_missing_colon() -> None:
26
+ with pytest.raises(FastAPICLIException) as exc_info:
27
+ get_import_data_from_import_string("module.submodule")
28
+
29
+ assert "Import string must be in the format module.submodule:app_name" in str(
30
+ exc_info.value
31
+ )
32
+
33
+
34
+ def test_get_import_data_from_import_string_missing_app() -> None:
35
+ with pytest.raises(FastAPICLIException) as exc_info:
36
+ get_import_data_from_import_string("module.submodule:")
37
+
38
+ assert "Import string must be in the format module.submodule:app_name" in str(
39
+ exc_info.value
40
+ )
41
+
42
+
43
+ def test_get_import_data_from_import_string_missing_module() -> None:
44
+ with pytest.raises(FastAPICLIException) as exc_info:
45
+ get_import_data_from_import_string(":app")
46
+
47
+ assert "Import string must be in the format module.submodule:app_name" in str(
48
+ exc_info.value
49
+ )
50
+
51
+
52
+ def test_get_import_data_from_import_string_empty() -> None:
53
+ with pytest.raises(FastAPICLIException) as exc_info:
54
+ get_import_data_from_import_string("")
55
+
56
+ assert "Import string must be in the format module.submodule:app_name" in str(
57
+ exc_info.value
58
+ )
@@ -1 +0,0 @@
1
- __version__ = "0.0.10"
File without changes
File without changes
File without changes