ergon-framework-python 0.1.9__tar.gz → 0.2.1__tar.gz

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 (115) hide show
  1. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/PKG-INFO +40 -11
  2. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/README.md +12 -0
  3. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/pyproject.toml +31 -11
  4. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/__init__.py +1 -1
  5. ergon_framework_python-0.2.1/src/ergon/connector/__init__.py +203 -0
  6. ergon_framework_python-0.2.1/src/ergon/connector/_lazy.py +51 -0
  7. ergon_framework_python-0.2.1/src/ergon/connector/ergon_platform/__init__.py +43 -0
  8. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/ergon_platform/_client.py +4 -1
  9. ergon_framework_python-0.2.1/src/ergon/connector/excel/__init__.py +44 -0
  10. ergon_framework_python-0.2.1/src/ergon/connector/nylas/__init__.py +75 -0
  11. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/nylas/async_connector.py +6 -0
  12. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/nylas/async_service.py +3 -0
  13. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/nylas/connector.py +6 -0
  14. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/nylas/models.py +8 -0
  15. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/nylas/service.py +9 -0
  16. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/nylas/utils.py +2 -4
  17. ergon_framework_python-0.2.1/src/ergon/connector/pipefy/__init__.py +49 -0
  18. ergon_framework_python-0.2.1/src/ergon/connector/postgres/__init__.py +37 -0
  19. ergon_framework_python-0.2.1/src/ergon/connector/rabbitmq/__init__.py +57 -0
  20. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/rabbitmq/async_service.py +192 -224
  21. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/rabbitmq/models.py +9 -1
  22. ergon_framework_python-0.2.1/src/ergon/connector/sqs/__init__.py +43 -0
  23. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon_framework_python.egg-info/PKG-INFO +40 -11
  24. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon_framework_python.egg-info/SOURCES.txt +2 -0
  25. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon_framework_python.egg-info/requires.txt +32 -9
  26. ergon_framework_python-0.2.1/tests/test_optional_connectors.py +88 -0
  27. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/tests/test_smoke.py +1 -1
  28. ergon_framework_python-0.1.9/src/ergon/connector/__init__.py +0 -116
  29. ergon_framework_python-0.1.9/src/ergon/connector/ergon_platform/__init__.py +0 -17
  30. ergon_framework_python-0.1.9/src/ergon/connector/excel/__init__.py +0 -18
  31. ergon_framework_python-0.1.9/src/ergon/connector/nylas/__init__.py +0 -45
  32. ergon_framework_python-0.1.9/src/ergon/connector/pipefy/__init__.py +0 -21
  33. ergon_framework_python-0.1.9/src/ergon/connector/postgres/__init__.py +0 -11
  34. ergon_framework_python-0.1.9/src/ergon/connector/rabbitmq/__init__.py +0 -29
  35. ergon_framework_python-0.1.9/src/ergon/connector/sqs/__init__.py +0 -15
  36. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/LICENSE +0 -0
  37. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/setup.cfg +0 -0
  38. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/__init__.py +0 -0
  39. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/_observability/docker-compose.telemetry.yml +0 -0
  40. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/_observability/grafana.yaml +0 -0
  41. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/_observability/loki.yaml +0 -0
  42. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/_observability/otel-collector-config.yaml +0 -0
  43. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/_observability/prometheus.yaml +0 -0
  44. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/_observability/tempo.yaml +0 -0
  45. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/connectors/__init__.py +0 -0
  46. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/main.py +0 -0
  47. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/__init__.py +0 -0
  48. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/constants.py +0 -0
  49. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/example_task/__init__.py +0 -0
  50. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/example_task/config.py +0 -0
  51. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/example_task/exceptions.py +0 -0
  52. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/example_task/helpers.py +0 -0
  53. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/example_task/schemas.py +0 -0
  54. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/example_task/task.py +0 -0
  55. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/exceptions.py +0 -0
  56. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/helpers.py +0 -0
  57. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/schemas.py +0 -0
  58. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/bootstrap/src/__project__/tasks/settings.py +0 -0
  59. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/cli.py +0 -0
  60. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/connector.py +0 -0
  61. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/ergon_platform/_operations.py +0 -0
  62. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/ergon_platform/async_connector.py +0 -0
  63. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/ergon_platform/connector.py +0 -0
  64. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/ergon_platform/models.py +0 -0
  65. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/ergon_platform/utils.py +0 -0
  66. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/excel/connector.py +0 -0
  67. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/excel/models.py +0 -0
  68. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/excel/service.py +0 -0
  69. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/nylas/async_auth_service.py +0 -0
  70. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/nylas/auth_service.py +0 -0
  71. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/pipefy/async_connector.py +0 -0
  72. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/pipefy/async_service.py +0 -0
  73. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/pipefy/connector.py +0 -0
  74. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/pipefy/models.py +0 -0
  75. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/pipefy/service.py +0 -0
  76. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/pipefy/version.py +0 -0
  77. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/postgres/async_connector.py +0 -0
  78. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/postgres/async_service.py +0 -0
  79. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/postgres/models.py +0 -0
  80. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/rabbitmq/async_connector.py +0 -0
  81. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/rabbitmq/connector.py +0 -0
  82. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/rabbitmq/helper.py +0 -0
  83. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/rabbitmq/service.py +0 -0
  84. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/sqs/async_connector.py +0 -0
  85. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/sqs/async_service.py +0 -0
  86. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/sqs/connector.py +0 -0
  87. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/sqs/models.py +0 -0
  88. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/sqs/service.py +0 -0
  89. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/connector/transaction.py +0 -0
  90. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/py.typed +0 -0
  91. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/service/__init__.py +0 -0
  92. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/service/service.py +0 -0
  93. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/__init__.py +0 -0
  94. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/base.py +0 -0
  95. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/exceptions.py +0 -0
  96. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/helpers.py +0 -0
  97. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/liveness.py +0 -0
  98. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/manager.py +0 -0
  99. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/mixins/__init__.py +0 -0
  100. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/mixins/consumer.py +0 -0
  101. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/mixins/metrics.py +0 -0
  102. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/mixins/producer.py +0 -0
  103. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/policies.py +0 -0
  104. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/runner.py +0 -0
  105. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/task/utils.py +0 -0
  106. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/telemetry/__init__.py +0 -0
  107. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/telemetry/_resource.py +0 -0
  108. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/telemetry/logging.py +0 -0
  109. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/telemetry/metrics.py +0 -0
  110. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/telemetry/tracing.py +0 -0
  111. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/utils/__init__.py +0 -0
  112. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon/utils/env.py +0 -0
  113. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon_framework_python.egg-info/dependency_links.txt +0 -0
  114. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon_framework_python.egg-info/entry_points.txt +0 -0
  115. {ergon_framework_python-0.1.9 → ergon_framework_python-0.2.1}/src/ergon_framework_python.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ergon-framework-python
