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
@@ -0,0 +1,250 @@
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,
12
+ )
13
+
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
@@ -112,6 +112,12 @@ class AsyncNylasConnector(AsyncConnector):
112
112
  if config is None:
113
113
  return
114
114
 
115
+ if config.delete:
116
+ if transaction.metadata.get("fetch_unit") == "thread":
117
+ raise ValueError("AckActionConfig(delete=True) is only supported for message transactions")
118
+ await self.service.delete_message(transaction.id)
119
+ return
120
+
115
121
  body = build_ack_request_body(config)
116
122
  if not body:
117
123
  return
@@ -116,6 +116,9 @@ class AsyncNylasService:
116
116
  async def update_message(self, message_id: str, request_body: Dict[str, Any]) -> Dict[str, Any]:
117
117
  return await asyncio.to_thread(self._sync.update_message, message_id, request_body)
118
118
 
119
+ async def delete_message(self, message_id: str) -> None:
120
+ await asyncio.to_thread(self._sync.delete_message, message_id)
121
+
119
122
  async def list_folders(self) -> List[Dict[str, Any]]:
120
123
  return await asyncio.to_thread(self._sync.list_folders)
121
124
 
@@ -102,6 +102,12 @@ class NylasConnector(Connector):
102
102
  if config is None:
103
103
  return
104
104
 
105
+ if config.delete:
106
+ if transaction.metadata.get("fetch_unit") == "thread":
107
+ raise ValueError("AckActionConfig(delete=True) is only supported for message transactions")
108
+ self.service.delete_message(transaction.id)
109
+ return
110
+
105
111
  body = build_ack_request_body(config)
106
112
  if not body:
107
113
  return
@@ -82,6 +82,14 @@ class AckActionConfig(BaseModel):
82
82
  move_to_folder_id: Optional[str] = Field(default=None, description="Folder ID to move message to")
83
83
  add_star: bool = Field(default=False, description="Star message on ack")
84
84
  archive: bool = Field(default=False, description="Archive message on ack (provider-specific)")
85
+ delete: bool = Field(
86
+ default=False,
87
+ description=(
88
+ "Permanently delete message on ack via the Nylas hard_delete API. "
89
+ "Requires hard delete to be enabled in the Nylas Dashboard. "
90
+ "When True, other ack actions (mark_as_read, move, star, archive) are skipped."
91
+ ),
92
+ )
85
93
 
86
94
 
87
95
  class NylasAuthClient(BaseModel):
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  from typing import Any, Dict, List, Optional
3
+ from urllib.parse import quote
3
4
 
4
5
  from ..transaction import Transaction
