deltafi 2.28.1__py3-none-any.whl → 2.29.1rc20250818210829__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.

Potentially problematic release.


This version of deltafi might be problematic. Click here for more details.

deltafi/plugin.py CHANGED
@@ -392,6 +392,7 @@ class Plugin(object):
392
392
  'start': start_time,
393
393
  'stop': stop_time,
394
394
  'type': result.result_type,
395
+ 'messages': [message.json() for message in result.messages],
395
396
  'metrics': [metric.json() for metric in result.metrics]
396
397
  }
397
398
  if result.result_key is not None:
deltafi/result.py CHANGED
@@ -19,10 +19,10 @@
19
19
  import abc
20
20
  import uuid
21
21
  from enum import Enum
22
- from typing import NamedTuple
23
22
 
24
23
  from deltafi.domain import Content, Context
25
24
  from deltafi.metric import Metric
25
+ from deltafi.resultmessage import LogMessage
26
26
 
27
27
 
28
28
  class Result:
@@ -31,6 +31,7 @@ class Result:
31
31
  def __init__(self, result_key, result_type, context):
32
32
  self.result_key = result_key
33
33
  self.result_type = result_type
34
+ self.messages = []
34
35
  self.metrics = []
35
36
  self.context = context
36
37
 
@@ -42,6 +43,18 @@ class Result:
42
43
  self.metrics.append(metric)
43
44
  return self
44
45
 
46
+ def log_info(self, message: str):
47
+ self.messages.append(LogMessage.info(self.context.action_name, message))
48
+ return self
49
+
50
+ def log_warning(self, message: str):
51
+ self.messages.append(LogMessage.warning(self.context.action_name, message))
52
+ return self
53
+
54
+ def log_error(self, message: str):
55
+ self.messages.append(LogMessage.error(self.context.action_name, message))
56
+ return self
57
+
45
58
 
46
59
  class EgressResult(Result):
47
60
  def __init__(self, context: Context):
@@ -63,6 +76,7 @@ class ErrorResult(Result):
63
76
  return self
64
77
 
65
78
  def response(self):
