ergon-framework-python 0.2.0__py3-none-any.whl → 0.2.2__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 (38) hide show
  1. ergon/__init__.py +1 -1
  2. ergon/connector/__init__.py +20 -0
  3. ergon/connector/ergon_platform/__init__.py +78 -11
  4. ergon/connector/ergon_platform/async_connector.py +3 -221
  5. ergon/connector/ergon_platform/channels/__init__.py +54 -0
  6. ergon/connector/ergon_platform/channels/adapters.py +230 -0
  7. ergon/connector/ergon_platform/channels/async_connector.py +327 -0
  8. ergon/connector/ergon_platform/channels/connector.py +294 -0
  9. ergon/connector/ergon_platform/channels/models.py +460 -0
  10. ergon/connector/ergon_platform/channels/services/__init__.py +39 -0
  11. ergon/connector/ergon_platform/channels/services/activity.py +300 -0
  12. ergon/connector/ergon_platform/channels/services/addresses.py +325 -0
  13. ergon/connector/ergon_platform/channels/services/attachments.py +283 -0
  14. ergon/connector/ergon_platform/channels/services/messages.py +127 -0
  15. ergon/connector/ergon_platform/channels/services/records.py +75 -0
  16. ergon/connector/ergon_platform/channels/services/service.py +34 -0
  17. ergon/connector/ergon_platform/connector.py +3 -198
  18. ergon/connector/ergon_platform/models.py +1 -73
  19. ergon/connector/ergon_platform/utils.py +39 -248
  20. ergon/connector/ergon_platform/workflows/__init__.py +52 -0
  21. ergon/connector/ergon_platform/{_operations.py → workflows/_operations.py} +8 -3
  22. ergon/connector/ergon_platform/workflows/async_connector.py +224 -0
  23. ergon/connector/ergon_platform/workflows/connector.py +201 -0
  24. ergon/connector/ergon_platform/workflows/models.py +90 -0
  25. ergon/connector/ergon_platform/workflows/utils.py +250 -0
  26. ergon/connector/nylas/async_connector.py +6 -0
  27. ergon/connector/nylas/async_service.py +3 -0
  28. ergon/connector/nylas/connector.py +6 -0
  29. ergon/connector/nylas/models.py +8 -0
  30. ergon/connector/nylas/service.py +9 -0
  31. ergon/connector/nylas/utils.py +2 -4
  32. ergon/task/mixins/consumer.py +0 -2
  33. {ergon_framework_python-0.2.0.dist-info → ergon_framework_python-0.2.2.dist-info}/METADATA +3 -3
  34. {ergon_framework_python-0.2.0.dist-info → ergon_framework_python-0.2.2.dist-info}/RECORD +38 -21
  35. {ergon_framework_python-0.2.0.dist-info → ergon_framework_python-0.2.2.dist-info}/WHEEL +0 -0
  36. {ergon_framework_python-0.2.0.dist-info → ergon_framework_python-0.2.2.dist-info}/entry_points.txt +0 -0
  37. {ergon_framework_python-0.2.0.dist-info → ergon_framework_python-0.2.2.dist-info}/licenses/LICENSE +0 -0
  38. {ergon_framework_python-0.2.0.dist-info → ergon_framework_python-0.2.2.dist-info}/top_level.txt +0 -0
@@ -1,200 +1,5 @@
1
- import logging
2
- from typing import Any, Dict, List, Optional
1
+ """Deprecated compatibility import for the Workflows connector."""
3
2
 
4
- from ..connector import Connector
5
- from ..transaction import Transaction
6
- from ._client import create_ergon_client
7
- from ._operations import _ErgonPlatformOperations
8
- from .models import (
9
- CreateItemPayload,
10
- ErgonPlatformClient,
11
- ErgonPlatformConsumerConfig,
12
- ErgonPlatformProducerConfig,
13
- )
14
- from .utils import get_value, normalize_create_payload
3
+ from .workflows.connector import ErgonPlatformConnector
15
4
 
