fastapi-cloud-cli 0.15.0__tar.gz → 0.15.1__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 (85) hide show
  1. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/PKG-INFO +1 -1
  2. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/pyproject.toml +1 -1
  3. fastapi_cloud_cli-0.15.1/src/fastapi_cloud_cli/__init__.py +1 -0
  4. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/deploy.py +2 -0
  5. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_cli_deploy.py +80 -2
  6. fastapi_cloud_cli-0.15.0/src/fastapi_cloud_cli/__init__.py +0 -1
  7. fastapi_cloud_cli-0.15.0/tests/assets/broken_package/mod/__init__.py +0 -1
  8. fastapi_cloud_cli-0.15.0/tests/assets/broken_package/mod/app.py +0 -10
  9. fastapi_cloud_cli-0.15.0/tests/assets/broken_package/utils.py +0 -2
  10. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_api/api.py +0 -8
  11. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app/api.py +0 -8
  12. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app/app.py +0 -8
  13. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_api/app/__init__.py +0 -0
  14. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_api/app/api.py +0 -8
  15. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_app/app/__init__.py +0 -0
  16. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_app/app/api.py +0 -8
  17. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_app/app/app.py +0 -8
  18. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_main/app/__init__.py +0 -0
  19. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_main/app/api.py +0 -8
  20. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_main/app/app.py +0 -8
  21. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_main/app/main.py +0 -8
  22. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_non_default/app/__init__.py +0 -0
  23. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_app_dir_non_default/app/nondefault.py +0 -8
  24. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_main/api.py +0 -8
  25. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_main/app.py +0 -8
  26. fastapi_cloud_cli-0.15.0/tests/assets/default_files/default_main/main.py +0 -8
  27. fastapi_cloud_cli-0.15.0/tests/assets/default_files/non_default/nonstandard.py +0 -8
  28. fastapi_cloud_cli-0.15.0/tests/assets/package/__init__.py +0 -2
  29. fastapi_cloud_cli-0.15.0/tests/assets/package/core/__init__.py +0 -0
  30. fastapi_cloud_cli-0.15.0/tests/assets/package/core/utils.py +0 -2
  31. fastapi_cloud_cli-0.15.0/tests/assets/package/mod/__init__.py +0 -1
  32. fastapi_cloud_cli-0.15.0/tests/assets/package/mod/api.py +0 -24
  33. fastapi_cloud_cli-0.15.0/tests/assets/package/mod/app.py +0 -32
  34. fastapi_cloud_cli-0.15.0/tests/assets/package/mod/other.py +0 -16
  35. fastapi_cloud_cli-0.15.0/tests/assets/single_file_api.py +0 -24
  36. fastapi_cloud_cli-0.15.0/tests/assets/single_file_app.py +0 -32
  37. fastapi_cloud_cli-0.15.0/tests/assets/single_file_other.py +0 -16
  38. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/LICENSE +0 -0
  39. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/README.md +0 -0
  40. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/scripts/format.sh +0 -0
  41. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/scripts/lint.sh +0 -0
  42. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/scripts/test-cov-html.sh +0 -0
  43. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/scripts/test.sh +0 -0
  44. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/__main__.py +0 -0
  45. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/cli.py +0 -0
  46. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/__init__.py +0 -0
  47. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/env.py +0 -0
  48. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/link.py +0 -0
  49. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/login.py +0 -0
  50. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/logout.py +0 -0
  51. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/logs.py +0 -0
  52. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/setup_ci.py +0 -0
  53. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/unlink.py +0 -0
  54. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/commands/whoami.py +0 -0
  55. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/config.py +0 -0
  56. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/logging.py +0 -0
  57. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/py.typed +0 -0
  58. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/utils/__init__.py +0 -0
  59. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/utils/api.py +0 -0
  60. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/utils/apps.py +0 -0
  61. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/utils/auth.py +0 -0
  62. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/utils/cli.py +0 -0
  63. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/utils/config.py +0 -0
  64. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/utils/env.py +0 -0
  65. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/src/fastapi_cloud_cli/utils/sentry.py +0 -0
  66. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/__init__.py +0 -0
  67. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/conftest.py +0 -0
  68. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_api_client.py +0 -0
  69. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_archive.py +0 -0
  70. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_auth.py +0 -0
  71. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_cli.py +0 -0
  72. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_cli_link.py +0 -0
  73. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_cli_login.py +0 -0
  74. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_cli_logout.py +0 -0
  75. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_cli_setup_ci.py +0 -0
  76. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_cli_unlink.py +0 -0
  77. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_cli_whoami.py +0 -0
  78. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_config.py +0 -0
  79. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_deploy_utils.py +0 -0
  80. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_env_delete.py +0 -0
  81. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_env_list.py +0 -0
  82. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_env_set.py +0 -0
  83. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_logs.py +0 -0
  84. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/test_sentry.py +0 -0
  85. {fastapi_cloud_cli-0.15.0 → fastapi_cloud_cli-0.15.1}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastapi-cloud-cli
