fastapi-cloud-cli 0.17.0__tar.gz → 0.17.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 (57) hide show
  1. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/PKG-INFO +1 -1
  2. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/pyproject.toml +1 -1
  3. fastapi_cloud_cli-0.17.1/src/fastapi_cloud_cli/__init__.py +1 -0
  4. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/utils/api.py +20 -1
  5. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_cli_deploy.py +29 -0
  6. fastapi_cloud_cli-0.17.0/src/fastapi_cloud_cli/__init__.py +0 -1
  7. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/LICENSE +0 -0
  8. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/README.md +0 -0
  9. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/scripts/add_latest_release_date.py +0 -0
  10. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/scripts/format.sh +0 -0
  11. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/scripts/lint.sh +0 -0
  12. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/scripts/test-cov-html.sh +0 -0
  13. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/scripts/test.sh +0 -0
  14. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/__main__.py +0 -0
  15. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/cli.py +0 -0
  16. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/__init__.py +0 -0
  17. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/deploy.py +0 -0
  18. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/env.py +0 -0
  19. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/link.py +0 -0
  20. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/login.py +0 -0
  21. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/logout.py +0 -0
  22. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/logs.py +0 -0
  23. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/setup_ci.py +0 -0
  24. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/unlink.py +0 -0
  25. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/commands/whoami.py +0 -0
  26. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/config.py +0 -0
  27. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/logging.py +0 -0
  28. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/py.typed +0 -0
  29. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/utils/__init__.py +0 -0
  30. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/utils/apps.py +0 -0
  31. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/utils/auth.py +0 -0
  32. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/utils/cli.py +0 -0
  33. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/utils/config.py +0 -0
  34. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/utils/env.py +0 -0
  35. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/utils/progress_file.py +0 -0
  36. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/src/fastapi_cloud_cli/utils/sentry.py +0 -0
  37. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/__init__.py +0 -0
  38. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/conftest.py +0 -0
  39. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_api_client.py +0 -0
  40. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_archive.py +0 -0
  41. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_auth.py +0 -0
  42. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_cli.py +0 -0
  43. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_cli_link.py +0 -0
  44. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_cli_login.py +0 -0
  45. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_cli_logout.py +0 -0
  46. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_cli_setup_ci.py +0 -0
  47. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_cli_unlink.py +0 -0
  48. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_cli_whoami.py +0 -0
  49. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_config.py +0 -0
  50. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_deploy_utils.py +0 -0
  51. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_env_delete.py +0 -0
  52. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_env_list.py +0 -0
  53. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_env_set.py +0 -0
  54. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_logs.py +0 -0
  55. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_progress_file.py +0 -0
  56. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.1}/tests/test_sentry.py +0 -0
  57. {fastapi_cloud_cli-0.17.0 → fastapi_cloud_cli-0.17.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.17.0
3
+ Version: 0.17.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.10.0",
42
42
  ]
43
- version = "0.17.0"
43
+ version = "0.17.1"
44
44
 
45
45
  [project.license]
46
46
  text = "MIT"
@@ -0,0 +1 @@
1
+ __version__ = "0.17.1"
@@ -209,6 +209,22 @@ def _handle_unauthorized(auth_mode: AuthMode) -> str:
209
209
  return message
210
210
 
211
211
 
212
+ def _get_response_error_message(response: httpx.Response) -> str | None:
213
+ try:
214
+ data = response.json()
215
+ except (json.JSONDecodeError, httpx.ResponseNotRead):
216
+ return None
217
+
218
+ if not isinstance(data, dict):
219
+ return None # pragma: no cover
220
+
221
+ detail = data.get("detail")
222
+ if not isinstance(detail, str):
223
+ return None # pragma: no cover
224
+
225
+ return detail
226
+
227
+
212
228
  def handle_http_error(
213
229
  error: httpx.HTTPError,
214
230
  default_message: str | None = None,
@@ -227,7 +243,10 @@ def handle_http_error(
227
243
  message = _handle_unauthorized(auth_mode=auth_mode)
228
244
 
229
245
  elif status_code == 403:
230
- message = "You don't have permissions for this resource"
246
+ message = (
247
+ _get_response_error_message(error.response)
248
+ or "You don't have permissions for this resource"
249
+ )
231
250
 
232
251
  if not message:
233
252
  message = (
@@ -461,6 +461,35 @@ def test_creates_app_on_backend(
461
461
  assert "App created successfully" in result.output
462
462
 
463
463
 
464
+ @pytest.mark.respx
465
+ def test_shows_api_message_when_create_app_is_forbidden(
466
+ logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
467
+ ) -> None:
468
+ steps = [Keys.ENTER, Keys.ENTER, *"demo", Keys.ENTER, Keys.ENTER, Keys.ENTER]
469
+ team = _get_random_team()
470
+
471
+ respx_mock.get("/teams/").mock(return_value=Response(200, json={"data": [team]}))
472
+ respx_mock.post(
473
+ "/apps/", json={"name": "demo", "team_id": team["id"], "directory": None}
474
+ ).mock(
475
+ return_value=Response(
476
+ 403,
477
+ json={"detail": "App limit reached"},
478
+ )
479
+ )
480
+
481
+ with (
482
+ changing_dir(tmp_path),
483
+ patch("rich_toolkit.container.getchar") as mock_getchar,
484
+ ):
485
+ mock_getchar.side_effect = steps
486
+
487
+ result = runner.invoke(app, ["deploy"])
488
+
489
+ assert result.exit_code == 1
490
+ assert "App limit reached" in result.output
491
+
492
+
464
493
  @pytest.mark.respx
465
494
  def test_creates_app_with_directory(
466
495
  logged_in_cli: None, tmp_path: Path, respx_mock: respx.MockRouter
@@ -1 +0,0 @@
1
- __version__ = "0.17.0"