Skip to content

Commit 7e44454

Browse files
Add integration tests for Async client (#326)
1 parent 0c2959a commit 7e44454

28 files changed

+6092
-87
lines changed

.github/workflows/pull_request.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ jobs:
8080
conductor-sdk-test:latest \
8181
/bin/sh -c "cd /package && COVERAGE_FILE=/package/${{ env.COVERAGE_DIR }}/.coverage.integration coverage run -m pytest -m v4 tests/integration -v"
8282
83+
- name: Run asyncio integration tests
84+
id: integration_tests
85+
continue-on-error: true
86+
run: |
87+
docker run --rm \
88+
-e CONDUCTOR_AUTH_KEY=${{ env.CONDUCTOR_AUTH_KEY }} \
89+
-e CONDUCTOR_AUTH_SECRET=${{ env.CONDUCTOR_AUTH_SECRET }} \
90+
-e CONDUCTOR_SERVER_URL=${{ env.CONDUCTOR_SERVER_URL }} \
91+
-v ${{ github.workspace }}/${{ env.COVERAGE_DIR }}:/package/${{ env.COVERAGE_DIR }}:rw \
92+
conductor-sdk-test:latest \
93+
/bin/sh -c "cd /package && COVERAGE_FILE=/package/${{ env.COVERAGE_DIR }}/.coverage.integration coverage run -m pytest -m v4 tests/integration -v"
94+
8395
- name: Generate coverage report
8496
id: coverage_report
8597
continue-on-error: true

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,4 @@ markers = [
188188
"v4_1_73: mark test to run for version 4.1.73",
189189
"v5_2_6: mark test to run for version 5.2.6",
190190
"v3_21_16: mark test to run for version 3.21.16"
191-
]
191+
]

src/conductor/asyncio_client/adapters/api/workflow_resource_api.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,90 @@ async def update_workflow_state(
7575
response_data=response_data,
7676
response_types_map=_response_types_map,
7777
).data
78+
79+
@validate_call
80+
async def start_workflow1(
81+
self,
82+
name: StrictStr,
83+
request_body: Dict[str, Any],
84+
version: Optional[StrictInt] = None,
85+
correlation_id: Optional[StrictStr] = None,
86+
priority: Optional[StrictInt] = None,
87+
x_idempotency_key: Optional[StrictStr] = None,
88+
x_on_conflict: Optional[StrictStr] = None,
89+
_request_timeout: Union[
90+
None,
91+
Annotated[StrictFloat, Field(gt=0)],
92+
Tuple[
93+
Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]
94+
],
95+
] = None,
96+
_request_auth: Optional[Dict[StrictStr, Any]] = None,
97+
_content_type: Optional[StrictStr] = None,
98+
_headers: Optional[Dict[StrictStr, Any]] = None,
99+
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
100+
) -> str:
101+
"""Start a new workflow. Returns the ID of the workflow instance that can be later used for tracking
102+
103+
104+
:param name: (required)
105+
:type name: str
106+
:param request_body: (required)
107+
:type request_body: Dict[str, object]
108+
:param version:
109+
:type version: int
110+
:param correlation_id:
111+
:type correlation_id: str
112+
:param priority:
113+
:type priority: int
114+
:param x_idempotency_key:
115+
:type x_idempotency_key: str
116+
:param x_on_conflict:
117+
:type x_on_conflict: str
118+
:param _request_timeout: timeout setting for this request. If one
119+
number provided, it will be total request
120+
timeout. It can also be a pair (tuple) of
121+
(connection, read) timeouts.
122+
:type _request_timeout: int, tuple(int, int), optional
123+
:param _request_auth: set to override the auth_settings for an a single
124+
request; this effectively ignores the
125+
authentication in the spec for a single request.
126+
:type _request_auth: dict, optional
127+
:param _content_type: force content-type for the request.
128+
:type _content_type: str, Optional
129+
:param _headers: set to override the headers for a single
130+
request; this effectively ignores the headers
131+
in the spec for a single request.
132+
:type _headers: dict, optional
133+
:param _host_index: set to override the host_index for a single
134+
request; this effectively ignores the host_index
135+
in the spec for a single request.
136+
:type _host_index: int, optional
137+
:return: Returns the result object.
138+
""" # noqa: E501
139+
140+
_param = self._start_workflow1_serialize(
141+
name=name,
142+
request_body=request_body,
143+
version=version,
144+
correlation_id=correlation_id,
145+
priority=priority,
146+
x_idempotency_key=x_idempotency_key,
147+
x_on_conflict=x_on_conflict,
148+
_request_auth=_request_auth,
149+
_content_type=_content_type,
150+
_headers=_headers,
151+
_host_index=_host_index,
152+
)
153+
154+
_response_types_map: Dict[str, Optional[str]] = {
155+
"200": "str",
156+
}
157+
response_data = await self.api_client.call_api(
158+
*_param, _request_timeout=_request_timeout
159+
)
160+
await response_data.read()
161+
return self.api_client.response_deserialize(
162+
response_data=response_data,
163+
response_types_map=_response_types_map,
164+
).data