3
- Version: 0.15.0
3
+ Version: 0.15.1
4
4
  Summary: Deploy and manage FastAPI Cloud apps from the command line 🚀
5
5
  Author-Email: Patrick Arminio <patrick@fastapilabs.com>
6
6
  License: MIT
@@ -40,7 +40,7 @@ dependencies = [
40
40
  "sentry-sdk >= 2.20.0",
41
41
  "fastar >= 0.8.0",
42
42
  ]
43
- version = "0.15.0"
43
+ version = "0.15.1"
44
44
 
45
45
  [project.license]
46
46
  text = "MIT"
@@ -0,0 +1 @@
1
+ __version__ = "0.15.1"
@@ -304,6 +304,7 @@ def _configure_app(toolkit: RichToolkit, path_to_deploy: Path) -> AppConfig:
304
304
  "Select the team you want to deploy to:",
305
305
  tag="team",
306
306
  options=[Option({"name": team.name, "value": team}) for team in teams],
307
+ allow_filtering=True,
307
308
  )
308
309
 
309
310
  toolkit.print_line()
@@ -335,6 +336,7 @@ def _configure_app(toolkit: RichToolkit, path_to_deploy: Path) -> AppConfig:
335
336
  selected_app = toolkit.ask(
336
337
  "Select the app you want to deploy to:",
337
338
  options=[Option({"name": app.slug, "value": app}) for app in apps],
339
+ allow_filtering=True,
338
340
  )
339
341
 