16
- logger = logging.getLogger(__name__)
17
-
18
-
19
- class ErgonPlatformConnector(Connector):
20
- def __init__(
21
- self,
22
- client: ErgonPlatformClient,
23
- consumer_config: Optional[ErgonPlatformConsumerConfig] = None,
24
- producer_config: Optional[ErgonPlatformProducerConfig] = None,
25
- ) -> None:
26
- self.client = create_ergon_client(client)
27
- self._operations = _ErgonPlatformOperations(client, self.client)
28
- self._consumer_config = consumer_config
29
- self._producer_config = producer_config or ErgonPlatformProducerConfig()
30
-
31
- def fetch_transactions(
32
- self,
33
- batch_size: Optional[int] = None,
34
- *args,
35
- **kwargs,
36
- ) -> List[Transaction]:
37
- if self._consumer_config is None:
38
- raise ValueError("ErgonPlatformConnector requires a consumer_config to fetch transactions")
39
-
40
- config = self._consumer_config
41
- limit = batch_size or config.batch_size
42
- params: Dict[str, Any] = {**config.list_params, **kwargs}
43
- if config.unassigned:
44
- params.pop("assigned_to", None)
45
- params["assigned"] = "no"
46
-
47
- transactions = self._operations.fetch_items(
48
- config.workflow_id,
49
- config.phase_id,
50
- limit=limit,
51
- offset=config.offset,
52
- **params,
53
- )
54
- if not config.unassigned:
55
- return transactions
56
-
57
- claimed_transactions: List[Transaction] = []
58
- for transaction in transactions:
59
- try:
60
- self.client.workflows.items.claim(transaction.id, {})
61
- claimed_transactions.append(self.fetch_transaction_by_id(transaction.id))
62
- except Exception:
63
- logger.warning(
64
- "Failed to claim item %s during unassigned fetch; skipping it",
65
- transaction.id,
66
- exc_info=True,
67
- )
68
- return claimed_transactions
69
-
70
- def dispatch_transactions(self, transactions: List[Transaction], *args, **kwargs) -> List[str]:
71
- created_ids: List[str] = []
72
- for transaction in transactions:
73
- result = self._create_from_payload(transaction.payload)
74
- created_ids.append(self._created_item_id(result))
75
- return created_ids
76
-
77
- def fetch_child_transactions(
78
- self,
79
- parent_item_id: str,
80
- *args,
81
- **kwargs,
82
- ) -> List[Transaction]:
83
- return self._operations.fetch_child_items(parent_item_id, **kwargs)
84
-
85
- def fetch_transaction_by_id(self, transaction_id: str, *args, **kwargs) -> Transaction:
86
- workflow_id = self._consumer_config.workflow_id if self._consumer_config else ""
87
- return self._operations.get_item_transaction(transaction_id, workflow_id, **kwargs)
88
-
89
- def fetch_items_by_query(
90
- self, workflow_id: str, query: Optional[Dict[str, Any]] = None, **fields: Any
91
- ) -> List[Transaction]:
92
- return self._operations.fetch_items_by_query(workflow_id, query, **fields)
93
-
94
- def get_transactions_count(self, *args, **kwargs) -> int:
95
- if self._consumer_config is None:
96
- raise ValueError("ErgonPlatformConnector requires a consumer_config to count transactions")
97
-
98
- config = self._consumer_config
99
- params: Dict[str, Any] = {**config.list_params, **kwargs}
100
- return self._operations.get_phase_items_count(
101
- config.workflow_id,
102
- config.phase_id,
103
- **params,
104
- )
105
-
106
- def ack_transaction(self, transaction: Transaction, phase_id: Optional[str] = None) -> None:
107
- target_phase = phase_id
108
- if target_phase is None and self._consumer_config is not None:
109
- target_phase = self._consumer_config.ack_phase_id
110
- if not target_phase:
111
- return
112
- self.client.workflows.items.route(transaction.id, to_phase_id=target_phase)
113
-
114
- def release_item(
115
- self,
116
- item_id: str,
117
- data: Optional[Dict[str, Any]] = None,
118
- *,
119
- delay_seconds: Optional[int] = None,
120
- **fields: Any,
121
- ) -> Any:
122
- return self._operations.release_item(
123
- item_id,
124
- data,
125
- delay_seconds=delay_seconds,
126
- **fields,
127
- )
128
-
129
- def nack_transaction(self, transaction: Transaction, requeue: bool = True, delay_seconds: int = 10) -> None:
130
- if requeue:
131
- self._operations.release_item(transaction.id, delay_seconds=delay_seconds)
132
- return
133
-
134
- target_phase = self._consumer_config.nack_phase_id if self._consumer_config is not None else None
135
- if not target_phase:
136
- raise ValueError("nack_phase_id is required when nack_transaction is called with requeue=False")
137
-
138
- self.client.workflows.items.route(transaction.id, to_phase_id=target_phase)
139
- logger.debug("Item %s moved to nack phase %s", transaction.id, target_phase)
140
-
141
- def close(self) -> None:
142
- self.client.close()
143
-
144
- def list_phase_fields(
145
- self,
146
- phase_id: str,
147
- *,
148
- workflow_id: Optional[str] = None,
149
- include_workflow_fields: bool = True,
150
- **params: Any,
151
- ) -> Any:
152
- return self._operations.list_phase_fields(
153
- phase_id,
154
- workflow_id=workflow_id,
155
- include_workflow_fields=include_workflow_fields,
156
- **params,
157
- )
158
-
159
- def get_pipeline_result(
160
- self,
161
- workflow_id: str,
162
- item_id: str,
163
- field_id: str,
164
- buckets_file_id: Optional[str] = None,
165
- ) -> Dict[str, Any]:
166
- return self._operations.get_pipeline_result(workflow_id, item_id, field_id, buckets_file_id)
167
-
168
- def _create_from_payload(self, payload: CreateItemPayload) -> Any:
169
- data = normalize_create_payload(payload)
170
- producer = self._producer_config
171
-
172
- workflow_id = data.get("workflow_id") or producer.workflow_id
173
- phase_id = data.get("phase_id") or producer.phase_id
174
- if not workflow_id:
175
- raise ValueError("workflow_id is required to create an item (set it in payload or producer_config)")
176
- if not phase_id:
177
- raise ValueError("phase_id is required to create an item (set it in payload or producer_config)")
178
-
179
- attachment = data.get("attachment")
180
- attachment_field_id = data.get("attachment_field_id") or producer.attachment_field_id
181
- content_type = data.get("content_type") or producer.default_content_type
182
- parent_item_id = data.get("parent_item_id") or producer.parent_item_id
183
-
184
- return self._operations.create_item(
185
- workflow_id,
186
- phase_id,
187
- data["title"],
188
- parent_item_id=parent_item_id,
189
- field_values=data.get("field_values"),
190
- attachment=attachment,
191
- attachment_field_id=attachment_field_id,
192
- content_type=content_type,
193
- **data.get("fields", {}),
194
- )
195
-
196
- @staticmethod
197
- def _created_item_id(result: Any) -> str:
198
- if isinstance(result, dict) and "item" in result:
199
- return str(get_value(result["item"], "id", ""))
200
- return str(get_value(result, "id", ""))
5
+ __all__ = ["ErgonPlatformConnector"]
@@ -1,4 +1,4 @@
1
- from typing import Any, Dict, Optional, Union
1
+ from typing import Optional
2
2
 