3
- Version: 0.1.9
3
+ Version: 0.2.1
4
4
  Summary: Ergon internal task-oriented project bootstrapper
5
5
  Author-email: Ergondata Technologies <anza.vossos@protonmail.com>
6
6
  License-Expression: MIT
@@ -16,26 +16,43 @@ Classifier: Programming Language :: Python :: 3.13
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: aio-pika>=9.0.0
20
- Requires-Dist: aiobotocore>=2.13.0
21
19
  Requires-Dist: async-timeout>=5.0.1
22
- Requires-Dist: asyncpg>=0.29.0
23
- Requires-Dist: boto3>=1.35.0
24
- Requires-Dist: ergon-platform-sdk>=0.1.0
25
- Requires-Dist: httpx>=0.28.0
26
20
  Requires-Dist: more-itertools>=10.8.0
27
- Requires-Dist: openpyxl>=3.1.5
28
21
  Requires-Dist: opentelemetry-api>=1.38.0
29
22
  Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.38.0
30
23
  Requires-Dist: opentelemetry-sdk>=1.38.0
31
- Requires-Dist: pika>=1.3.0
32
24
  Requires-Dist: pydantic>=2.12.4
33
25
  Requires-Dist: python-dotenv>=1.2.1
34
26
  Requires-Dist: python-json-logger>=4.0.0