340
342
  app_name = (
@@ -24,8 +24,8 @@ runner = CliRunner()
24
24
  assets_path = Path(__file__).parent / "assets"
25
25
 
26
26
 
27
- def _get_random_team() -> dict[str, str]:
28
- name = "".join(random.choices(string.ascii_lowercase, k=10))
27
+ def _get_random_team(name: str | None = None) -> dict[str, str]:
28
+ name = name or "".join(random.choices(string.ascii_lowercase, k=10))
29
29
  slug = "".join(random.choices(string.ascii_lowercase, k=10))
30
30
  id = "".join(random.choices(string.digits, k=10))
31
31
 
@@ -323,6 +323,42 @@ def test_shows_teams(
323
323
  assert team_2["name"] in result.output
324
324
 
325
325
 
326
+ @pytest.mark.respx
327
+ def test_filter_teams(
328
+ logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
329
+ ) -> None:
330
+ steps = [*"al", Keys.ENTER, Keys.CTRL_C]
331
+
332
+ team_1 = _get_random_team(name="Alpha Team")
333
+ team_2 = _get_random_team(name="Beta Team")
334
+
335
+ respx_mock.get("/teams/").mock(
336
+ return_value=Response(
337
+ 200,
338
+ json={"data": [team_1, team_2]},
339
+ )
340
+ )
341
+
342
+ with (
343
+ changing_dir(tmp_path),
344
+ patch("rich_toolkit.container.getchar") as mock_getchar,
345
+ ):
346
+ mock_getchar.side_effect = steps
347
+
348
+ result = runner.invoke(app, ["deploy"])
349
+
350
+ assert result.exit_code == 1
351
+
352
+ assert "Filter: al" in result.output
353
+
354
+ # Truncate part of the output before "Filter: al"
355
+ filer_pos = result.output.rfind("Filter: al")
356
+ last_output = result.output[filer_pos:]
357
+
358
+ assert team_1["name"] in last_output
359
+ assert team_2["name"] not in last_output
360
+
361
+
326
362
  @pytest.mark.respx
327
363
  def test_asks_for_app_name_after_team(
328
364
  logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
@@ -349,6 +385,48 @@ def test_asks_for_app_name_after_team(
349
385
  assert "What's your app name?" in result.output
350
386
 
351
387
 
388
+ @pytest.mark.respx
389
+ def test_filter_apps(
390
+ logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
391
+ ) -> None:
392
+ steps = [Keys.ENTER, Keys.RIGHT_ARROW, Keys.ENTER, *"an", Keys.ENTER, Keys.CTRL_C]
393
+
394
+ team = _get_random_team()
395
+
396
+ respx_mock.get("/teams/").mock(
397
+ return_value=Response(
398
+ 200,
399
+ json={"data": [team]},
400
+ )
401
+ )
402
+
403
+ app_1 = _get_random_app(team_id=team["id"], slug="My App")
404
+ app_2 = _get_random_app(team_id=team["id"], slug="Another App")
405
+
406
+ respx_mock.get("/apps/", params={"team_id": team["id"]}).mock(
407
+ return_value=Response(200, json={"data": [app_1, app_2]})
408
+ )
409
+
410
+ with (
411
+ changing_dir(tmp_path),
412
+ patch("rich_toolkit.container.getchar") as mock_getchar,
413
+ ):
414
+ mock_getchar.side_effect = steps
415
+
416
+ result = runner.invoke(app, ["deploy"])
417
+
418
+ assert result.exit_code == 1
419
+
420
+ assert "Filter: an" in result.output
421
+
422
+ # Truncate part of the output before "Filter: an"
423
+ filer_pos = result.output.rfind("Filter: an")
424
+ last_output = result.output[filer_pos:]
425
+
426
+ assert app_1["slug"] not in last_output
427
+ assert app_2["slug"] in last_output
428
+
429
+
352
430
  @pytest.mark.respx
353
431
  def test_creates_app_on_backend(
354
432
  logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
@@ -1 +0,0 @@
1
- __version__ = "0.15.0"
@@ -1 +0,0 @@
1
- from .app import app as app
@@ -1,10 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- from ..utils import get_message
4
-
5
- app = FastAPI()
6
-
7
-
8
- @app.get("/")
9
- def app_root():
10
- return {"message": get_message()}
@@ -1,2 +0,0 @@
1
- def get_message() -> str:
2
- return "Hello World!"
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,8 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- app = FastAPI()
4
-
5
-
6
- @app.get("/")
7
- def app_root():
8
- return {"message": "single file app"}
@@ -1,2 +0,0 @@
1
- from .mod.api import api as api
2
- from .mod.app import app as app
@@ -1,2 +0,0 @@
1
- def get_hello_world() -> str:
2
- return "Hello World"
@@ -1 +0,0 @@
1
- from .app import app as app
@@ -1,24 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- first_other = FastAPI()
4
-
5
-
6
- @first_other.get("/")
7
- def first_other_root():
8
- return {"message": "package first_other"}
9
-
10
-
11
- second_other = FastAPI()
12
-
13
-
14
- @second_other.get("/")
15
- def second_other_root():
16
- return {"message": "package second_other"}
17
-
18
-
19
- api = FastAPI()
20
-
21
-
22
- @api.get("/")
23
- def api_root():
24
- return {"message": "package api"}
@@ -1,32 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- first_other = FastAPI()
4
-
5
-
6
- @first_other.get("/")
7
- def first_other_root():
8
- return {"message": "package first_other"}
9
-
10
-
11
- second_other = FastAPI()
12
-
13
-
14
- @second_other.get("/")
15
- def second_other_root():
16
- return {"message": "package second_other"}
17
-
18
-
19
- api = FastAPI()
20
-
21
-
22
- @api.get("/")
23
- def api_root():
24
- return {"message": "package api"}
25
-
26
-
27
- app = FastAPI()
28
-
29
-
30
- @app.get("/")
31
- def app_root():
32
- return {"message": "package app"}
@@ -1,16 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- first_other = FastAPI()
4
-
5
-
6
- @first_other.get("/")
7
- def first_other_root():
8
- return {"message": "package first_other"}
9
-
10
-
11
- second_other = FastAPI()
12
-
13
-
14
- @second_other.get("/")
15
- def second_other_root():
16
- return {"message": "package second_other"}
@@ -1,24 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- first_other = FastAPI()
4
-
5
-
6
- @first_other.get("/")
7
- def first_other_root():
8
- return {"message": "single file first_other"}
9
-
10
-
11
- second_other = FastAPI()
12
-
13
-
14
- @second_other.get("/")
15
- def second_other_root():
16
- return {"message": "single file second_other"}
17
-
18
-
19
- api = FastAPI()
20
-
21
-
22
- @api.get("/")
23
- def api_root():
24
- return {"message": "single file api"}
@@ -1,32 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- first_other = FastAPI()
4
-
5
-
6
- @first_other.get("/")
7
- def first_other_root():
8
- return {"message": "single file first_other"}
9
-
10
-
11
- second_other = FastAPI()
12
-
13
-
14
- @second_other.get("/")
15
- def second_other_root():
16
- return {"message": "single file second_other"}
17
-
18
-
19
- api = FastAPI()
20
-
21
-
22
- @api.get("/")
23
- def api_root():
24
- return {"message": "single file api"}
25
-
26
-
27
- app = FastAPI()
28
-
29
-
30
- @app.get("/")
31
- def app_root():
32
- return {"message": "single file app"}
@@ -1,16 +0,0 @@
1
- from fastapi import FastAPI
2
-
3
- first_other = FastAPI()
4
-
5
-
6
- @first_other.get("/")
7
- def first_other_root():
8
- return {"message": "single file first_other"}
9
-
10
-
11
- second_other = FastAPI()
12
-
13
-
14
- @second_other.get("/")
15
- def second_other_root():
16
- return {"message": "single file second_other"}