79
+ self.log_error(self.error_cause + '\n' + self.error_context)
66
80
  return {
67
81
  'cause': self.error_cause,
68
82
  'context': self.error_context,
@@ -145,8 +159,8 @@ class IngressResultItem:
145
159
  return segment_names
146
160
 
147
161
  def annotate(self, key: str, value: str):
148
- self.annotations[key] = value
149
- return self
162
+ self.annotations[key] = value
163
+ return self
150
164
 
151
165
  def response(self):
152
166
  return {
@@ -0,0 +1,56 @@
1
+ #
2
+ # DeltaFi - Data transformation and enrichment platform
3
+ #
4
+ # Copyright 2021-2025 DeltaFi Contributors <deltafi@deltafi.org>
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ import time
20
+ from enum import Enum
21
+ from typing import NamedTuple
22
+
23
+
24
+ class LogSeverity(Enum):
25
+ TRACE = "TRACE"
26
+ INFO = "INFO"
27
+ WARNING = "WARNING"
28
+ ERROR = "ERROR"
29
+ USER = "USER"
30
+
31
+
32
+ class LogMessage(NamedTuple):
33
+ severity: LogSeverity
34
+ created: int
35
+ source: str
36
+ message: str
37
+
38
+ @classmethod
39
+ def info(cls, source: str, message: str):
40
+ return LogMessage(severity=LogSeverity.INFO, created=time.time(), source=source, message=message)
41
+
42
+ @classmethod
43
+ def warning(cls, source: str, message: str):
44
+ return LogMessage(severity=LogSeverity.WARNING, created=time.time(), source=source,
45
+ message=message)
46
+
47
+ @classmethod
48
+ def error(cls, source: str, message: str):
49
+ return LogMessage(severity=LogSeverity.ERROR, created=time.time(), source=source,
50
+ message=message)
51
+
52
+ def json(self):
53
+ return {'severity': self.severity.value,
54
+ 'created': self.created,
55
+ 'source': self.source,
56
+ 'message': self.message}
@@ -50,5 +50,5 @@ class EgressActionTest(ActionTest):
50
50
  self.assert_egress_result(test_case, result)
51
51
 
52
52
  def assert_egress_result(self, test_case: EgressTestCase, result: EgressResult):
53
- # Check metrics
54
53
  self.compare_metrics(test_case.expected_metrics, result.metrics)
54
+ self.compare_log_messages(test_case.expected_messages, result.messages)
@@ -16,6 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
+ import re
19
20
  import uuid
20
21
  from abc import ABC
21
22
  from importlib.resources import files
@@ -25,7 +26,9 @@ from deltafi.domain import DeltaFileMessage, Event, Content, Context
25
26
  from deltafi.logger import get_logger
26
27
  from deltafi.metric import Metric
27
28
  from deltafi.result import ErrorResult, FilterResult
29
+ from deltafi.resultmessage import LogMessage
28
30
  from deltafi.storage import Segment
31
+
29
32
  from .assertions import *
30
33
  from .compare_helpers import GenericCompareHelper, CompareHelper
31
34
  from .constants import *
@@ -170,10 +173,14 @@ class TestCaseBase(ABC):
170
173
  self.err_or_filt_annotations = None
171
174
  self.join_meta = data["join_meta"] if "join_meta" in data else None
172
175
  self.expected_metrics = []
176
+ self.expected_messages = []
173
177
 
174
178
  def add_metric(self, metric: Metric):
175
179
  self.expected_metrics.append(metric)
176
180
 
181
+ def add_message(self, message: LogMessage):
182
+ self.expected_messages.append(message)
183
+
177
184
  def expect_error_result(self, cause: str, context: str, annotations: Dict = None):
178
185
  """
179
186
  A Sets the expected output of the action to an Error Result
@@ -360,6 +367,24 @@ class ActionTest(ABC):
360
367
  for index, expected in enumerate(expected_metrics):
361
368
  self.compare_one_metric(expected, results[index])
362
369
 
370
+ @staticmethod
371
+ def compare_one_message(expected: LogMessage, result: LogMessage):
372
+ assert_equal_short(expected.severity, result.severity, "message severity does not match")
373
+ # Look for regex characters:
374
+ if '*' in expected.message or '{' in expected.message or '^' in expected.message \
375
+ or '$' in expected.message:
376
+ match = re.search(expected.message, result.message)
377
+ assert match is not None, "message does not match regex"
378
+
379
+ else:
380
+ assert_equal_short(expected.message, result.message, "message value does not match")
381
+
382
+ def compare_log_messages(self, expected_messages: List[LogMessage], results: List[LogMessage]):
383
+ if len(expected_messages) > 0:
384
+ assert_equal_len_with_label(expected_messages, results, "invalid messages count")
385
+ for index, expected in enumerate(expected_messages):
386
+ self.compare_one_message(expected, results[index])
387
+
363
388
  def has_saved_content__size(self, count: int):
364
389
  assert_equal_with_label(
365
390
  count, len(self.context.saved_content), "savedContent")
@@ -19,6 +19,7 @@
19
19
  from typing import List
20
20
 
21
21
  from deltafi.result import IngressResult, IngressResultItem, IngressStatusEnum
22
+
22
23
  from .assertions import *
23
24
  from .framework import TestCaseBase, ActionTest, IOContent
24
25
 
@@ -43,7 +44,8 @@ class TimedIngressTestCase(TestCaseBase):
43
44
  self.status = status
44
45
  self.status_message = status_message
45
46
 
46
- def add_ingress_result_item(self, content: List[IOContent], metadata: Dict, name: str = None, annotations: Dict = None):
47
+ def add_ingress_result_item(self, content: List[IOContent], metadata: Dict, name: str = None,
48
+ annotations: Dict = None):
47
49
  if annotations is None:
48
50
  annotations = {}
49
51
  self.results.append(
@@ -80,6 +82,7 @@ class TimedIngressActionTest(ActionTest):
80
82
  assert_equal_short(test_case.execute_immediate, result.execute_immediate, "invalid execute_immediate")
81
83
  assert_equal_short(test_case.status, result.status, "invalid status")
82
84
  assert_equal_with_label(test_case.status_message, result.status_message, "invalid status_message")
85
+ self.compare_log_messages(test_case.expected_messages, result.messages)
83
86
 
84
87
  assert_equal_len_with_label(test_case.results, result.ingress_result_items, "item count mismatch")
85
88
  for index, ingress_item in enumerate(result.ingress_result_items):
@@ -19,6 +19,7 @@
19
19
  from typing import List
20
20
 
21
21
  from deltafi.result import TransformResult, TransformResults
22
+
22
23
  from .assertions import *
23
24
  from .framework import TestCaseBase, ActionTest, IOContent
24
25
 
@@ -81,8 +82,8 @@ class TransformActionTest(ActionTest):
81
82
  assert_equal_with_label(expected["name"], child_result.delta_file_name, f"name[{index}]")
82
83
 
83
84
  def assert_transform_result(self, test_case: TransformTestCase, result: TransformResult):
84
- # Check metrics
85
85
  self.compare_metrics(test_case.expected_metrics, result.metrics)
86
+ self.compare_log_messages(test_case.expected_messages, result.messages)
86
87
  self.compare_one_transform_result(test_case, result, 0)
87
88
 
88
89
  def compare_one_transform_result(self, test_case: TransformTestCase, result: TransformResult, index: int):
@@ -0,0 +1,82 @@
1
+ Metadata-Version: 2.4
2
+ Name: deltafi
3
+ Version: 2.29.1rc20250818210829
4
+ Summary: SDK for DeltaFi plugins and actions
5
+ Project-URL: Source Code, https://gitlab.com/deltafi/deltafi
6
+ Project-URL: Documentation, https://docs.deltafi.org/#/
7
+ Project-URL: Bug Reports, https://chat.deltafi.org/deltafi/channels/bug-reports
8
+ Author-email: DeltaFi <deltafi@systolic.com>
9
+ License: Apache License, Version 2.0
10
+ Keywords: deltafi
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development
18
+ Requires-Python: >=3.13
19
+ Requires-Dist: deepdiff==6.7.1
20
+ Requires-Dist: json-logging==1.5.1
21
+ Requires-Dist: minio==7.2.15
22
+ Requires-Dist: pydantic==2.11.7
23
+ Requires-Dist: pyyaml==6.0.2
24
+ Requires-Dist: redis==6.2.0
25
+ Requires-Dist: requests==2.32.4
26
+ Requires-Dist: urllib3==2.5.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
29
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
30
+ Provides-Extra: test
31
+ Requires-Dist: mockito==1.5.4; extra == 'test'
32
+ Requires-Dist: pytest-mock==3.14.1; extra == 'test'
33
+ Requires-Dist: pytest==8.4.1; extra == 'test'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # DeltaFi Action Kit
37
+
38
+ This project provides a Python implementation of the DeltaFi Action Kit. The DeltaFi Action Kit is a setup of modules which simplify the creation of a DeltaFi Plugin.
39
+
40
+ ## Development Setup
41
+
42
+ This project uses [uv](https://github.com/astral-sh/uv) for dependency management and building. uv is a fast Python package installer and resolver.
43
+
44
+ ### Prerequisites
45
+
46
+ - Python 3.13 or higher
47
+ - uv (will be installed automatically via the build process)
48
+
49
+ ### Building and Testing
50
+
51
+ The project uses Gradle to orchestrate the build process with uv:
52
+
53
+ ```bash
54
+ # Build the project
55
+ ./gradlew assemble
56
+
57
+ # Run tests
58
+ ./gradlew test
59
+
60
+ # Clean build artifacts
61
+ ./gradlew clean
62
+ ```
63
+
64
+ ### Manual Development
65
+
66
+ For manual development without Gradle:
67
+
68
+ ```bash
69
+ cd src
70
+
71
+ # Install uv if not already installed
72
+ brew install uv || pip install uv
73
+
74
+ # Install dependencies
75
+ uv pip install -e .[test]
76
+
77
+ # Run tests
78
+ uv run pytest
79
+
80
+ # Build package
81
+ uv build
82
+ ```
@@ -8,17 +8,18 @@ deltafi/genericmodel.py,sha256=0qgii2o-fzHS6lM1C5X7_WTTSYsiZAM0i7RTfw0nw4U,1152
8
8
  deltafi/input.py,sha256=CZ02GsObhu6CpdBKzNE5TJ_PSihQF3cr4XKPqouqRUU,1780
9
9
  deltafi/logger.py,sha256=Lms9wmjyZWe9-SCKj4raNmGC9Cyn3BrfiniPXeM9VDY,2140
10
10
  deltafi/metric.py,sha256=5Q40bLpNXk8mwu1wnN5L8GX22-iZxYEFBGt3zSNmYxI,972
11
- deltafi/plugin.py,sha256=6EQx65kmv94_7SPayFA5VoPrrEsP1CweqrPMfEDTmoU,19088
12
- deltafi/result.py,sha256=j_3icJ74xIQo9KQV738XiqaFOYirjuIgFEtld4pBvXk,9555
11
+ deltafi/plugin.py,sha256=AEWw9Yf6KmgKSZzBU0eRwQhGSVCHklkL7DpUAPQXSeQ,19161
12
+ deltafi/result.py,sha256=pbVSq5lQ0HdOtiQDwkvWMGg3nUjI63DTv3OwA7lnhIA,10070
13
+ deltafi/resultmessage.py,sha256=jYCvKKlFAWuA5YfOE30w3TH294M4EuTEowROc6LkZzE,1767
13
14
  deltafi/storage.py,sha256=zgBkaDTiT4BLEE1lAYjq4mqS4zqZKzuoVmG1CNbkD20,2979
14
15
  deltafi/test_kit/__init__.py,sha256=FHwsfe4TgGeVLINN6940urXAzxGvl_Hof0gmOB32N7Y,709
15
16
  deltafi/test_kit/assertions.py,sha256=itKLaI22PoiiDLHNrvRAAohcrKsbKuW5-ba0sg7J780,1594
16
17
  deltafi/test_kit/compare_helpers.py,sha256=1p0HbjR76K2_QZ4ODfw1V_zuR7rcKqRSoSA351L-qWo,12957
17
18
  deltafi/test_kit/constants.py,sha256=7Z8m3a-8_t2wYdCMNvxfShQo2bvoOV9PjVMJX4y5yZY,833
18
- deltafi/test_kit/egress.py,sha256=MXEsYsgiG1G-1zCuwV23RCn7w5bPObP1J0_7nVN03MU,1899
19
- deltafi/test_kit/framework.py,sha256=pU8tLsMNWUhVtIhLusbQL3uPT4y8xsKWdzzXuxmxRrU,15432
20
- deltafi/test_kit/timed_ingress.py,sha256=ogk6AzbPZInLOPMYy3MhjEXpITPn9-Ha6YSILGBdpro,4177
21
- deltafi/test_kit/transform.py,sha256=7KOsNY9OSDiyTFXIx0knZeweXIA421vHS6PAxQAcOc0,4122
22
- deltafi-2.28.1.dist-info/METADATA,sha256=BQsaqWWKdbtRQeD5DY0Z4cPTpXdKwiv7j-Vqz2K6wd8,1519
23
- deltafi-2.28.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
24
- deltafi-2.28.1.dist-info/RECORD,,
19
+ deltafi/test_kit/egress.py,sha256=DhWfVUSFx_V94rtLpohEKvlXlSfoY8P3Yjd4lj2smfQ,1955
20
+ deltafi/test_kit/framework.py,sha256=9m7opcSVMmQHA1x0E0DAtSWKHZU5y-0A5sPng_im81A,16591
21
+ deltafi/test_kit/timed_ingress.py,sha256=qfZIpbl4ESKRJNO9UsO-jvB4iVI7RZWGGYbPrMhfROs,4290
22
+ deltafi/test_kit/transform.py,sha256=CLtcP3GputylMrO73_P4Tbu33Y4Auelp2318gTnLxhU,4179
23
+ deltafi-2.29.1rc20250818210829.dist-info/METADATA,sha256=-58dtKXrpOhjFtp4eHHEltK2dH1sGRNb2oPq-CJ8sPQ,2270
24
+ deltafi-2.29.1rc20250818210829.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
+ deltafi-2.29.1rc20250818210829.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.3
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,38 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: deltafi
3
- Version: 2.28.1
4
- Summary: SDK for DeltaFi plugins and actions
5
- License: Apache License, Version 2.0
6
- Keywords: deltafi
7
- Author: DeltaFi
8
- Author-email: deltafi@systolic.com
9
- Requires-Python: >=3.9,<4.0
10
- Classifier: Development Status :: 4 - Beta
11
- Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: Apache Software License
13
- Classifier: License :: Other/Proprietary License
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
- Classifier: Programming Language :: Python :: 3.13
21
- Classifier: Topic :: Software Development
22
- Requires-Dist: PyYAML (==6.0.2)
23
- Requires-Dist: deepdiff (==6.7.1)
24
- Requires-Dist: json-logging (==1.5.1)
25
- Requires-Dist: minio (==7.2.15)
26
- Requires-Dist: pydantic (==2.11.7)
27
- Requires-Dist: redis (==6.2.0)
28
- Requires-Dist: requests (==2.32.4)
29
- Requires-Dist: urllib3 (==2.5.0)
30
- Project-URL: Bug Reports, https://chat.deltafi.org/deltafi/channels/bug-reports
31
- Project-URL: Documentation, https://docs.deltafi.org/#/
32
- Project-URL: Source Code, https://gitlab.com/deltafi/deltafi
33
- Description-Content-Type: text/markdown
34
-
35
- # DeltaFi Action Kit
36
-
37
- This project provides a Python implementation of the DeltaFi Action Kit. The DeltaFi Action Kit is a setup of modules which simplify the creation of a DeltaFi Plugin.
38
-