plato-sdk-v2 2.8.5__py3-none-any.whl → 2.8.7__py3-none-any.whl

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 (30) hide show
  1. plato/_generated/__init__.py +1 -1
  2. plato/_generated/api/v1/session/__init__.py +2 -0
  3. plato/_generated/api/v1/session/upload_review_screenshot.py +74 -0
  4. plato/_generated/api/v1/testcases/__init__.py +2 -0
  5. plato/_generated/api/v1/testcases/assign_testcases_to_work_order_item.py +74 -0
  6. plato/_generated/api/v2/__init__.py +2 -0
  7. plato/_generated/api/v2/jobs/__init__.py +4 -0
  8. plato/_generated/api/v2/jobs/heartbeat.py +69 -0
  9. plato/_generated/api/v2/jobs/rdp_url.py +93 -0
  10. plato/_generated/api/v2/releases/__init__.py +2 -0
  11. plato/_generated/api/v2/releases/deploy.py +6 -6
  12. plato/_generated/api/v2/releases/get.py +8 -8
  13. plato/_generated/api/v2/releases/prep_release_assigned_testcases.py +6 -6
  14. plato/_generated/api/v2/releases/prep_release_from_work_order.py +85 -0
  15. plato/_generated/api/v2/releases/update.py +6 -6
  16. plato/_generated/api/v2/sessions/__init__.py +2 -0
  17. plato/_generated/api/v2/sessions/get_rdp_url.py +87 -0
  18. plato/_generated/api/v2/work_orders/__init__.py +19 -0
  19. plato/_generated/api/v2/work_orders/archive_work_order.py +81 -0
  20. plato/_generated/api/v2/work_orders/archive_work_order_item.py +81 -0
  21. plato/_generated/api/v2/work_orders/create_work_order.py +76 -0
  22. plato/_generated/api/v2/work_orders/create_work_order_item.py +81 -0
  23. plato/_generated/api/v2/work_orders/get_work_order.py +75 -0
  24. plato/_generated/api/v2/work_orders/list_work_orders.py +80 -0
  25. plato/_generated/models/__init__.py +274 -7
  26. plato/cli/pm.py +2 -1
  27. {plato_sdk_v2-2.8.5.dist-info → plato_sdk_v2-2.8.7.dist-info}/METADATA +1 -1
  28. {plato_sdk_v2-2.8.5.dist-info → plato_sdk_v2-2.8.7.dist-info}/RECORD +30 -17
  29. {plato_sdk_v2-2.8.5.dist-info → plato_sdk_v2-2.8.7.dist-info}/WHEEL +0 -0
  30. {plato_sdk_v2-2.8.5.dist-info → plato_sdk_v2-2.8.7.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,4 @@
1
- """Plato API SDK - v0.48.2"""
1
+ """Plato API SDK - v0.49.7"""
2
2
 
3
3
  from . import api, errors, models
4
4
  from .client import AsyncClient, Client
@@ -29,12 +29,14 @@ from . import (
29
29
  set_session_output,
30
30
  update_session_public,
31
31
  update_session_testcase,
32
+ upload_review_screenshot,
32
33
  )
33
34
 
34
35
  __all__ = [
35
36
  "create_session_from_browser",
36
37
  "create_session_from_har",
37
38
  "create_session_from_env_recording",
39
+ "upload_review_screenshot",
38
40
  "get_sessions",
39
41
  "get_next_session_for_annotator",
40
42
  "get_grouped_replay_sessions",
@@ -0,0 +1,74 @@
1
+ """Upload Review Screenshot"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ import httpx
8
+
9
+ from plato._generated.errors import raise_for_status
10
+ from plato._generated.models import BodyUploadReviewScreenshot
11
+
12
+
13
+ def _build_request_args(
14
+ body: BodyUploadReviewScreenshot,
15
+ authorization: str | None = None,
16
+ x_api_key: str | None = None,
17
+ ) -> dict[str, Any]:
18
+ """Build request arguments."""
19
+ url = "/api/v1/session/upload-review-screenshot"
20
+
21
+ headers: dict[str, str] = {}
22
+ if authorization is not None:
23
+ headers["authorization"] = authorization
24
+ if x_api_key is not None:
25
+ headers["X-API-Key"] = x_api_key
26
+
27
+ return {
28
+ "method": "POST",
29
+ "url": url,
30
+ "json": body.model_dump(mode="json", exclude_none=True),
31
+ "headers": headers,
32
+ }
33
+
34
+
35
+ def sync(
36
+ client: httpx.Client,
37
+ body: BodyUploadReviewScreenshot,
38
+ authorization: str | None = None,
39
+ x_api_key: str | None = None,
40
+ ) -> Any:
41
+ """Upload a review screenshot to S3.
42
+ Used by the data-review Chrome extension to upload annotated screenshots.
43
+ Supports both user session and API key authentication."""
44
+
45
+ request_args = _build_request_args(
46
+ body=body,
47
+ authorization=authorization,
48
+ x_api_key=x_api_key,
49
+ )
50
+
51
+ response = client.request(**request_args)
52
+ raise_for_status(response)
53
+ return response.json()
54
+
55
+
56
+ async def asyncio(
57
+ client: httpx.AsyncClient,
58
+ body: BodyUploadReviewScreenshot,
59
+ authorization: str | None = None,
60
+ x_api_key: str | None = None,
61
+ ) -> Any:
62
+ """Upload a review screenshot to S3.
63
+ Used by the data-review Chrome extension to upload annotated screenshots.
64
+ Supports both user session and API key authentication."""
65
+
66
+ request_args = _build_request_args(
67
+ body=body,
68
+ authorization=authorization,
69
+ x_api_key=x_api_key,
70
+ )
71
+
72
+ response = await client.request(**request_args)
73
+ raise_for_status(response)
74
+ return response.json()
@@ -5,6 +5,7 @@ from . import (
5
5
  archive_organization_testcase,
6
6
  archive_testcase,
7
7
  assign_testcase_to_organizations,
8
+ assign_testcases_to_work_order_item,
8
9
  auto_verify_testcase,
9
10
  bulk_archive_testcases,
10
11
  convert_text_to_structured_data,
@@ -61,6 +62,7 @@ __all__ = [
61
62
  "mark_organization_test_case_completed",
62
63
  "get_human_recorder_tab_counts",
63
64
  "bulk_archive_testcases",
65
+ "assign_testcases_to_work_order_item",
64
66
  "archive_organization_testcase",
65
67
  "version_bump_testcase",
66
68
  "auto_verify_testcase",
@@ -0,0 +1,74 @@
1
+ """Assign Testcases To Work Order Item"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ import httpx
8
+
9
+ from plato._generated.errors import raise_for_status
10
+ from plato._generated.models import AssignToWorkOrderItemRequest
11
+
12
+
13
+ def _build_request_args(
14
+ body: AssignToWorkOrderItemRequest,
15
+ authorization: str | None = None,
16
+ x_api_key: str | None = None,
17
+ ) -> dict[str, Any]:
18
+ """Build request arguments."""
19
+ url = "/api/v1/testcases/assign-to-work-order-item"
20
+
21
+ headers: dict[str, str] = {}
22
+ if authorization is not None:
23
+ headers["authorization"] = authorization
24
+ if x_api_key is not None:
25
+ headers["X-API-Key"] = x_api_key
26
+
27
+ return {
28
+ "method": "POST",
29
+ "url": url,
30
+ "json": body.model_dump(mode="json", exclude_none=True),
31
+ "headers": headers,
32
+ }
33
+
34
+
35
+ def sync(
36
+ client: httpx.Client,
37
+ body: AssignToWorkOrderItemRequest,
38
+ authorization: str | None = None,
39
+ x_api_key: str | None = None,
40
+ ) -> Any:
41
+ """Assign multiple test cases to a work order item.
42
+ Creates TestCaseStatus entries linking test cases to the work order item.
43
+ Admin-only endpoint."""
44
+
45
+ request_args = _build_request_args(
46
+ body=body,
47
+ authorization=authorization,
48
+ x_api_key=x_api_key,
49
+ )
50
+
51
+ response = client.request(**request_args)
52
+ raise_for_status(response)
53
+ return response.json()
54
+
55
+
56
+ async def asyncio(
57
+ client: httpx.AsyncClient,
58
+ body: AssignToWorkOrderItemRequest,
59
+ authorization: str | None = None,
60
+ x_api_key: str | None = None,
61
+ ) -> Any:
62
+ """Assign multiple test cases to a work order item.
63
+ Creates TestCaseStatus entries linking test cases to the work order item.
64
+ Admin-only endpoint."""
65
+
66
+ request_args = _build_request_args(
67
+ body=body,
68
+ authorization=authorization,
69
+ x_api_key=x_api_key,
70
+ )
71
+
72
+ response = await client.request(**request_args)
73
+ raise_for_status(response)
74
+ return response.json()
@@ -13,6 +13,7 @@ from . import (
13
13
  releases,
14
14
  sessions,
15
15
  user,
16
+ work_orders,
16
17
  )
17
18
 
18
19
  __all__ = [
@@ -28,4 +29,5 @@ __all__ = [
28
29
  "releases",
29
30
  "sessions",
30
31
  "user",
32
+ "work_orders",
31
33
  ]
@@ -9,9 +9,11 @@ from . import (
9
9
  execute,
10
10
  get_flows,
11
11
  get_plato_config,
12
+ heartbeat,
12
13
  log_for_job,
13
14
  make,
14
15
  public_url,
16
+ rdp_url,
15
17
  reset,
16
18
  set_date,
17
19
  setup_sandbox,
@@ -25,6 +27,7 @@ __all__ = [
25
27
  "make",
26
28
  "reset",
27
29
  "close",
30
+ "heartbeat",
28
31
  "execute",
29
32
  "set_date",
30
33
  "setup_sandbox",
@@ -38,6 +41,7 @@ __all__ = [
38
41
  "wait_for_ready",
39
42
  "public_url",
40
43
  "connect_url",
44
+ "rdp_url",
41
45
  "connect_routing_info",
42
46
  "log_for_job",
43
47
  ]
@@ -0,0 +1,69 @@
1
+ """Heartbeat"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ import httpx
8
+
9
+ from plato._generated.errors import raise_for_status
10
+ from plato._generated.models import HeartbeatJobResult
11
+
12
+
13
+ def _build_request_args(
14
+ job_id: str,
15
+ authorization: str | None = None,
16
+ x_api_key: str | None = None,
17
+ ) -> dict[str, Any]:
18
+ """Build request arguments."""
19
+ url = f"/api/v2/jobs/{job_id}/heartbeat"
20
+
21
+ headers: dict[str, str] = {}
22
+ if authorization is not None:
23
+ headers["authorization"] = authorization
24
+ if x_api_key is not None:
25
+ headers["X-API-Key"] = x_api_key
26
+
27
+ return {
28
+ "method": "POST",
29
+ "url": url,
30
+ "headers": headers,
31
+ }
32
+
33
+
34
+ def sync(
35
+ client: httpx.Client,
36
+ job_id: str,
37
+ authorization: str | None = None,
38
+ x_api_key: str | None = None,
39
+ ) -> HeartbeatJobResult:
40
+ """Send a heartbeat to keep a specific job alive."""
41
+
42
+ request_args = _build_request_args(
43
+ job_id=job_id,
44
+ authorization=authorization,
45
+ x_api_key=x_api_key,
46
+ )
47
+
48
+ response = client.request(**request_args)
49
+ raise_for_status(response)
50
+ return HeartbeatJobResult.model_validate(response.json())
51
+
52
+
53
+ async def asyncio(
54
+ client: httpx.AsyncClient,
55
+ job_id: str,
56
+ authorization: str | None = None,
57
+ x_api_key: str | None = None,
58
+ ) -> HeartbeatJobResult:
59
+ """Send a heartbeat to keep a specific job alive."""
60
+
61
+ request_args = _build_request_args(
62
+ job_id=job_id,
63
+ authorization=authorization,
64
+ x_api_key=x_api_key,
65
+ )
66
+
67
+ response = await client.request(**request_args)
68
+ raise_for_status(response)
69
+ return HeartbeatJobResult.model_validate(response.json())
@@ -0,0 +1,93 @@
1
+ """Rdp Url"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ import httpx
8
+
9
+ from plato._generated.errors import raise_for_status
10
+ from plato._generated.models import RdpUrlResult
11
+
12
+
13
+ def _build_request_args(
14
+ job_id: str,
15
+ authorization: str | None = None,
16
+ x_api_key: str | None = None,
17
+ ) -> dict[str, Any]:
18
+ """Build request arguments."""
19
+ url = f"/api/v2/jobs/{job_id}/rdp_url"
20
+
21
+ headers: dict[str, str] = {}
22
+ if authorization is not None:
23
+ headers["authorization"] = authorization
24
+ if x_api_key is not None:
25
+ headers["X-API-Key"] = x_api_key
26
+
27
+ return {
28
+ "method": "GET",
29
+ "url": url,
30
+ "headers": headers,
31
+ }
32
+
33
+
34
+ def sync(
35
+ client: httpx.Client,
36
+ job_id: str,
37
+ authorization: str | None = None,
38
+ x_api_key: str | None = None,
39
+ ) -> RdpUrlResult:
40
+ """Get RDP viewer URL for browser-based remote desktop access.
41
+
42
+ Returns URL to the Guacamole-based RDP viewer for Windows VMs.
43
+ The URL includes a trailing slash which is required for proper routing.
44
+
45
+ Args:
46
+ job_id: The job public ID.
47
+
48
+ Returns:
49
+ RdpUrlResult with RDP viewer URL.
50
+
51
+ Raises:
52
+ 404: If job not found."""
53
+
54
+ request_args = _build_request_args(
55
+ job_id=job_id,
56
+ authorization=authorization,
57
+ x_api_key=x_api_key,
58
+ )
59
+
60
+ response = client.request(**request_args)
61
+ raise_for_status(response)
62
+ return RdpUrlResult.model_validate(response.json())
63
+
64
+
65
+ async def asyncio(
66
+ client: httpx.AsyncClient,
67
+ job_id: str,
68
+ authorization: str | None = None,
69
+ x_api_key: str | None = None,
70
+ ) -> RdpUrlResult:
71
+ """Get RDP viewer URL for browser-based remote desktop access.
72
+
73
+ Returns URL to the Guacamole-based RDP viewer for Windows VMs.
74
+ The URL includes a trailing slash which is required for proper routing.
75
+
76
+ Args:
77
+ job_id: The job public ID.
78
+
79
+ Returns:
80
+ RdpUrlResult with RDP viewer URL.
81
+
82
+ Raises:
83
+ 404: If job not found."""
84
+
85
+ request_args = _build_request_args(
86
+ job_id=job_id,
87
+ authorization=authorization,
88
+ x_api_key=x_api_key,
89
+ )
90
+
91
+ response = await client.request(**request_args)
92
+ raise_for_status(response)
93
+ return RdpUrlResult.model_validate(response.json())
@@ -8,6 +8,7 @@ from . import (
8
8
  handle_import,
9
9
  list_releases,
10
10
  prep_release_assigned_testcases,
11
+ prep_release_from_work_order,
11
12
  update,
12
13
  )
13
14
 
@@ -18,6 +19,7 @@ __all__ = [
18
19
  "update",
19
20
  "deploy",
20
21
  "prep_release_assigned_testcases",
22
+ "prep_release_from_work_order",
21
23
  "handle_import",
22
24
  "handle_get_existing_public_ids",
23
25
  ]
@@ -10,12 +10,12 @@ from plato._generated.errors import raise_for_status
10
10
 
11
11
 
12
12
  def _build_request_args(
13
- release_id: int,
13
+ public_id: str,
14
14
  authorization: str | None = None,
15
15
  x_api_key: str | None = None,
16
16
  ) -> dict[str, Any]:
17
17
  """Build request arguments."""
18
- url = f"/api/v2/releases/{release_id}/deploy"
18
+ url = f"/api/v2/releases/{public_id}/deploy"
19
19
 
20
20
  headers: dict[str, str] = {}
21
21
  if authorization is not None:
@@ -32,7 +32,7 @@ def _build_request_args(
32
32
 
33
33
  def sync(
34
34
  client: httpx.Client,
35
- release_id: int,
35
+ public_id: str,
36
36
  authorization: str | None = None,
37
37
  x_api_key: str | None = None,
38
38
  ) -> Any:
@@ -46,7 +46,7 @@ def sync(
46
46
  - error: optional error message"""
47
47
 
48
48
  request_args = _build_request_args(
49
- release_id=release_id,
49
+ public_id=public_id,
50
50
  authorization=authorization,
51
51
  x_api_key=x_api_key,
52
52
  )
@@ -58,7 +58,7 @@ def sync(
58
58
 
59
59
  async def asyncio(
60
60
  client: httpx.AsyncClient,
61
- release_id: int,
61
+ public_id: str,
62
62
  authorization: str | None = None,
63
63
  x_api_key: str | None = None,
64
64
  ) -> Any:
@@ -72,7 +72,7 @@ async def asyncio(
72
72
  - error: optional error message"""
73
73
 
74
74
  request_args = _build_request_args(
75
- release_id=release_id,
75
+ public_id=public_id,
76
76
  authorization=authorization,
77
77
  x_api_key=x_api_key,
78
78
  )
@@ -11,12 +11,12 @@ from plato._generated.models import ReleaseResponse
11
11
 
12
12
 
13
13
  def _build_request_args(
14
- release_id: int,
14
+ public_id: str,
15
15
  authorization: str | None = None,
16
16
  x_api_key: str | None = None,
17
17
  ) -> dict[str, Any]:
18
18
  """Build request arguments."""
19
- url = f"/api/v2/releases/{release_id}"
19
+ url = f"/api/v2/releases/{public_id}"
20
20
 
21
21
  headers: dict[str, str] = {}
22
22
  if authorization is not None:
@@ -33,14 +33,14 @@ def _build_request_args(
33
33
 
34
34
  def sync(
35
35
  client: httpx.Client,
36
- release_id: int,
36
+ public_id: str,
37
37
  authorization: str | None = None,
38
38
  x_api_key: str | None = None,
39
39
  ) -> ReleaseResponse:
40
- """Get a specific release by ID."""
40
+ """Get a specific release by public ID."""
41
41
 
42
42
  request_args = _build_request_args(
43
- release_id=release_id,
43
+ public_id=public_id,
44
44
  authorization=authorization,
45
45
  x_api_key=x_api_key,
46
46
  )
@@ -52,14 +52,14 @@ def sync(
52
52
 
53
53
  async def asyncio(
54
54
  client: httpx.AsyncClient,
55
- release_id: int,
55
+ public_id: str,
56
56
  authorization: str | None = None,
57
57
  x_api_key: str | None = None,
58
58
  ) -> ReleaseResponse:
59
- """Get a specific release by ID."""
59
+ """Get a specific release by public ID."""
60
60
 
61
61
  request_args = _build_request_args(
62
- release_id=release_id,
62
+ public_id=public_id,
63
63
  authorization=authorization,
64
64
  x_api_key=x_api_key,
65
65
  )
@@ -11,13 +11,13 @@ from plato._generated.models import PrepAssignedTestcasesRequest, ReleaseRespons
11
11
 
12
12
 
13
13
  def _build_request_args(
14
- release_id: int,
14
+ public_id: str,
15
15
  body: PrepAssignedTestcasesRequest,
16
16
  authorization: str | None = None,
17
17
  x_api_key: str | None = None,
18
18
  ) -> dict[str, Any]:
19
19
  """Build request arguments."""
20
- url = f"/api/v2/releases/{release_id}/prep/assigned_testcases"
20
+ url = f"/api/v2/releases/{public_id}/prep/assigned_testcases"
21
21
 
22
22
  headers: dict[str, str] = {}
23
23
  if authorization is not None:
@@ -35,7 +35,7 @@ def _build_request_args(
35
35
 
36
36
  def sync(
37
37
  client: httpx.Client,
38
- release_id: int,
38
+ public_id: str,
39
39
  body: PrepAssignedTestcasesRequest,
40
40
  authorization: str | None = None,
41
41
  x_api_key: str | None = None,
@@ -51,7 +51,7 @@ def sync(
51
51
  Admin only."""
52
52
 
53
53
  request_args = _build_request_args(
54
- release_id=release_id,
54
+ public_id=public_id,
55
55
  body=body,
56
56
  authorization=authorization,
57
57
  x_api_key=x_api_key,
@@ -64,7 +64,7 @@ def sync(
64
64
 
65
65
  async def asyncio(
66
66
  client: httpx.AsyncClient,
67
- release_id: int,
67
+ public_id: str,
68
68
  body: PrepAssignedTestcasesRequest,
69
69
  authorization: str | None = None,
70
70
  x_api_key: str | None = None,
@@ -80,7 +80,7 @@ async def asyncio(
80
80
  Admin only."""
81
81
 
82
82
  request_args = _build_request_args(
83
- release_id=release_id,
83
+ public_id=public_id,
84
84
  body=body,
85
85
  authorization=authorization,
86
86
  x_api_key=x_api_key,
@@ -0,0 +1,85 @@
1
+ """Prep Release From Work Order"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ import httpx
8
+
9
+ from plato._generated.errors import raise_for_status
10
+ from plato._generated.models import PrepFromWorkOrderRequest, ReleaseResponse
11
+
12
+
13
+ def _build_request_args(
14
+ public_id: str,
15
+ body: PrepFromWorkOrderRequest,
16
+ authorization: str | None = None,
17
+ x_api_key: str | None = None,
18
+ ) -> dict[str, Any]:
19
+ """Build request arguments."""
20
+ url = f"/api/v2/releases/{public_id}/prep/work_order"
21
+
22
+ headers: dict[str, str] = {}
23
+ if authorization is not None:
24
+ headers["authorization"] = authorization
25
+ if x_api_key is not None:
26
+ headers["X-API-Key"] = x_api_key
27
+
28
+ return {
29
+ "method": "POST",
30
+ "url": url,
31
+ "json": body.model_dump(mode="json", exclude_none=True),
32
+ "headers": headers,
33
+ }
34
+
35
+
36
+ def sync(
37
+ client: httpx.Client,
38
+ public_id: str,
39
+ body: PrepFromWorkOrderRequest,
40
+ authorization: str | None = None,
41
+ x_api_key: str | None = None,
42
+ ) -> ReleaseResponse:
43
+ """Prep a release with selected testcases from a work order.
44
+
45
+ Allows granular selection of individual testcases to include in the release.
46
+ Collects linked testcase_artifacts, artifacts, and simulators automatically.
47
+
48
+ Admin only."""
49
+
50
+ request_args = _build_request_args(
51
+ public_id=public_id,
52
+ body=body,
53
+ authorization=authorization,
54
+ x_api_key=x_api_key,
55
+ )
56
+
57
+ response = client.request(**request_args)
58
+ raise_for_status(response)
59
+ return ReleaseResponse.model_validate(response.json())
60
+
61
+
62
+ async def asyncio(
63
+ client: httpx.AsyncClient,
64
+ public_id: str,
65
+ body: PrepFromWorkOrderRequest,
66
+ authorization: str | None = None,
67
+ x_api_key: str | None = None,
68
+ ) -> ReleaseResponse:
69
+ """Prep a release with selected testcases from a work order.
70
+
71
+ Allows granular selection of individual testcases to include in the release.
72
+ Collects linked testcase_artifacts, artifacts, and simulators automatically.
73
+
74
+ Admin only."""
75
+
76
+ request_args = _build_request_args(
77
+ public_id=public_id,
78
+ body=body,
79
+ authorization=authorization,
80
+ x_api_key=x_api_key,
81
+ )
82
+
83
+ response = await client.request(**request_args)
84
+ raise_for_status(response)
85
+ return ReleaseResponse.model_validate(response.json())