3
3
  from pydantic import BaseModel, Field
4
4
 
@@ -33,75 +33,3 @@ class ErgonPlatformClient(BaseModel):
33
33
  )
34
34
  timeout: float = Field(default=30.0, description="HTTP timeout in seconds")
35
35
  max_retries: int = Field(default=2, ge=0, description="Max automatic HTTP retries")
36
-
37
-
38
- class ErgonPlatformConsumerConfig(BaseModel):
39
- """Parameters used to list workflow items as transactions."""
40
-
41
- workflow_id: str = Field(description="Workflow ID to consume items from")
42
- phase_id: str = Field(description="Phase ID to list items from")
43
- batch_size: int = Field(default=50, ge=1, description="Max items per fetch")
44
- offset: int = Field(default=0, ge=0, description="Pagination offset")
45
- ack_phase_id: Optional[str] = Field(
46
- default=None,
47
- description="Phase to route an item to on ack; ack is a no-op when omitted",
48
- )
49
- nack_phase_id: Optional[str] = Field(
50
- default=None,
51
- description="Phase to route an item to on nack when requeue=False",
52
- )
53
- unassigned: bool = Field(
54
- default=False,
55
- description="When true, fetch only unassigned cards and claim them during fetch",
56
- )
57
- list_params: Dict[str, Any] = Field(
58
- default_factory=dict,
59
- description="Extra query params forwarded to the items listing endpoint",
60
- )
61
-
62
-
63
- class ErgonPlatformProducerConfig(BaseModel):
64
- """Defaults applied when creating items via dispatch."""
65
-
66
- workflow_id: Optional[str] = Field(default=None, description="Default workflow for created items")
67
- phase_id: Optional[str] = Field(default=None, description="Default phase for created items")
68
- attachment_field_id: Optional[str] = Field(
69
- default=None,
70
- description="Default field ID used when an attachment is provided",
71
- )
72
- default_content_type: Optional[str] = Field(
73
- default=None,
74
- description="Fallback MIME type when it cannot be guessed from the filename",
75
- )
76
- parent_item_id: Optional[str] = Field(
77
- default=None,
78
- description="Default parent item ID used to create child items via dispatch",
79
- )
80
-
81
-
82
- class CreateItemInput(BaseModel):
83
- """Payload describing an item to create, with optional attachment upload."""
84
-
85
- title: str = Field(description="Item title")
86
- workflow_id: Optional[str] = Field(default=None, description="Workflow ID; falls back to producer config")
87
- phase_id: Optional[str] = Field(default=None, description="Target phase ID; falls back to producer config")
88
- parent_item_id: Optional[str] = Field(
89
- default=None,
90
- description="Optional parent item ID to create this item as a child",
91
- )
92
- field_values: Optional[Dict[str, Any]] = Field(default=None, description="Field values keyed by field ID")
93
- attachment: Optional[str] = Field(default=None, description="Local file path to upload after creation")
94
- attachment_field_id: Optional[str] = Field(
95
- default=None,
96
- description="Field ID that receives the attachment; falls back to producer config",
97
- )
98
- content_type: Optional[str] = Field(default=None, description="Override MIME type for the attachment")
99
- extra_fields: Dict[str, Any] = Field(
100
- default_factory=dict,
101
- description="Additional keyword fields forwarded to create_item",
102
- )
103
-
104
- model_config = {"populate_by_name": True}
105
-
106
-
107
- CreateItemPayload = Union[CreateItemInput, Dict[str, Any]]
@@ -1,250 +1,41 @@
1
- import base64
2
- import json
3
- from typing import Any, Dict, List, Optional
4
-
5
- from ..transaction import Transaction
6
- from .models import (
7
- FAILURE_STATUSES,
8
- PROCESSING_STATUSES,
9
- SUCCESS_STATUSES,
10
- CreateItemInput,
11
- CreateItemPayload,
1
+ """Deprecated compatibility exports for Workflows connector helpers."""
2
+
3
+ from .workflows.utils import (
4
+ as_payload,
5
+ build_redispatch_transaction,
6
+ classify_status,
7
+ decode_jwt_claims,
8
+ extract_buckets_file_id,
9
+ extract_buckets_file_id_from_attachments,
10
+ extract_items,
11
+ extract_status_entries,
12
+ extract_status_file_id,
13
+ extract_total,
14
+ find_status_entry,
15
+ get_value,
16
+ item_to_transaction,
17
+ latest_status_entry,
18
+ normalize_create_payload,
19
+ requeue,
20
+ serialize_object,
12
21
  )
13
22
 
14
-
15
- def get_value(obj: Any, key: str, default: Any = None) -> Any:
16
- """Read a key from a dict or an attribute from an object, tolerating both shapes."""
17
- if isinstance(obj, dict):
18
- return obj.get(key, default)
19
- return getattr(obj, key, default)
20
-
21
-
22
- def as_payload(obj: Any) -> Any:
23
- """Convert SDK models to JSON-friendly payloads while leaving plain data untouched."""
24
- if hasattr(obj, "model_dump"):
25
- return obj.model_dump(mode="json")
26
- return obj
27
-
28
-
29
- def serialize_object(obj: Any) -> Any:
30
- if obj is None:
31
- return None
32
- if isinstance(obj, (str, int, float, bool, bytes)):
33
- return obj
34
- if isinstance(obj, dict):
35
- return {k: serialize_object(v) for k, v in obj.items()}
36
- if isinstance(obj, (list, tuple)):
37
- return [serialize_object(item) for item in obj]
38
- if hasattr(obj, "model_dump"):
39
- return obj.model_dump(mode="json")
40
- if hasattr(obj, "to_dict"):
41
- return obj.to_dict()
42
- if hasattr(obj, "__dict__"):
43
- return {k: serialize_object(v) for k, v in obj.__dict__.items() if not k.startswith("_")}
44
- return obj
45
-
46
-
47
- def classify_status(raw_status: str) -> str:
48
- """Map a raw pipeline status string to a coarse state."""
49
- status = (raw_status or "").lower()
50
- if status in SUCCESS_STATUSES:
51
- return "success"
52
- if status in FAILURE_STATUSES:
53
- return "failed"
54
- if status in PROCESSING_STATUSES:
55
- return "processing"
56
- return "unknown"
57
-
58
-
59
- def find_status_entry(statuses: Any, buckets_file_id: str) -> Any:
60
- for status in extract_status_entries(statuses):
61
- if extract_status_file_id(status) == str(buckets_file_id):
62
- return status
63
- return {}
64
-
65
-
66
- def extract_status_entries(statuses: Any) -> List[Any]:
67
- """Normalize SDK attachment status responses to a list of status entries."""
68
- if statuses is None:
69
- return []
70
- if isinstance(statuses, list):
71
- return statuses
72
- if isinstance(statuses, tuple):
73
- return list(statuses)
74
- if isinstance(statuses, dict):
75
- for key in ("items", "data", "results", "statuses", "attachments", "files"):
76
- value = statuses.get(key)
77
- if isinstance(value, list):
78
- return value
79
- if get_value(statuses, "status") is not None or extract_status_file_id(statuses):
80
- return [statuses]
81
- return []
82
- for key in ("items", "data", "results", "statuses", "attachments", "files"):
83
- value = getattr(statuses, key, None)
84
- if isinstance(value, (list, tuple)):
85
- return list(value)
86
- if get_value(statuses, "status") is not None or extract_status_file_id(statuses):
87
- return [statuses]
88
- return []
89
-
90
-
91
- def extract_status_file_id(status: Any) -> Optional[str]:
92
- for key in ("buckets_file_id", "bucketsFileId", "file_id", "fileId"):
93
- value = get_value(status, key)
94
- if value:
95
- return str(value)
96
- return None
97
-
98
-
99
- def latest_status_entry(statuses: Any) -> Any:
100
- entries = extract_status_entries(statuses)
101
- return entries[-1] if entries else {}
102
-
103
-
104
- def extract_buckets_file_id(item: Any, field_id: str) -> Optional[str]:
105
- field_values = get_value(item, "field_values", []) or []
106
- if isinstance(field_values, dict):
107
- return extract_buckets_file_id_from_attachments(field_values.get(field_id))
108
-
109
- for field_value in field_values:
110
- if str(get_value(field_value, "field_id")) != str(field_id):
111
- continue
112
- buckets_file_id = extract_buckets_file_id_from_attachments(get_value(field_value, "value", []))
113
- if buckets_file_id:
114
- return buckets_file_id
115
- return None
116
-
117
-
118
- def extract_buckets_file_id_from_attachments(value: Any) -> Optional[str]:
119
- attachments = value or []
120
- if isinstance(attachments, dict):
121
- for key in ("attachments", "files", "items", "data", "results", "value"):
122
- nested = attachments.get(key)
123
- if isinstance(nested, list):
124
- attachments = nested
125
- break
126
- else:
127
- attachments = [attachments]
128
- if not isinstance(attachments, list):
129
- return None
130
- for attachment in reversed(attachments):
131
- buckets_file_id = get_value(attachment, "buckets_file_id")
132
- if buckets_file_id:
133
- return str(buckets_file_id)
134
- return None
135
-
136
-
137
- def item_to_transaction(item: Any, workflow_id: str) -> Transaction:
138
- payload = serialize_object(item)
139
- payload = payload if isinstance(payload, dict) else {"value": payload}
140
- return Transaction(
141
- id=str(payload.get("id", "")),
142
- payload=payload,
143
- metadata={
144
- "workflow_id": workflow_id,
145
- "phase_id": payload.get("phase_id"),
146
- "company_id": payload.get("company_id"),
147
- "title": payload.get("title"),
148
- },
149
- )
150
-
151
-
152
- def normalize_create_payload(payload: CreateItemPayload) -> Dict[str, Any]:
153
- """Flatten a CreateItemInput/dict into kwargs accepted by the service create_item."""
154
- if isinstance(payload, CreateItemInput):
155
- data: Dict[str, Any] = {
156
- "title": payload.title,
157
- "workflow_id": payload.workflow_id,
158
- "phase_id": payload.phase_id,
159
- "parent_item_id": payload.parent_item_id,
160
- "field_values": payload.field_values,
161
- "attachment": payload.attachment,
162
- "attachment_field_id": payload.attachment_field_id,
163
- "content_type": payload.content_type,
164
- "fields": dict(payload.extra_fields),
165
- }
166
- return data
167
- if isinstance(payload, dict):
168
- data = dict(payload)
169
- data.setdefault("fields", {})
170
- return data
171
- raise TypeError(f"Unsupported create payload type: {type(payload)}")
172
-
173
-
174
- def requeue(transaction: Transaction) -> CreateItemInput:
175
- """Build a CreateItemInput from a transaction payload for re-dispatch."""
176
- data = normalize_create_payload(transaction.payload)
177
- workflow_id = data.get("workflow_id") or transaction.metadata.get("workflow_id")
178
- phase_id = data.get("phase_id") or transaction.metadata.get("phase_id")
179
- title = data.get("title")
180
- if not isinstance(title, str) or not title.strip():
181
- raise ValueError("title is required to requeue a transaction")
182
-
183
- return CreateItemInput(
184
- title=title,
185
- workflow_id=workflow_id,
186
- phase_id=phase_id,
187
- parent_item_id=data.get("parent_item_id"),
188
- field_values=data.get("field_values"),
189
- attachment=data.get("attachment"),
190
- attachment_field_id=data.get("attachment_field_id"),
191
- content_type=data.get("content_type"),
192
- extra_fields=dict(data.get("fields") or {}),
193
- )
194
-
195
-
196
- def build_redispatch_transaction(transaction: Transaction) -> Transaction:
197
- """Prepare a transaction payload suitable for re-dispatch."""
198
- return Transaction(
199
- id=transaction.id,
200
- payload=requeue(transaction),
201
- metadata=dict(transaction.metadata or {}),
202
- )
203
-
204
-
205
- def decode_jwt_claims(jwt_token: str) -> Dict[str, Any]:
206
- """Decode JWT payload claims without signature validation.
207
-
208
- Raises:
209
- ValueError: When the token shape or payload encoding is invalid.
210
- """
211
- parts = jwt_token.split(".")
212
- if len(parts) < 2 or not parts[1]:
213
- raise ValueError("Invalid JWT format: payload segment is missing")
214
-
215
- payload = parts[1]
216
- payload += "=" * (-len(payload) % 4)
217
- try:
218
- decoded = base64.urlsafe_b64decode(payload.encode("ascii"))
219
- claims = json.loads(decoded.decode("utf-8"))
220
- except Exception as exc: # noqa: BLE001
221
- raise ValueError("Invalid JWT payload encoding") from exc
222
-
223
- if not isinstance(claims, dict):
224
- raise ValueError("Invalid JWT payload: expected a JSON object")
225
- return claims
226
-
227
-
228
- def extract_items(response: Any) -> List[Any]:
229
- """Pull the item list out of a Page, dict, or raw list response."""
230
- if isinstance(response, list):
231
- return response
232
- if isinstance(response, dict):
233
- for key in ("items", "data", "results"):
234
- value = response.get(key)
235
- if isinstance(value, list):
236
- return value
237
- return []
238
- items = getattr(response, "items", None)
239
- if isinstance(items, (list, tuple)):
240
- return list(items)
241
- return []
242
-
243
-
244
- def extract_total(response: Any) -> int:
245
- """Read total count from a paginated Page, dict, or SDK response."""
246
- for key in ("total", "total_count", "count"):
247
- value = get_value(response, key)
248
- if value is not None:
249
- return int(value)
250
- return 0
23
+ __all__ = [
24
+ "as_payload",
25
+ "build_redispatch_transaction",
26
+ "classify_status",
27
+ "decode_jwt_claims",
28
+ "extract_buckets_file_id",
29
+ "extract_buckets_file_id_from_attachments",
30
+ "extract_items",
31
+ "extract_status_entries",
32
+ "extract_status_file_id",
33
+ "extract_total",
34
+ "find_status_entry",
35
+ "get_value",
36
+ "item_to_transaction",
37
+ "latest_status_entry",
38
+ "normalize_create_payload",
39
+ "requeue",
40
+ "serialize_object",
41
+ ]
@@ -0,0 +1,52 @@
1
+ from typing import TYPE_CHECKING, Any
2
+
3
+ from ..._lazy import exported_names, load_optional_export
4
+ from .models import (
5
+ FAILURE_STATUSES,
6
+ PROCESSING_STATUSES,
7
+ SUCCESS_STATUSES,
8
+ CreateItemInput,
9
+ CreateItemPayload,
10
+ ErgonPlatformConsumerConfig,
11
+ ErgonPlatformProducerConfig,
12
+ )
13
+
14
+ if TYPE_CHECKING:
15
+ from ._operations import ErgonPlatformWorkflowsService
16
+ from .async_connector import AsyncErgonPlatformConnector
17
+ from .connector import ErgonPlatformConnector
18
+
19
+ _LAZY_EXPORTS = {
20
+ "AsyncErgonPlatformConnector": "async_connector",
21
+ "ErgonPlatformConnector": "connector",
22
+ "ErgonPlatformWorkflowsService": "_operations",
23
+ }
24
+
25
+
26
+ def __getattr__(name: str) -> Any:
27
+ return load_optional_export(
28
+ name=name,
29
+ package=__name__,
30
+ exports=_LAZY_EXPORTS,
31
+ namespace=globals(),
32
+ extra="ergon-platform",
33
+ dependencies=("ergon_platform", "httpx"),
34
+ )
35
+
36
+
37
+ def __dir__() -> list[str]:
38
+ return exported_names(globals(), _LAZY_EXPORTS)
39
+
40
+
41
+ __all__ = [
42
+ "AsyncErgonPlatformConnector",
43
+ "CreateItemInput",
44
+ "CreateItemPayload",
45
+ "ErgonPlatformConnector",
46
+ "ErgonPlatformConsumerConfig",
47
+ "ErgonPlatformProducerConfig",
48
+ "ErgonPlatformWorkflowsService",
49
+ "FAILURE_STATUSES",
50
+ "PROCESSING_STATUSES",
51
+ "SUCCESS_STATUSES",
52
+ ]
@@ -5,8 +5,8 @@ from typing import Any, Dict, List, Optional
5
5
 
6
6
  import httpx
7
7
 
8
- from ..transaction import Transaction
9
- from .models import ErgonPlatformClient
8
+ from ...transaction import Transaction
9
+ from ..models import ErgonPlatformClient
10
10
  from .utils import (
11
11
  as_payload,
12
12
  classify_status,
@@ -22,7 +22,9 @@ from .utils import (
22
22
  )
23
23
 
24
24
 
25
- class _ErgonPlatformOperations:
25
+ class ErgonPlatformWorkflowsService:
26
+ """Workflows HTTP, pagination, claim, and attachment service."""
27
+
26
28
  def __init__(self, config: ErgonPlatformClient, client: Any) -> None:
27
29
  self.config = config
28
30
  self.client = client
@@ -262,3 +264,6 @@ class _ErgonPlatformOperations:
262
264
  seen_ids.add(field_id)
263
265
  merged.append(field)
264
266
  return merged
267
+
268
+
269
+ _ErgonPlatformOperations = ErgonPlatformWorkflowsService