35
- Requires-Dist: requests>=2.32.5
27
+ Provides-Extra: all
28
+ Requires-Dist: aio-pika>=9.0.0; extra == "all"
29
+ Requires-Dist: aiobotocore>=2.13.0; extra == "all"
30
+ Requires-Dist: asyncpg>=0.29.0; extra == "all"
31
+ Requires-Dist: boto3>=1.35.0; extra == "all"
32
+ Requires-Dist: ergon-platform-sdk>=0.1.0; extra == "all"
33
+ Requires-Dist: httpx>=0.28.0; extra == "all"
34
+ Requires-Dist: nylas>=6.0.0; extra == "all"
35
+ Requires-Dist: openpyxl>=3.1.5; extra == "all"
36
+ Requires-Dist: pika>=1.3.0; extra == "all"
37
+ Requires-Dist: requests>=2.32.5; extra == "all"
38
+ Provides-Extra: ergon-platform
39
+ Requires-Dist: ergon-platform-sdk>=0.1.0; extra == "ergon-platform"
40
+ Requires-Dist: httpx>=0.28.0; extra == "ergon-platform"
41
+ Provides-Extra: excel
42
+ Requires-Dist: openpyxl>=3.1.5; extra == "excel"
36
43
  Provides-Extra: nylas
37
44
  Requires-Dist: nylas>=6.0.0; extra == "nylas"
38
- Provides-Extra: ergon-platform
45
+ Provides-Extra: pipefy
46
+ Requires-Dist: httpx>=0.28.0; extra == "pipefy"
47
+ Requires-Dist: requests>=2.32.5; extra == "pipefy"
48
+ Provides-Extra: postgres
49
+ Requires-Dist: asyncpg>=0.29.0; extra == "postgres"
50
+ Provides-Extra: rabbitmq
51
+ Requires-Dist: aio-pika>=9.0.0; extra == "rabbitmq"
52
+ Requires-Dist: pika>=1.3.0; extra == "rabbitmq"
53
+ Provides-Extra: sqs
54
+ Requires-Dist: aiobotocore>=2.13.0; extra == "sqs"
55
+ Requires-Dist: boto3>=1.35.0; extra == "sqs"
39
56
  Dynamic: license-file
40
57
 
41
58
  # Ergon Framework — Python SDK
@@ -54,6 +71,18 @@ Dynamic: license-file
54
71
  pip install ergon-framework-python
55
72
  ```
56
73
 
74
+ Connector integrations are optional extras, so a core installation does not
75
+ pull in client libraries that your application does not use:
76
+
77
+ ```bash
78
+ pip install 'ergon-framework-python[rabbitmq]'
79
+ pip install 'ergon-framework-python[sqs,postgres]'
80
+ pip install 'ergon-framework-python[all]'
81
+ ```
82
+
83
+ Available extras are `rabbitmq`, `sqs`, `postgres`, `pipefy`, `excel`,
84
+ `ergon-platform`, and `nylas`.
85
+
57
86
  For local development, install in editable mode:
58
87
 
59
88
  ```bash
@@ -14,6 +14,18 @@
14
14
  pip install ergon-framework-python
15
15
  ```
16
16
 
17
+ Connector integrations are optional extras, so a core installation does not
18
+ pull in client libraries that your application does not use:
19
+
20
+ ```bash
21
+ pip install 'ergon-framework-python[rabbitmq]'
22
+ pip install 'ergon-framework-python[sqs,postgres]'
23
+ pip install 'ergon-framework-python[all]'
24
+ ```
25
+
26
+ Available extras are `rabbitmq`, `sqs`, `postgres`, `pipefy`, `excel`,
27
+ `ergon-platform`, and `nylas`.
28
+
17
29
  For local development, install in editable mode:
18
30
 
19
31
  ```bash
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ergon-framework-python"
3
- version = "0.1.9"
3
+ version = "0.2.1"
4
4
  description = "Ergon internal task-oriented project bootstrapper"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -18,28 +18,48 @@ classifiers = [
18
18
  "Programming Language :: Python :: 3.13",
19
19
  ]