src/conductor/asyncio_client/adapters/models/extended_task_def_adapter.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class ExtendedTaskDefAdapter(ExtendedTaskDef):
1919
default=None, alias="outputSchema"
2020
)
2121
tags: Optional[List["TagAdapter"]] = None
22+
timeout_seconds: Optional[int] = Field(alias="timeoutSeconds", default=None)
23+
total_timeout_seconds: Optional[int] = Field(alias="totalTimeoutSeconds", default=None)
2224

2325
@classmethod
2426
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:

src/conductor/asyncio_client/adapters/models/extended_workflow_def_adapter.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class ExtendedWorkflowDefAdapter(ExtendedWorkflowDef):
2727
tags: Optional[List["TagAdapter"]] = None
2828
tasks: List["WorkflowTaskAdapter"]
2929
variables: Optional[Dict[str, Any]] = None
30+
timeout_seconds: Optional[int] = Field(default=None, alias="timeoutSeconds")
3031

3132
@classmethod
3233
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
@@ -99,7 +100,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
99100
from conductor.asyncio_client.adapters.models.schema_def_adapter import ( # noqa: E402
100101
SchemaDefAdapter,
101102
)
102-
from conductor.asyncio_client.adapters.models.tag_adapter import TagAdapter # noqa: E402
103+
from conductor.asyncio_client.adapters.models.tag_adapter import (
104+
TagAdapter,
105+
) # noqa: E402
103106
from conductor.asyncio_client.adapters.models.workflow_task_adapter import ( # noqa: E402
104107
WorkflowTaskAdapter,
105108
)

src/conductor/asyncio_client/adapters/models/integration_def_adapter.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import Any, Dict, List, Optional
44

5+
from pydantic import ConfigDict, field_validator
56
from typing_extensions import Self
67

78
from conductor.asyncio_client.http.models import IntegrationDef
@@ -10,6 +11,34 @@
1011
class IntegrationDefAdapter(IntegrationDef):
1112
configuration: Optional[List["IntegrationDefFormFieldAdapter"]] = None
1213

14+
@field_validator("category")
15+
def category_validate_enum(cls, value):
16+
if value is None:
17+
return value
18+
19+
if value not in set(
20+
[
21+
"API",
22+
"AI_MODEL",
23+
"VECTOR_DB",
24+
"RELATIONAL_DB",
25+
"MESSAGE_BROKER",
26+
"GIT",
27+
"EMAIL",
28+
"MCP",
29+
]
30+
):
31+
raise ValueError(
32+
"must be one of enum values ('API', 'AI_MODEL', 'VECTOR_DB', 'RELATIONAL_DB', 'MESSAGE_BROKER', 'GIT', 'EMAIL', 'MCP')"
33+
)
34+
return value
35+
36+
model_config = ConfigDict(
37+
populate_by_name=True,
38+
validate_assignment=True,
39+
protected_namespaces=(),
40+
)
41+
1342
@classmethod
1443
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
1544
"""Create an instance of IntegrationDef from a dict"""
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
from __future__ import annotations
2+
from enum import Enum
23

34
from typing import Any, Dict, Optional
45

56
from conductor.asyncio_client.http.models import SchemaDef
67

78

9+
class SchemaType(str, Enum):
10+
JSON = ("JSON",)
11+
AVRO = ("AVRO",)
12+
PROTOBUF = "PROTOBUF"
13+
14+
def __str__(self) -> str:
15+
return self.name.__str__()
16+
17+
818
class SchemaDefAdapter(SchemaDef):
919
data: Optional[Dict[str, Any]] = None

src/conductor/asyncio_client/adapters/models/task_def_adapter.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class TaskDefAdapter(TaskDef):
1818
output_schema: Optional["SchemaDefAdapter"] = Field(
1919
default=None, alias="outputSchema"
2020
)
21+
timeout_seconds: Optional[int] = Field(alias="timeoutSeconds", default=None)
22+
total_timeout_seconds: Optional[int] = Field(alias="totalTimeoutSeconds", default=None)
2123

2224
@classmethod
2325
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:

src/conductor/asyncio_client/adapters/models/workflow_def_adapter.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class WorkflowDefAdapter(WorkflowDef):
2828
rate_limit_config: Optional["RateLimitConfigAdapter"] = Field(
2929
default=None, alias="rateLimitConfig"
3030
)
31+
timeout_seconds: Optional[int] = Field(default=None, alias="timeoutSeconds")
32+
3133
__properties: ClassVar[List[str]] = [
3234
"createTime",
3335
"createdBy",

0 commit comments

Comments
 (0)