Skip to content

Commit 04ee90d

Browse files
committed
fix(blueprints): handle awaiting upload status
1 parent 2376350 commit 04ee90d

5 files changed

Lines changed: 63 additions & 21 deletions

File tree

src/runloop_api_client/resources/blueprints.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ def retrieve_blueprint() -> BlueprintView:
371371
)
372372

373373
def is_done_building(blueprint: BlueprintView) -> bool:
374-
return blueprint.status not in ["queued", "building", "provisioning"]
374+
return blueprint.status not in ["queued", "building", "provisioning", "awaiting_upload"]
375375

376376
blueprint = poll_until(retrieve_blueprint, is_done_building, polling_config)
377377

@@ -481,7 +481,7 @@ def list(
481481
482482
starting_after: Load the next page of data starting after the item with the given ID.
483483
484-
status: Filter by build status (queued, provisioning, building, failed, build_complete)
484+
status: Filter by build status (queued, provisioning, building, awaiting_upload, failed, build_complete)
485485
486486
extra_headers: Send extra headers
487487
@@ -584,7 +584,7 @@ def list_public(
584584
585585
starting_after: Load the next page of data starting after the item with the given ID.
586586
587-
status: Filter by build status (queued, provisioning, building, failed, build_complete)
587+
status: Filter by build status (queued, provisioning, building, awaiting_upload, failed, build_complete)
588588
589589
extra_headers: Send extra headers
590590
@@ -1033,7 +1033,7 @@ async def retrieve_blueprint() -> BlueprintView:
10331033
)
10341034

10351035
def is_done_building(blueprint: BlueprintView) -> bool:
1036-
return blueprint.status not in ["queued", "building", "provisioning"]
1036+
return blueprint.status not in ["queued", "building", "provisioning", "awaiting_upload"]
10371037

10381038
blueprint = await async_poll_until(retrieve_blueprint, is_done_building, polling_config)
10391039

@@ -1143,7 +1143,7 @@ def list(
11431143
11441144
starting_after: Load the next page of data starting after the item with the given ID.
11451145
1146-
status: Filter by build status (queued, provisioning, building, failed, build_complete)
1146+
status: Filter by build status (queued, provisioning, building, awaiting_upload, failed, build_complete)
11471147
11481148
extra_headers: Send extra headers
11491149
@@ -1246,7 +1246,7 @@ def list_public(
12461246
12471247
starting_after: Load the next page of data starting after the item with the given ID.
12481248
1249-
status: Filter by build status (queued, provisioning, building, failed, build_complete)
1249+
status: Filter by build status (queued, provisioning, building, awaiting_upload, failed, build_complete)
12501250
12511251
extra_headers: Send extra headers
12521252

src/runloop_api_client/types/blueprint_list_params.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ class BlueprintListParams(TypedDict, total=False):
2424
"""Load the next page of data starting after the item with the given ID."""
2525

2626
status: str
27-
"""Filter by build status (queued, provisioning, building, failed, build_complete)"""
27+
"""Filter by build status (queued, provisioning, building, awaiting_upload, failed, build_complete)"""

src/runloop_api_client/types/blueprint_list_public_params.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ class BlueprintListPublicParams(TypedDict, total=False):
2424
"""Load the next page of data starting after the item with the given ID."""
2525

2626
status: str
27-
"""Filter by build status (queued, provisioning, building, failed, build_complete)"""
27+
"""Filter by build status (queued, provisioning, building, awaiting_upload, failed, build_complete)"""

src/runloop_api_client/types/blueprint_view.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class BlueprintView(BaseModel):
6363
state: Literal["created", "deleted"]
6464
"""The state of the Blueprint."""
6565

66-
status: Literal["queued", "provisioning", "building", "failed", "build_complete"]
66+
status: Literal["queued", "provisioning", "building", "awaiting_upload", "failed", "build_complete"]
6767
"""The status of the Blueprint build."""
6868

6969
base_blueprint_id: Optional[str] = None

tests/api_resources/test_blueprints.py

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import os
66
from typing import Any, cast
77

8+
import httpx
89
import pytest
10+
from respx import MockRouter
911

1012
from tests.utils import assert_matches_type
1113
from runloop_api_client import Runloop, AsyncRunloop
@@ -22,16 +24,40 @@
2224
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
2325

2426

27+
def mock_register(respx_mock: MockRouter) -> None:
28+
respx_mock.post("/v1/blueprints/register").mock(
29+
return_value=httpx.Response(
30+
200,
31+
json={
32+
"blueprint": {
33+
"id": "bpt_123",
34+
"name": "name",
35+
"status": "awaiting_upload",
36+
"state": "created",
37+
"create_time_ms": 0,
38+
"parameters": {"name": "name"},
39+
},
40+
"push_reference": "converter.runloop.ai/blueprints:bpt_123",
41+
},
42+
)
43+
)
44+
45+
2546
class TestBlueprints:
2647
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
2748

2849
@parametrize
29-
def test_method_register(self, client: Runloop) -> None:
50+
@pytest.mark.respx(base_url=base_url)
51+
def test_method_register(self, client: Runloop, respx_mock: MockRouter) -> None:
52+
mock_register(respx_mock)
3053
upload = client.blueprints.register(name="name")
3154
assert_matches_type(BlueprintUploadView, upload, path=["response"])
55+
assert upload.push_reference == "converter.runloop.ai/blueprints:bpt_123"
3256

3357
@parametrize
34-
def test_method_register_with_all_params(self, client: Runloop) -> None:
58+
@pytest.mark.respx(base_url=base_url)
59+
def test_method_register_with_all_params(self, client: Runloop, respx_mock: MockRouter) -> None:
60+
mock_register(respx_mock)
3561
upload = client.blueprints.register(
3662
name="name",
3763
launch_parameters={"architecture": "x86_64"},
@@ -40,15 +66,19 @@ def test_method_register_with_all_params(self, client: Runloop) -> None:
4066
assert_matches_type(BlueprintUploadView, upload, path=["response"])
4167

4268
@parametrize
43-
def test_raw_response_register(self, client: Runloop) -> None:
69+
@pytest.mark.respx(base_url=base_url)
70+
def test_raw_response_register(self, client: Runloop, respx_mock: MockRouter) -> None:
71+
mock_register(respx_mock)
4472
response = client.blueprints.with_raw_response.register(name="name")
4573
assert response.is_closed is True
4674
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
4775
upload = response.parse()
4876
assert_matches_type(BlueprintUploadView, upload, path=["response"])
4977

5078
@parametrize
51-
def test_streaming_response_register(self, client: Runloop) -> None:
79+
@pytest.mark.respx(base_url=base_url)
80+
def test_streaming_response_register(self, client: Runloop, respx_mock: MockRouter) -> None:
81+
mock_register(respx_mock)
5282
with client.blueprints.with_streaming_response.register(name="name") as response:
5383
assert not response.is_closed
5484
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -492,31 +522,43 @@ class TestAsyncBlueprints:
492522
parametrize = pytest.mark.parametrize(
493523
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
494524
)
525+
register_parametrize = pytest.mark.parametrize(
526+
"async_client", [False, True], indirect=True, ids=["loose", "strict"]
527+
)
495528

496-
@parametrize
497-
async def test_method_register(self, async_client: AsyncRunloop) -> None:
529+
@register_parametrize
530+
@pytest.mark.respx(base_url=base_url)
531+
async def test_method_register(self, async_client: AsyncRunloop, respx_mock: MockRouter) -> None:
532+
mock_register(respx_mock)
498533
upload = await async_client.blueprints.register(name="name")
499534
assert_matches_type(BlueprintUploadView, upload, path=["response"])
535+
assert upload.push_reference == "converter.runloop.ai/blueprints:bpt_123"
500536

501-
@parametrize
502-
async def test_method_register_with_all_params(self, async_client: AsyncRunloop) -> None:
537+
@register_parametrize
538+
@pytest.mark.respx(base_url=base_url)
539+
async def test_method_register_with_all_params(self, async_client: AsyncRunloop, respx_mock: MockRouter) -> None:
540+
mock_register(respx_mock)
503541
upload = await async_client.blueprints.register(
504542
name="name",
505543
launch_parameters={"architecture": "x86_64"},
506544
metadata={"source": "upload"},
507545
)
508546
assert_matches_type(BlueprintUploadView, upload, path=["response"])
509547

510-
@parametrize
511-
async def test_raw_response_register(self, async_client: AsyncRunloop) -> None:
548+
@register_parametrize
549+
@pytest.mark.respx(base_url=base_url)
550+
async def test_raw_response_register(self, async_client: AsyncRunloop, respx_mock: MockRouter) -> None:
551+
mock_register(respx_mock)
512552
response = await async_client.blueprints.with_raw_response.register(name="name")
513553
assert response.is_closed is True
514554
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
515555
upload = await response.parse()
516556
assert_matches_type(BlueprintUploadView, upload, path=["response"])
517557

518-
@parametrize
519-
async def test_streaming_response_register(self, async_client: AsyncRunloop) -> None:
558+
@register_parametrize
559+
@pytest.mark.respx(base_url=base_url)
560+
async def test_streaming_response_register(self, async_client: AsyncRunloop, respx_mock: MockRouter) -> None:
561+
mock_register(respx_mock)
520562
async with async_client.blueprints.with_streaming_response.register(name="name") as response:
521563
assert not response.is_closed
522564
assert response.http_request.headers.get("X-Stainless-Lang") == "python"

0 commit comments

Comments
 (0)