20
20
  dependencies = [
21
- "aio-pika>=9.0.0",
22
- "aiobotocore>=2.13.0",
23
21
  "async-timeout>=5.0.1",
24
- "asyncpg>=0.29.0",
25
- "boto3>=1.35.0",
26
- "ergon-platform-sdk>=0.1.0",
27
- "httpx>=0.28.0",
28
22
  "more-itertools>=10.8.0",
29
- "openpyxl>=3.1.5",
30
23
  "opentelemetry-api>=1.38.0",
31
24
  "opentelemetry-exporter-otlp-proto-grpc>=1.38.0",
32
25
  "opentelemetry-sdk>=1.38.0",
33
- "pika>=1.3.0",
34
26
  "pydantic>=2.12.4",
35
27
  "python-dotenv>=1.2.1",
36
28
  "python-json-logger>=4.0.0",
37
- "requests>=2.32.5",
38
29
  ]
39
30
 
40
31
  [project.optional-dependencies]
32
+ all = [
33
+ "aio-pika>=9.0.0",
34
+ "aiobotocore>=2.13.0",
35
+ "asyncpg>=0.29.0",
36
+ "boto3>=1.35.0",
37
+ "ergon-platform-sdk>=0.1.0",
38
+ "httpx>=0.28.0",
39
+ "nylas>=6.0.0",
40
+ "openpyxl>=3.1.5",
41
+ "pika>=1.3.0",
42
+ "requests>=2.32.5",
43
+ ]
44
+ "ergon-platform" = [
45
+ "ergon-platform-sdk>=0.1.0",
46
+ "httpx>=0.28.0",
47
+ ]
48
+ excel = ["openpyxl>=3.1.5"]
41
49
  nylas = ["nylas>=6.0.0"]
42
- ergon_platform = []
50
+ pipefy = [
51
+ "httpx>=0.28.0",
52
+ "requests>=2.32.5",
53
+ ]
54
+ postgres = ["asyncpg>=0.29.0"]
55
+ rabbitmq = [
56
+ "aio-pika>=9.0.0",
57
+ "pika>=1.3.0",
58
+ ]
59
+ sqs = [
60
+ "aiobotocore>=2.13.0",
61
+ "boto3>=1.35.0",
62
+ ]
43
63
 
44
64
  [dependency-groups]