5
6
  from .models import (
@@ -259,6 +260,14 @@ class NylasService:
259
260
  data = extract_response_data(response)
260
261
  return data if isinstance(data, dict) else serialize_nylas_object(data)
261
262
 
263
+ def delete_message(self, message_id: str) -> None:
264
+ # nylas>=6 does not expose DELETE query parameters on messages.destroy().
265
+ self._nylas.http_client._execute(
266
+ method="DELETE",
267
+ path=f"/v3/grants/{self.grant_id}/messages/{quote(message_id, safe='')}",
268
+ query_params={"hard_delete": "true"},
269
+ )
270
+
262
271
  def list_folders(self) -> List[Dict[str, Any]]:
263
272
  response = self._nylas.folders.list(self.grant_id)
264
273
  data = extract_response_data(response) or []
@@ -62,11 +62,9 @@ def merge_query_filter(
62
62
  query_field_names = set(MessageQueryFilter.model_fields.keys())
63
63
  merged: Dict[str, Any] = {}
64
64
  if base is not None:
65
- merged.update(
66
- {k: v for k, v in base.model_dump(exclude_none=True, by_alias=True).items() if k in query_field_names}
67
- )
65
+ merged.update({k: v for k, v in base.model_dump(exclude_none=True).items() if k in query_field_names})
68
66
  if overrides is not None:
69
- merged.update(overrides.model_dump(exclude_none=True, by_alias=True))
67
+ merged.update({k: v for k, v in overrides.model_dump(exclude_none=True).items() if k in query_field_names})
70
68
  for key, value in kwargs.items():
71
69
  if value is not None and key in query_field_names:
72
70
  merged[key] = value
@@ -136,7 +136,6 @@ class ConsumerMixin(ABC):
136
136
  # -----------------------
137
137
  # 3) SUCCESS HANDLER
138
138
  # -----------------------
139
- logger.info(f"Invoking success handler for transaction {transaction.id} with outcome: '{process_result}'")
140
139
  success_ok, success_result = self._handle_success(transaction, process_result, policy.success.retry)
141
140
 
142
141
  if not success_ok:
@@ -679,7 +678,6 @@ class AsyncConsumerMixin(ABC):
679
678
  # -----------------------
680
679
  # 3) SUCCESS HANDLER
681
680
  # -----------------------
682
- logger.info(f"Invoking success handler for transaction {transaction.id} with outcome: '{process_result}'")
683
681
  success_ok, success_result = await self._handle_success(transaction, process_result, policy.success.retry)
684
682
 
685
683
  if not success_ok:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ergon-framework-python
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Ergon internal task-oriented project bootstrapper
5
5
  Author-email: Ergondata Technologies <anza.vossos@protonmail.com>
6
6
  License-Expression: MIT
@@ -29,14 +29,14 @@ Requires-Dist: aio-pika>=9.0.0; extra == "all"
29
29
  Requires-Dist: aiobotocore>=2.13.0; extra == "all"
30
30
  Requires-Dist: asyncpg>=0.29.0; extra == "all"
31
31
  Requires-Dist: boto3>=1.35.0; extra == "all"
32
- Requires-Dist: ergon-platform-sdk>=0.1.0; extra == "all"
32
+ Requires-Dist: ergon-platform-sdk>=0.2.0; extra == "all"
33
33
  Requires-Dist: httpx>=0.28.0; extra == "all"
34
34
  Requires-Dist: nylas>=6.0.0; extra == "all"
35
35
  Requires-Dist: openpyxl>=3.1.5; extra == "all"
36
36
  Requires-Dist: pika>=1.3.0; extra == "all"
37
37
  Requires-Dist: requests>=2.32.5; extra == "all"
38
38
  Provides-Extra: ergon-platform
39
- Requires-Dist: ergon-platform-sdk>=0.1.0; extra == "ergon-platform"
39
+ Requires-Dist: ergon-platform-sdk>=0.2.0; extra == "ergon-platform"
40
40
  Requires-Dist: httpx>=0.28.0; extra == "ergon-platform"
41
41
  Provides-Extra: excel
42
42
  Requires-Dist: openpyxl>=3.1.5; extra == "excel"
@@ -1,4 +1,4 @@
1
- ergon/__init__.py,sha256=ebO_7kOv-MSGjDVMRDELKKWgzig6ALBEG56bmQWCzBo,218
1
+ ergon/__init__.py,sha256=o88UpQYh3RcjogyA8PsDjekDAK6Xfth93UCFdDWixyo,218
2
2
  ergon/cli.py,sha256=CF8PvOjIguR18a657aEBEyhFXUoSVtSRVXv5PfnuWtA,6021
3
3
  ergon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  ergon/bootstrap/src/__project__/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -22,30 +22,47 @@ ergon/bootstrap/src/__project__/tasks/example_task/exceptions.py,sha256=LTWwquhM
22
22
  ergon/bootstrap/src/__project__/tasks/example_task/helpers.py,sha256=uR_XZEtxR6JzbJloi7OhJb77f7Wc6pnOe1W3CHvl8vE,122
23
23
  ergon/bootstrap/src/__project__/tasks/example_task/schemas.py,sha256=3_qANKlJIQ90gaRNrDuBAM42UNzfDbLI4-F0kkjjWHc,155
24
24
  ergon/bootstrap/src/__project__/tasks/example_task/task.py,sha256=XnmVg-B0N8Ld48FMLJgGfTTJLjmpy5Nog_Gaj1ruVEQ,36
25
- ergon/connector/__init__.py,sha256=ybPKXBpRaOIWl6TM998vLYalKAGFGGVE5Mh6nbiEdIA,5658
25
+ ergon/connector/__init__.py,sha256=qBgpM6yArVb-ns7l09RN6hYU84Rxx1_3aD4ZZiCFTRE,6648
26
26
  ergon/connector/_lazy.py,sha256=ANsKY3JTtmVo8Z8p3ey3LwkQGVVYITKO1eEK66IvA3U,1690
27
27
  ergon/connector/connector.py,sha256=jaF1iXKALE1IHHfcP54mTD5mvj-wzk5iNaLo96IOcDI,3944
28
28
  ergon/connector/transaction.py,sha256=LMGEFfisdjGGCPrWps3nYJ-SRBKa-P2pOFmwbSgDN-E,291
29
- ergon/connector/ergon_platform/__init__.py,sha256=j4CMZYLg6EgLpfMNr8dSPELC3V-ou7zoWfnZ1KIhrbY,1026
29
+ ergon/connector/ergon_platform/__init__.py,sha256=BYp8roDI5JyKdwLaVGeE9Qnx3VWt4gpPdAdb258YKuw,3807
30
30
  ergon/connector/ergon_platform/_client.py,sha256=RQbTRanK0pF_JzJi7EF9_6d4veCC4_xfXHk5A0nL5jE,812
31
- ergon/connector/ergon_platform/_operations.py,sha256=-HpkrTjJm7D_rw2K4YW0s1e7B0sXxod1g0fKMDs3Cdg,9614
32
- ergon/connector/ergon_platform/async_connector.py,sha256=B6VArBW_e-qYV5ZK8RCnH6ZkrbTe8u_5VbISs9Xkd3M,8398
33
- ergon/connector/ergon_platform/connector.py,sha256=tp-ogXNlZDmt90X0wpRj5C06SHuIiO6sXmPY99Vuii4,7511
34
- ergon/connector/ergon_platform/models.py,sha256=qxUZE9Gu-F9n8pJz0K73NlltYJ2tLYmQfqZpXkefGf8,4366
35
- ergon/connector/ergon_platform/utils.py,sha256=z0pMSPCzTBeQfHYaLCQInzJuulkMVFx_gLpvRu9XKUM,8778
31
+ ergon/connector/ergon_platform/async_connector.py,sha256=Is4wpMO9dtPNJoj1Y8WeyZg8bpskHbcpApdVYl45OYM,184
32
+ ergon/connector/ergon_platform/connector.py,sha256=pIRBPoWTLs8q_5_2Dby7fNEMQJWsnVOrt7dTJdFZdMo,162
33
+ ergon/connector/ergon_platform/models.py,sha256=ydrowIUaMhiZ08iJPKynkJU19RvqmogIreQFeJKhCuw,1248
34
+ ergon/connector/ergon_platform/utils.py,sha256=eZU8PHwarpz--EWgz74MkfPLD2AbKp5pmNveijd13oc,987
35
+ ergon/connector/ergon_platform/channels/__init__.py,sha256=wEpy-8p1mwQNZmosO17hOZ3DIPisX3P14T6WVbyMeBo,1480
36
+ ergon/connector/ergon_platform/channels/adapters.py,sha256=LoylPshBCMi5R32Ms-IHe_H2rCO4QFrUWMvscRWkmQ8,8123
37
+ ergon/connector/ergon_platform/channels/async_connector.py,sha256=iKqj-I_2k6DPRd-r0FZ7li659L0Rf3k5--lT3VCBd-8,12853
38
+ ergon/connector/ergon_platform/channels/connector.py,sha256=UEgT7so-CWEVPUmxhBzkX4WnxC5PJVlhs-fDd1o1qYk,11637
39
+ ergon/connector/ergon_platform/channels/models.py,sha256=00WTLbYdputWd9FHy9D5h3X4AAiAIBeYlBeH5cGY6vA,18292
40
+ ergon/connector/ergon_platform/channels/services/__init__.py,sha256=EQBc2Sc2mL3gwitd1cPL2wpYnio7C7nHzAA1ml45UzQ,1091
41
+ ergon/connector/ergon_platform/channels/services/activity.py,sha256=SxN3y2VZDulPxiqy6XNDipVvhCk9uDzsIeSXs9Hd6WA,9756
42
+ ergon/connector/ergon_platform/channels/services/addresses.py,sha256=YNjMTqZidfqo5aOXa32F_rXIukVKxE04ULrdBBm2L4k,11288
43
+ ergon/connector/ergon_platform/channels/services/attachments.py,sha256=IT9bU8p3X93StRFpQAofcf2nuBTpqfpqEuabAccj05M,10216
44
+ ergon/connector/ergon_platform/channels/services/messages.py,sha256=us0gemfUAk3GKdC7-mXW0V7r7oCIbD73qIYXgy6W9Oc,4474
45
+ ergon/connector/ergon_platform/channels/services/records.py,sha256=yv_xl0lFhksk0baHpHkFlqA8X3YaoEOQ9jpOUT5guk0,2483
46
+ ergon/connector/ergon_platform/channels/services/service.py,sha256=BjqRYeLUZtzXpPeOLjgNdlq7TJXFc28SJtMH-Uha2DY,1160
47
+ ergon/connector/ergon_platform/workflows/__init__.py,sha256=W5TDhYmldZqfQRJ4G8siFis7AAasIAuZhtqrwlR5QFk,1315
48
+ ergon/connector/ergon_platform/workflows/_operations.py,sha256=IJPsiCEo27UvRKhGTrxn1HqCxbaPfVLwV0mFGgs0sOw,9750
49
+ ergon/connector/ergon_platform/workflows/async_connector.py,sha256=PYqLxDAw1M0T6dR9SckohT1nhibPyRoBhdu9JFJ2r90,8463
50
+ ergon/connector/ergon_platform/workflows/connector.py,sha256=gooEFbkzVB0ig-a29sD__hZJeNEQ9JfDi2mxBuLQGB0,7576
51
+ ergon/connector/ergon_platform/workflows/models.py,sha256=_a2qH9Bkx5f2IqWb0LdqML0D088aH7AwApe204REoEE,3591
52
+ ergon/connector/ergon_platform/workflows/utils.py,sha256=---WoYGjyAqKLl-OWOqpkvFDK8HCeiApmz47nJ3z958,8779
36
53
  ergon/connector/excel/__init__.py,sha256=YHrcMRwW96DtvRs2CNpKK5GW3lJXZSdClLUWCDMgzsA,1013
37
54
  ergon/connector/excel/connector.py,sha256=Tx2T9Ggo8pPAaSmua4j_PMu_QiiiezWm1Nru3Jr0E94,5327
38
55
  ergon/connector/excel/models.py,sha256=9RSCaFJAaFTTI0BMZ8S87SWvRqpEsMA50Mw7Gc47_dE,905
39
56
  ergon/connector/excel/service.py,sha256=H6T4oJ46espyHXoJRLsZT7gEje5elqYozChsRPI4aXc,3339
40
57
  ergon/connector/nylas/__init__.py,sha256=IGcKSq3b9dynpnQyPULyTZyAbLsLMVBNArKuF3UXc6M,1798
41
58
  ergon/connector/nylas/async_auth_service.py,sha256=sEMvoSCDjRFUSZgmN39L4e5lI2mqh7s_5kmW4nu5mGo,604
42
- ergon/connector/nylas/async_connector.py,sha256=X6mqmKqk_L5RICKwG5pp76HWciMsOGBFlOrXbZFrcyU,4491
43
- ergon/connector/nylas/async_service.py,sha256=mX5UCptdBfxgErQyqP84jyTMpqkHY51QK2GHqNKuj1g,4664
59
+ ergon/connector/nylas/async_connector.py,sha256=VXSPY31iYJYn1KPmmxqwhfKi1OxwHXl94xYpXx9oNbY,4774
60
+ ergon/connector/nylas/async_service.py,sha256=lkxWEAkaMCKD2X7E9ijyuE8CjnR3ITdB1sH3lj1wAFM,4797
44
61
  ergon/connector/nylas/auth_service.py,sha256=f2FguCE5AqqInig1su4Z-rMMoh6zXn9UY7M2eb3aYs0,1835
45
- ergon/connector/nylas/connector.py,sha256=rUcXo_IZmtfHtMlja_bStW695m2lUoxugFKOmmWhKc0,4248
46
- ergon/connector/nylas/models.py,sha256=5Hf4kxC_8b6QFBdHG_YUVfeSfzmfjUFRFpUUdCWXH8Q,9896
47
- ergon/connector/nylas/service.py,sha256=Uxmh36cCerBEUtbfNTY4ITydDAWH64dnXRCxQTp4Ep4,11139
48
- ergon/connector/nylas/utils.py,sha256=J0VyBiAC2lkDRaMyg1nR_Z7gZQEV5yyw22Uz1kWJHl8,4714
62
+ ergon/connector/nylas/connector.py,sha256=4mIRdaQ6YH6j1gt4htAVeXVoKvZMYses6M3d2G6GCAs,4525
63
+ ergon/connector/nylas/models.py,sha256=dqPG5xhM5ZBFKN1hPW0US7lDztSaV-CZwwIherrdDkA,10230
64
+ ergon/connector/nylas/service.py,sha256=kj0zY0cvBWkqlne_gZyw4fFDDiIJ5ACB4PX7vYksE3Q,11525
65
+ ergon/connector/nylas/utils.py,sha256=jP-_hslfSWQgS4Sh5FPOKKLnX-n68m38mkuHOcRVaFk,4715
49
66
  ergon/connector/pipefy/__init__.py,sha256=FI9OfHDa_914NC2s-SMjNYwZj6tpgBve7TER9SE9zo4,1119
50
67
  ergon/connector/pipefy/async_connector.py,sha256=Ls4fRcTD21gWbeSj32WpSID6b5ZYTNBjWN7kNw-9Ey0,1739
51
68
  ergon/connector/pipefy/async_service.py,sha256=Kpd-LVTet3Ve6z85pUWZ2uUWFpgTaF74znbKFzmXAMA,26298
@@ -82,7 +99,7 @@ ergon/task/policies.py,sha256=3x1SV-yt3FXNgmnATdQdpRtsDtlskjx582SpbC6UH6A,7358
82
99
  ergon/task/runner.py,sha256=xUaMSO6V_iOq6QJdiyW1IA5kfWuwQjh1IJl6HUh06hY,20344
83
100
  ergon/task/utils.py,sha256=OmlP2AhLM32V8O9OMky6DdSvxwmMNn9x2LTguf0y-M0,2501
84
101
  ergon/task/mixins/__init__.py,sha256=6A8vNgdjaQYNJvymWNF-kBN2oTaQBYRLctS3Sq1w_-Y,320
85
- ergon/task/mixins/consumer.py,sha256=pImeLqO3tGnoV9nUOaRNbusBWj-gGg170eRAzloT_08,52508
102
+ ergon/task/mixins/consumer.py,sha256=DhN2qBtNtB6xdKEdCokw1Z5ic2W8QfoUCm1QH_YPIFA,52270
86
103
  ergon/task/mixins/metrics.py,sha256=4bavwo8koWiN5ADD8t5qd2BVeVcgxo6ddzq-xOybeTg,13159
87
104
  ergon/task/mixins/producer.py,sha256=xENTZdZ7t0dpw5YsreQT20iTycSaj1EA4ny-60u-SWM,20427
88
105
  ergon/telemetry/__init__.py,sha256=8waeIAHEx6tMXWfw-zOEKgjrg7V8S1poG070MdAmi_8,100
@@ -92,9 +109,9 @@ ergon/telemetry/metrics.py,sha256=0T_CuNw9P5AG1U9k1-bNp1g7McyiNLUIt_zKyLOtrnA,28
92
109
  ergon/telemetry/tracing.py,sha256=_ktiZWAgB1DU-uN91Mzr0iYNXxbCN21LnKiRo5SOJxY,4454
93
110
  ergon/utils/__init__.py,sha256=M0_VCjMN7jvSPlRZLZHeFKTHAl1zu3BnAhjrzJjDfiI,57
94
111
  ergon/utils/env.py,sha256=lji4xENvfHqg2GTGnzG95VKpxxM4f3DHIKKP61xQG08,621
95
- ergon_framework_python-0.2.0.dist-info/licenses/LICENSE,sha256=bWCIhHzaadz_ecLdCdtwyMafeQ17s2d7_FSSuSuEcDs,1079
96
- ergon_framework_python-0.2.0.dist-info/METADATA,sha256=OTKjdM1Hyw1xT2pQAXoDHa6IMlbHtw6ulSmk1pIbaNs,16914
97
- ergon_framework_python-0.2.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
98
- ergon_framework_python-0.2.0.dist-info/entry_points.txt,sha256=reZ934txb5OrtcNBgTGqCsXa1biUDQWubD2a9fGZynE,42
99
- ergon_framework_python-0.2.0.dist-info/top_level.txt,sha256=KSPt6N7RzsjU7PRAalWQ9Cul7YTUxbo84yAJ-y2vLm8,6
100
- ergon_framework_python-0.2.0.dist-info/RECORD,,
112
+ ergon_framework_python-0.2.2.dist-info/licenses/LICENSE,sha256=bWCIhHzaadz_ecLdCdtwyMafeQ17s2d7_FSSuSuEcDs,1079
113
+ ergon_framework_python-0.2.2.dist-info/METADATA,sha256=VNSh11YTgbAxLcsXPSj44s5pvfEniE9QST6-JEmsK1w,16914
114
+ ergon_framework_python-0.2.2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
115
+ ergon_framework_python-0.2.2.dist-info/entry_points.txt,sha256=reZ934txb5OrtcNBgTGqCsXa1biUDQWubD2a9fGZynE,42
116
+ ergon_framework_python-0.2.2.dist-info/top_level.txt,sha256=KSPt6N7RzsjU7PRAalWQ9Cul7YTUxbo84yAJ-y2vLm8,6
117
+ ergon_framework_python-0.2.2.dist-info/RECORD,,