45
65
  dev = [
@@ -10,4 +10,4 @@ __all__ = [
10
10
  "manager",
11
11
  ]
12
12
 
13
- __version__ = "0.1.9"
13
+ __version__ = "0.2.1"
@@ -0,0 +1,203 @@
1
+ from importlib import import_module
2
+ from typing import TYPE_CHECKING, Any
3
+
4
+ from ._lazy import exported_names, load_export
5
+ from .connector import AsyncConnector, Connector, ConnectorConfig
6
+ from .transaction import Transaction
7
+
8
+ if TYPE_CHECKING:
9
+ from .ergon_platform import (
10
+ AsyncErgonPlatformConnector,
11
+ CreateItemInput,
12
+ ErgonPlatformClient,
13
+ ErgonPlatformConnector,
14
+ ErgonPlatformConsumerConfig,
15
+ ErgonPlatformProducerConfig,
16
+ )
17
+ from .excel import ExcelConnector, ExcelFetchConfig, ExcelRow, ExcelService
18
+ from .nylas import (
19
+ AckActionConfig,
20
+ AsyncNylasAuthService,
21
+ AsyncNylasConnector,
22
+ AsyncNylasService,
23
+ AuthUrlConfig,
24
+ CodeExchangeInput,
25
+ GrantAuthResult,
26
+ MessageQueryFilter,
27
+ NylasAuthClient,
28
+ NylasAuthService,
29
+ NylasClient,
30
+ NylasConnector,
31
+ NylasConsumerConfig,
32
+ NylasProducerConfig,
33
+ NylasService,
34
+ SendMessageInput,
35
+ )
36
+ from .postgres import (
37
+ AsyncPostgresConnector,
38
+ AsyncPostgresService,
39
+ PostgresClient,
40
+ PostgresConsumerConfig,
41
+ PostgresProducerConfig,
42
+ )
43
+ from .rabbitmq import (
44
+ AsyncRabbitmqClient,
45
+ AsyncRabbitMQConnector,
46
+ AsyncRabbitmqConsumerConfig,
47
+ AsyncRabbitmqExchangeBinding,
48
+ AsyncRabbitmqProducerConfig,
49
+ AsyncRabbitmqQueueSubscription,
50
+ AsyncRabbitMQService,
51
+ RabbitmqClient,
52
+ RabbitMQConnector,
53
+ RabbitmqConsumerMessage,
54
+ RabbitmqProducerMessage,
55
+ RabbitMQService,
56
+ )
57
+ from .sqs import (
58
+ AsyncSQSConnector,
59
+ AsyncSQSService,
60
+ SQSClient,
61
+ SQSConnector,
62
+ SQSConsumerConfig,
63
+ SQSProducerConfig,
64
+ SQSService,
65
+ )
66
+
67
+ _CONNECTOR_SUBPACKAGES = (
68
+ "ergon_platform",
69
+ "excel",
70
+ "nylas",
71
+ "pipefy",
72
+ "postgres",
73
+ "rabbitmq",
74
+ "sqs",
75
+ )
76
+
77
+ _LAZY_EXPORTS = {
78
+ "AckActionConfig": "nylas",
79
+ "AsyncErgonPlatformConnector": "ergon_platform",
80
+ "AsyncNylasAuthService": "nylas",
81
+ "AsyncNylasConnector": "nylas",
82
+ "AsyncNylasService": "nylas",
83
+ "AsyncPostgresConnector": "postgres",
84
+ "AsyncPostgresService": "postgres",
85
+ "AsyncRabbitMQConnector": "rabbitmq",
86
+ "AsyncRabbitMQService": "rabbitmq",
87
+ "AsyncRabbitmqClient": "rabbitmq",
88
+ "AsyncRabbitmqConsumerConfig": "rabbitmq",
89
+ "AsyncRabbitmqExchangeBinding": "rabbitmq",
90
+ "AsyncRabbitmqProducerConfig": "rabbitmq",
91
+ "AsyncRabbitmqQueueSubscription": "rabbitmq",
92
+ "AsyncSQSConnector": "sqs",
93
+ "AsyncSQSService": "sqs",
94
+ "AuthUrlConfig": "nylas",
95
+ "CodeExchangeInput": "nylas",
96
+ "CreateItemInput": "ergon_platform",
97
+ "ErgonPlatformClient": "ergon_platform",
98
+ "ErgonPlatformConnector": "ergon_platform",
99
+ "ErgonPlatformConsumerConfig": "ergon_platform",
100
+ "ErgonPlatformProducerConfig": "ergon_platform",
101
+ "ExcelConnector": "excel",
102
+ "ExcelFetchConfig": "excel",
103
+ "ExcelRow": "excel",
104
+ "ExcelService": "excel",
105
+ "GrantAuthResult": "nylas",
106
+ "MessageQueryFilter": "nylas",
107
+ "NylasAuthClient": "nylas",
108
+ "NylasAuthService": "nylas",
109
+ "NylasClient": "nylas",
110
+ "NylasConnector": "nylas",
111
+ "NylasConsumerConfig": "nylas",
112
+ "NylasProducerConfig": "nylas",
113
+ "NylasService": "nylas",
114
+ "PostgresClient": "postgres",
115
+ "PostgresConsumerConfig": "postgres",
116
+ "PostgresProducerConfig": "postgres",
117
+ "RabbitMQConnector": "rabbitmq",
118
+ "RabbitMQService": "rabbitmq",
119
+ "RabbitmqClient": "rabbitmq",
120
+ "RabbitmqConsumerMessage": "rabbitmq",
121
+ "RabbitmqProducerMessage": "rabbitmq",
122
+ "SQSClient": "sqs",
123
+ "SQSConnector": "sqs",
124
+ "SQSConsumerConfig": "sqs",
125
+ "SQSProducerConfig": "sqs",
126
+ "SQSService": "sqs",
127
+ "SendMessageInput": "nylas",
128
+ }
129
+
130
+
131
+ def __getattr__(name: str) -> Any:
132
+ if name in _CONNECTOR_SUBPACKAGES:
133
+ module = import_module(f".{name}", __name__)
134
+ globals()[name] = module
135
+ return module
136
+ return load_export(
137
+ name=name,
138
+ package=__name__,
139
+ exports=_LAZY_EXPORTS,
140
+ namespace=globals(),
141
+ )
142
+
143
+
144
+ def __dir__() -> list[str]:
145
+ return sorted(set(exported_names(globals(), _LAZY_EXPORTS)) | set(_CONNECTOR_SUBPACKAGES))
146
+
147
+
148
+ __all__ = [
149
+ "AckActionConfig",
150
+ "AsyncConnector",
151
+ "AsyncErgonPlatformConnector",
152
+ "AsyncNylasAuthService",
153
+ "AsyncNylasConnector",
154
+ "AsyncNylasService",
155
+ "AuthUrlConfig",
156
+ "CodeExchangeInput",
157
+ "GrantAuthResult",
158
+ "AsyncPostgresConnector",
159
+ "AsyncPostgresService",
160
+ "AsyncRabbitMQConnector",
161
+ "AsyncRabbitMQService",
162
+ "AsyncRabbitmqClient",
163
+ "AsyncRabbitmqConsumerConfig",
164
+ "AsyncRabbitmqExchangeBinding",
165
+ "AsyncRabbitmqProducerConfig",
166
+ "AsyncRabbitmqQueueSubscription",
167
+ "AsyncSQSConnector",
168
+ "AsyncSQSService",
169
+ "Connector",
170
+ "ConnectorConfig",
171
+ "CreateItemInput",
172
+ "ErgonPlatformClient",
173
+ "ErgonPlatformConnector",
174
+ "ErgonPlatformConsumerConfig",
175
+ "ErgonPlatformProducerConfig",
176
+ "ExcelConnector",
177
+ "ExcelFetchConfig",
178
+ "ExcelRow",
179
+ "ExcelService",
180
+ "MessageQueryFilter",
181
+ "NylasAuthClient",
182
+ "NylasAuthService",
183
+ "NylasClient",
184
+ "NylasConnector",
185
+ "NylasConsumerConfig",
186
+ "NylasProducerConfig",
187
+ "NylasService",
188
+ "PostgresClient",
189
+ "SendMessageInput",
190
+ "PostgresConsumerConfig",
191
+ "PostgresProducerConfig",
192
+ "RabbitMQConnector",
193
+ "RabbitMQService",
194
+ "RabbitmqClient",
195
+ "RabbitmqConsumerMessage",
196
+ "RabbitmqProducerMessage",
197
+ "SQSClient",
198
+ "SQSConnector",
199
+ "SQSConsumerConfig",
200
+ "SQSProducerConfig",
201
+ "SQSService",
202
+ "Transaction",
203
+ ]
@@ -0,0 +1,51 @@
1
+ """Helpers for loading connector implementations only when requested."""
2
+
3
+ from importlib import import_module
4
+ from typing import Any, Mapping, MutableMapping, Sequence
5
+
6
+
7
+ def load_export(
8
+ *,
9
+ name: str,
10
+ package: str,
11
+ exports: Mapping[str, str],
12
+ namespace: MutableMapping[str, Any],
13
+ ) -> Any:
14
+ """Load and cache one lazily exported attribute."""
15
+ module_name = exports.get(name)
16
+ if module_name is None:
17
+ raise AttributeError(f"module {package!r} has no attribute {name!r}")
18
+
19
+ module = import_module(f".{module_name}", package)
20
+ value = getattr(module, name)
21
+ namespace[name] = value
22
+ return value
23
+
24
+
25
+ def load_optional_export(
26
+ *,
27
+ name: str,
28
+ package: str,
29
+ exports: Mapping[str, str],
30
+ namespace: MutableMapping[str, Any],
31
+ extra: str,
32
+ dependencies: Sequence[str],
33
+ ) -> Any:
34
+ """Load a connector export and explain how to install a missing extra."""
35
+ try:
36
+ return load_export(name=name, package=package, exports=exports, namespace=namespace)
37
+ except ModuleNotFoundError as exc:
38
+ missing_module = exc.name or ""
39
+ if not any(
40
+ missing_module == dependency or missing_module.startswith(f"{dependency}.") for dependency in dependencies
41
+ ):
42
+ raise
43
+ raise ImportError(
44
+ f"The {extra!r} connector dependencies are not installed. "
45
+ f"Install them with: pip install 'ergon-framework-python[{extra}]'"
46
+ ) from exc
47
+
48
+
49
+ def exported_names(namespace: Mapping[str, Any], exports: Mapping[str, str]) -> list[str]:
50
+ """Return module names including lazy exports for interactive discovery."""
51
+ return sorted(set(namespace) | set(exports))
@@ -0,0 +1,43 @@
1
+ from typing import TYPE_CHECKING, Any
2
+
3
+ from .._lazy import exported_names, load_optional_export
4
+ from .models import (
5
+ CreateItemInput,
6
+ ErgonPlatformClient,
7
+ ErgonPlatformConsumerConfig,
8
+ ErgonPlatformProducerConfig,
9
+ )
10
+
11
+ if TYPE_CHECKING:
12
+ from .async_connector import AsyncErgonPlatformConnector
13
+ from .connector import ErgonPlatformConnector
14
+
15
+ _LAZY_EXPORTS = {
16
+ "AsyncErgonPlatformConnector": "async_connector",
17
+ "ErgonPlatformConnector": "connector",
18
+ }
19
+
20
+
21
+ def __getattr__(name: str) -> Any:
22
+ return load_optional_export(
23
+ name=name,
24
+ package=__name__,
25
+ exports=_LAZY_EXPORTS,
26
+ namespace=globals(),
27
+ extra="ergon-platform",
28
+ dependencies=("ergon_platform", "httpx"),
29
+ )
30
+
31
+
32
+ def __dir__() -> list[str]:
33
+ return exported_names(globals(), _LAZY_EXPORTS)
34
+
35
+
36
+ __all__ = [
37
+ "AsyncErgonPlatformConnector",
38
+ "CreateItemInput",
39
+ "ErgonPlatformClient",
40
+ "ErgonPlatformConnector",
41
+ "ErgonPlatformConsumerConfig",
42
+ "ErgonPlatformProducerConfig",
43
+ ]
@@ -1,6 +1,9 @@
1
1
  from .models import ErgonPlatformClient
2
2
 
3
- _ERGON_PLATFORM_IMPORT_ERROR = "Install the ergon-platform-sdk package in the same environment"
3
+ _ERGON_PLATFORM_IMPORT_ERROR = (
4
+ "The 'ergon-platform' connector dependencies are not installed. "
5
+ "Install them with: pip install 'ergon-framework-python[ergon-platform]'"
6
+ )
4
7
 
5
8
 
6
9
  def _get_ergon_client():
@@ -0,0 +1,44 @@
1
+ """
2
+ Excel connector for ergon-framework.
3
+ Provides transaction-based access to Excel files with support for:
4
+ - Batch mode (multiple rows per transaction for high-throughput processing)
5
+ - Normal mode (one row per transaction)
6
+ - Sharding for parallel processing
7
+ """
8
+
9
+ from typing import TYPE_CHECKING, Any
10
+
11
+ from .._lazy import exported_names, load_optional_export
12
+ from .models import ExcelFetchConfig, ExcelRow
13
+
14
+ if TYPE_CHECKING:
15
+ from .connector import ExcelConnector
16
+ from .service import ExcelService
17
+
18
+ _LAZY_EXPORTS = {
19
+ "ExcelConnector": "connector",
20
+ "ExcelService": "service",
21
+ }
22
+
23
+
24
+ def __getattr__(name: str) -> Any:
25
+ return load_optional_export(
26
+ name=name,
27
+ package=__name__,
28
+ exports=_LAZY_EXPORTS,
29
+ namespace=globals(),
30
+ extra="excel",
31
+ dependencies=("openpyxl",),
32
+ )
33
+
34
+
35
+ def __dir__() -> list[str]:
36
+ return exported_names(globals(), _LAZY_EXPORTS)
37
+
38
+
39
+ __all__ = [
40
+ "ExcelConnector",
41
+ "ExcelService",
42
+ "ExcelFetchConfig",
43
+ "ExcelRow",
44
+ ]
@@ -0,0 +1,75 @@
1
+ from typing import TYPE_CHECKING, Any
2
+
3
+ from .._lazy import exported_names, load_optional_export
4
+ from .models import (
5
+ AckActionConfig,
6
+ AttachmentInput,
7
+ AuthUrlConfig,
8
+ ClientSideFilter,
9
+ CodeExchangeInput,
10
+ EmailAddress,
11
+ GrantAuthResult,
12
+ MessageFields,
13
+ MessageQueryFilter,
14
+ NylasAuthClient,
15
+ NylasClient,
16
+ NylasConsumerConfig,
17
+ NylasProducerConfig,
18
+ SendMessageInput,
19
+ )
20
+
21
+ if TYPE_CHECKING:
22
+ from .async_auth_service import AsyncNylasAuthService
23
+ from .async_connector import AsyncNylasConnector
24
+ from .async_service import AsyncNylasService
25
+ from .auth_service import NylasAuthService
26
+ from .connector import NylasConnector
27
+ from .service import NylasService
28
+
29
+ _LAZY_EXPORTS = {
30
+ "AsyncNylasAuthService": "async_auth_service",
31
+ "AsyncNylasConnector": "async_connector",
32
+ "AsyncNylasService": "async_service",
33
+ "NylasAuthService": "auth_service",
34
+ "NylasConnector": "connector",
35
+ "NylasService": "service",
36
+ }
37
+
38
+
39
+ def __getattr__(name: str) -> Any:
40
+ return load_optional_export(
41
+ name=name,
42
+ package=__name__,
43
+ exports=_LAZY_EXPORTS,
44
+ namespace=globals(),
45
+ extra="nylas",
46
+ dependencies=("nylas",),
47
+ )
48
+
49
+
50
+ def __dir__() -> list[str]:
51
+ return exported_names(globals(), _LAZY_EXPORTS)
52
+
53
+
54
+ __all__ = [
55
+ "AckActionConfig",
56
+ "AsyncNylasAuthService",
57
+ "AsyncNylasConnector",
58
+ "AsyncNylasService",
59
+ "AttachmentInput",
60
+ "AuthUrlConfig",
61
+ "ClientSideFilter",
62
+ "CodeExchangeInput",
63
+ "EmailAddress",
64
+ "GrantAuthResult",
65
+ "MessageFields",
66
+ "MessageQueryFilter",
67
+ "NylasAuthClient",
68
+ "NylasAuthService",
69
+ "NylasClient",
70
+ "NylasConnector",
71
+ "NylasConsumerConfig",
72
+ "NylasProducerConfig",
73
+ "NylasService",
74
+ "SendMessageInput",
75
+ ]
@@ -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 []