deltafi 2.0rc1720728217472__py3-none-any.whl → 2.0rc1722532930396__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.
@@ -37,15 +37,20 @@ class IOContent:
37
37
  The IOContent class holds the details for loading input or output
38
38
  content into the test framework.
39
39
  Attributes:
40
- file_name (str): The name of file in test/data.
41
- content_name (str): The name of the content.
42
- content_type (str): The media type of the content
43
- offset (int): Offset to use in Segment
44
- content_bytes (str): Bypass file read, and uses these bytes for content
40
+ file_name (str) : The name of file in test/data.
41
+ content_name (str) : The name of the content.
42
+ content_type (str) : The media type of the content
43
+ offset (int) : Offset to use in Segment
44
+ content_bytes (str): Optional. If set to a String of length greater than zero, indicates to consumers of this
45
+ IOContent that they should bypass file read and use these bytes for content.
46
+ no_content (bool) : Optional. If 'True', then consumers should not attempt to interpret content but should
47
+ apply other aspects of this IOContent. When 'True', 'content_bytes' should be ignored and
48
+ loaded content, if any, should be interpreted as empty String or otherwise as documented by
49
+ the consumer.
45
50
  """
46
51
 
47
52
  def __init__(self, file_name: str, content_name: str = None, content_type: str = None, offset: int = 0,
48
- content_bytes: str = ""):
53
+ content_bytes: str = "", no_content: bool = False):
49
54
  self.file_name = file_name
50
55
  if content_name is None:
51
56
  self.content_name = file_name
@@ -56,7 +61,11 @@ class IOContent:
56
61
  else:
57
62
  self.content_type = content_type
58
63
  self.offset = offset
59
- self.content_bytes = content_bytes
64
+ self.no_content = no_content
65
+ if no_content:
66
+ self.content_bytes = None
67
+ else:
68
+ self.content_bytes = content_bytes
60
69
  self.segment_uuid = uuid.uuid4()
61
70
 
62
71
  @classmethod
@@ -79,7 +88,10 @@ class LoadedContent:
79
88
  if data is not None:
80
89
  self.data = data
81
90
  else:
82
- self.data = ioc.content_bytes
91
+ if ioc.no_content:
92
+ self.data = ""
93
+ else:
94
+ self.data = ioc.content_bytes
83
95
  self.segment = Segment.from_dict(
84
96
  {"uuid": str(ioc.segment_uuid), "offset": self.offset, "size": len(self.data), "did": did})
85
97
 
@@ -103,6 +115,10 @@ class InternalContentService:
103
115
  seg_id = segments[0].uuid
104
116
  return self.loaded_content[seg_id].data
105
117
 
118
+ def get_bytes(self, segments: List[Segment]):
119
+ seg_id = segments[0].uuid
120
+ return self.loaded_content[seg_id].data.encode('utf-8')
121
+
106
122
  def get_output(self, seg_id: str):
107
123
  if seg_id in self.outputs:
108
124
  return self.outputs[seg_id]
@@ -123,8 +139,8 @@ class TestCaseBase(ABC):
123
139
  - inputs: (optional) List[IOContent]: input content to action
124
140
  - parameters: (optional) Dict: map of action input parameters
125
141
  - in_meta: (optional) Dict: map of metadata as input to action
126
- - in_domains: (optional) List[Domain]: list of domains as input to action
127
- - in_enrichments: (optional) List[Domain]: list of enrichments as input to action
142
+ - join_meta: (optional): List[Dict]: When a List is provided, this enables the JOIN portion of an action.
143
+ When using JOIN, join_meta must match the size of inputs, though the Dict can be empty
128
144
  - did: (optional): str: overrides random DID
129
145
  """
130
146
  if "action" in data:
@@ -144,16 +160,14 @@ class TestCaseBase(ABC):
144
160
 
145
161
  self.inputs = data["inputs"] if "inputs" in data else []
146
162
  self.file_name = data["file_name"] if "file_name" in data else "filename"
147
- self.outputs = data["outputs"] if "outputs" in data else []
148
163
  self.parameters = data["parameters"] if "parameters" in data else {}
149
164
  self.in_meta = data["in_meta"] if "in_meta" in data else {}
150
- self.in_domains = data["in_domains"] if "in_domains" in data else []
151
- self.in_enrichments = data["in_enrichments"] if "in_enrichments" in data else []
152
165
  self.use_did = data["did"] if "did" in data else None
153
166
  self.expected_result_type = None
154
167
  self.err_or_filt_cause = None
155
168
  self.err_or_filt_context = None
156
169
  self.err_or_filt_annotations = None
170
+ self.join_meta = data["join_meta"] if "join_meta" in data else None
157
171
  self.expected_metrics = []
158
172
 
159
173
  def add_metric(self, metric: Metric):
@@ -164,7 +178,7 @@ class TestCaseBase(ABC):
164
178
  A Sets the expected output of the action to an Error Result
165
179
  :param cause: the expected error cause
166
180
  :param context: the expected error context
167
- :param annotations (Optional): Dict: the expected annotations
181
+ :param annotations: Dict: (Optional) the expected annotations
168
182
  """
169
183
  self.expected_result_type = ErrorResult
170
184
  self.err_or_filt_cause = cause
@@ -175,8 +189,8 @@ class TestCaseBase(ABC):
175
189
  """
176
190
  A Sets the expected output of the action to a Filter Result
177
191
  :param cause: the expected filter cause (message)
178
- :param context (Optional): the expected filter context
179
- :param annotations (Optional): Dict: the expected annotations
192
+ :param context: (Optional) the expected filter context
193
+ :param annotations: Dict: (Optional) the expected annotations
180
194
  """
181
195
  self.expected_result_type = FilterResult
182
196
  self.err_or_filt_cause = cause
@@ -193,7 +207,6 @@ class ActionTest(ABC):
193
207
  """
194
208
  self.content_service = InternalContentService()
195
209
  self.did = ""
196
- self.expected_outputs = []
197
210
  self.loaded_inputs = []
198
211
  self.package_name = package_name
199
212
  self.res_path = ""
@@ -204,7 +217,6 @@ class ActionTest(ABC):
204
217
  self.did = str(uuid.uuid4())
205
218
  else:
206
219
  self.did = did
207
- self.expected_outputs = []
208
220
  self.loaded_inputs = []
209
221
  self.res_path = ""
210
222
 
@@ -220,19 +232,12 @@ class ActionTest(ABC):
220
232
 
221
233
  # Load inputs
222
234
  for input_ioc in test_case.inputs:
223
- if len(input_ioc.content_bytes) == 0:
235
+ if not input_ioc.no_content and len(input_ioc.content_bytes) == 0:
224
236
  self.loaded_inputs.append(LoadedContent(self.did, input_ioc, self.load_file(input_ioc)))
225
237
  else:
226
238
  self.loaded_inputs.append(LoadedContent(self.did, input_ioc, None))
227
239
 
228
- # Load expected outputs
229
- for output_ioc in test_case.outputs:
230
- if len(output_ioc.content_bytes) == 0:
231
- self.expected_outputs.append(LoadedContent(self.did, output_ioc, self.load_file(output_ioc)))
232
- else:
233
- self.expected_outputs.append(LoadedContent(self.did, output_ioc, None))
234
-
235
- def make_content_list(self, test_case: TestCaseBase):
240
+ def make_content_list(self):
236
241
  content_list = []
237
242
  for loaded_input in self.loaded_inputs:
238
243
  c = Content(name=loaded_input.name, segments=[loaded_input.segment], media_type=loaded_input.content_type,
@@ -242,34 +247,42 @@ class ActionTest(ABC):
242
247
 
243
248
  return content_list
244
249
 
245
- def make_df_msg(self, test_case: TestCaseBase):
246
- content_list = self.make_content_list(test_case)
250
+ def make_df_msgs(self, test_case: TestCaseBase):
251
+ content_list = self.make_content_list()
247
252
  self.content_service.load(self.loaded_inputs)
248
253
 
249
- return DeltaFileMessage(
250
- metadata=test_case.in_meta,
251
- content_list=content_list,
252
- domains=test_case.in_domains,
253
- enrichments=test_case.in_enrichments)
254
+ delta_file_messages = []
255
+
256
+ if test_case.join_meta is None:
257
+ delta_file_messages.append(DeltaFileMessage(metadata=test_case.in_meta, content_list=content_list))
258
+ else:
259
+ for index, content in enumerate(content_list):
260
+ delta_file_messages.append(DeltaFileMessage(
261
+ metadata=test_case.join_meta[index],
262
+ content_list=[content]))
263
+
264
+ return delta_file_messages
254
265
 
255
266
  def make_context(self, test_case: TestCaseBase):
256
267
  action_name = INGRESS_FLOW + "." + test_case.action.__class__.__name__
268
+ join = {} if test_case.join_meta else None
257
269
  return Context(
258
270
  did=self.did,
259
- action_flow=INGRESS_FLOW,
271
+ delta_file_name=test_case.file_name,
272
+ data_source="DATASRC",
273
+ flow_name=INGRESS_FLOW,
274
+ flow_id="FLOWID",
260
275
  action_name=action_name,
261
- source_filename=test_case.file_name,
262
- ingress_flow=INGRESS_FLOW,
263
- egress_flow=EGRESS_FLOW,
264
- system=SYSTEM,
276
+ action_id="ACTIONID",
277
+ action_version="1.0",
265
278
  hostname=HOSTNAME,
279
+ system_name=SYSTEM,
266
280
  content_service=self.content_service,
267
- collect=None,
268
- collected_dids=None,
281
+ join=join,
269
282
  logger=get_logger())
270
283
 
271
284
  def make_event(self, test_case: TestCaseBase):
272
- return Event(delta_file_messages=[self.make_df_msg(test_case)], context=self.make_context(test_case),
285
+ return Event(delta_file_messages=self.make_df_msgs(test_case), context=self.make_context(test_case),
273
286
  params=test_case.parameters, queue_name="", return_address="")
274
287
 
275
288
  def call_action(self, test_case: TestCaseBase):
@@ -311,37 +324,27 @@ class ActionTest(ABC):
311
324
  else:
312
325
  raise ValueError(f"unknown type: {test_case.expected_result_type}")
313
326
 
314
- def compare_content_details(self, expected: LoadedContent, actual: Content):
327
+ @staticmethod
328
+ def compare_content_details(expected: LoadedContent, actual: Content):
315
329
  assert_equal(expected.content_type, actual.media_type)
316
330
  assert_equal(expected.name, actual.name)
317
331
 
318
- def compare_one_content(self, comparitor: CompareHelper, expected: LoadedContent, actual, index):
332
+ def compare_one_content(self, comparator: CompareHelper, expected: LoadedContent, actual, index):
319
333
  self.compare_content_details(expected, actual)
320
334
  seg_id = actual.segments[0].uuid
321
- comparitor.compare(expected.data, self.content_service.get_output(seg_id), f"Content[{index}]")
322
-
323
- def compare_all_output(self, comparitor: CompareHelper, content: List):
324
- assert_equal_len(self.expected_outputs, content)
325
- for index, expected in enumerate(self.expected_outputs):
326
- self.compare_one_content(comparitor, expected, content[index], index)
327
-
328
- def compare_domains(self, comparitor: CompareHelper, expected_items: List[Dict], results: List[Dict]):
329
- assert_equal_len(expected_items, results)
330
- for index, expected in enumerate(expected_items):
331
- actual = results[index]
332
- assert_equal(expected['name'], actual['name'])
333
- assert_equal(expected['mediaType'], actual['mediaType'])
334
-
335
- expected_value = expected['value']
336
- if type(expected_value) == str:
337
- comparitor.compare(expected_value, actual['value'], f"Domain[{index}]")
338
- elif type(expected_value) == IOContent:
339
- expected_data = self.load_file(expected_value)
340
- comparitor.compare(expected_data, actual['value'], f"Domain[{index}]")
335
+ comparator.compare(expected.data, self.content_service.get_output(seg_id), f"Content[{index}]")
336
+
337
+ def compare_content_list(self, comparator: CompareHelper, expected_outputs: List[IOContent], content: List):
338
+ assert_equal_len(expected_outputs, content)
339
+ for index, expected_ioc in enumerate(expected_outputs):
340
+ if not expected_ioc.no_content and len(expected_ioc.content_bytes) == 0:
341
+ expected = LoadedContent(self.did, expected_ioc, self.load_file(expected_ioc))
341
342
  else:
342
- raise ValueError(f"unknown expected_value type: {type(expected_value)}")
343
+ expected = LoadedContent(self.did, expected_ioc, None)
344
+ self.compare_one_content(comparator, expected, content[index], index)
343
345
 
344
- def compare_one_metric(self, expected: Metric, result: Metric):
346
+ @staticmethod
347
+ def compare_one_metric(expected: Metric, result: Metric):
345
348
  assert expected.name == result.name
346
349
  assert_equal_with_label(expected.value, result.value, expected.name)
347
350
  assert_keys_and_values(expected.tags, result.tags)
@@ -18,24 +18,34 @@
18
18
 
19
19
  from typing import List
20
20
 
21
- from deltafi.result import TransformResult
21
+ from deltafi.result import TransformResult, TransformResults
22
22
 
23
23
  from .assertions import *
24
- from .framework import TestCaseBase, ActionTest
24
+ from .framework import TestCaseBase, ActionTest, IOContent
25
25
 
26
26
 
27
27
  class TransformTestCase(TestCaseBase):
28
28
  def __init__(self, fields: Dict):
29
29
  super().__init__(fields)
30
- self.metadata = {}
31
- self.delete_metadata_keys = []
32
- self.annotations = {}
30
+ self.results = []
33
31
 
34
- def expect_transform_result(self, metadata: Dict, delete_metadata_keys: List[str], annotations: Dict):
32
+ def expect_transform_result(self):
35
33
  self.expected_result_type = TransformResult
36
- self.metadata = metadata
37
- self.delete_metadata_keys = delete_metadata_keys
38
- self.annotations = annotations
34
+
35
+ def expect_transform_results(self):
36
+ self.expected_result_type = TransformResults
37
+
38
+ def add_transform_result(self, content: List[IOContent], metadata: Dict, delete_metadata_keys: List[str],
39
+ annotations: Dict, name: str = None):
40
+ self.results.append(
41
+ {
42
+ 'content': content,
43
+ 'metadata': metadata,
44
+ 'delete_metadata_keys': delete_metadata_keys,
45
+ 'annotations': annotations,
46
+ 'name': name
47
+ }
48
+ )
39
49
 
40
50
 
41
51
  class TransformActionTest(ActionTest):
@@ -50,6 +60,8 @@ class TransformActionTest(ActionTest):
50
60
  def transform(self, test_case: TransformTestCase):
51
61
  if test_case.expected_result_type == TransformResult:
52
62
  self.expect_transform_result(test_case)
63
+ elif test_case.expected_result_type == TransformResults:
64
+ self.expect_transform_results(test_case)
53
65
  else:
54
66
  super().execute(test_case)
55
67
 
@@ -57,19 +69,35 @@ class TransformActionTest(ActionTest):
57
69
  result = super().run_and_check_result_type(test_case, TransformResult)
58
70
  self.assert_transform_result(test_case, result)
59
71
 
72
+ def expect_transform_results(self, test_case: TransformTestCase):
73
+ result = super().run_and_check_result_type(test_case, TransformResults)
74
+ self.assert_transform_results(test_case, result)
75
+
76
+ def assert_transform_results(self, test_case: TransformTestCase, result: TransformResults):
77
+ assert_equal_len(test_case.results, result.named_results)
78
+ for index, named_result in enumerate(result.named_results):
79
+ self.compare_one_transform_result(test_case, named_result.result, index)
80
+ expected = test_case.results[index]
81
+ if 'name' in expected:
82
+ assert_equal_with_label(expected["name"], named_result.name, f"name[{index}]")
83
+
60
84
  def assert_transform_result(self, test_case: TransformTestCase, result: TransformResult):
61
85
  # Check metrics
62
86
  self.compare_metrics(test_case.expected_metrics, result.metrics)
87
+ self.compare_one_transform_result(test_case, result, 0)
88
+
89
+ def compare_one_transform_result(self, test_case: TransformTestCase, result: TransformResult, index: int):
90
+ expected = test_case.results[index]
63
91
 
64
92
  # Check output
65
- self.compare_all_output(test_case.compare_tool, result.content)
93
+ self.compare_content_list(test_case.compare_tool, expected['content'], result.content)
66
94
 
67
95
  # Check metadata
68
- assert_keys_and_values(test_case.metadata, result.metadata)
96
+ assert_keys_and_values(expected['metadata'], result.metadata)
69
97
 
70
98
  # Check deleted metadata
71
- for key in test_case.delete_metadata_keys:
99
+ for key in expected['delete_metadata_keys']:
72
100
  assert_key_in(key, result.delete_metadata_keys)
73
101
 
74
102
  # Check annotations
75
- assert_keys_and_values(test_case.annotations, result.annotations)
103
+ assert_keys_and_values(expected['annotations'], result.annotations)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: deltafi
3
- Version: 2.0rc1720728217472
3
+ Version: 2.0rc1722532930396
4
4
  Summary: SDK for DeltaFi plugins and actions
5
5
  License: Apache License, Version 2.0
6
6
  Keywords: deltafi
@@ -20,11 +20,11 @@ Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Topic :: Software Development
21
21
  Requires-Dist: deepdiff (>=6.7.1)
22
22
  Requires-Dist: json-logging (>=1.3.0)
23
- Requires-Dist: minio (>=7.2.3)
24
- Requires-Dist: pydantic (>=2.5.3)
25
- Requires-Dist: redis (>=5.0.1)
26
- Requires-Dist: requests (>=2.31.0)
27
- Requires-Dist: urllib3 (>=2.1.0)
23
+ Requires-Dist: minio (>=7.2.7)
24
+ Requires-Dist: pydantic (>=2.8.2)
25
+ Requires-Dist: redis (>=5.0.7)
26
+ Requires-Dist: requests (>=2.32.3)
27
+ Requires-Dist: urllib3 (>=2.2.2)
28
28
  Project-URL: Bug Reports, https://chat.deltafi.org/deltafi/channels/bug-reports
29
29
  Project-URL: Documentation, https://docs.deltafi.org/#/
30
30
  Project-URL: Source Code, https://gitlab.com/deltafi/deltafi
@@ -0,0 +1,23 @@
1
+ deltafi/__init__.py,sha256=qv6y7PpBG0ekTN9EuD9Lj8JYOLVqZA6tvHwgjplncAM,709
2
+ deltafi/action.py,sha256=eK18D7DCCELwEDouq3ssTv-pHWj_qWzkc00rvyKc8ho,5552
3
+ deltafi/actioneventqueue.py,sha256=mCRE1PFXy_KvaeezTeMze5N400CO1V06zEF8FFD6xZk,2847
4
+ deltafi/actiontype.py,sha256=V7JbTgHQIaWQ2N36pG-XV7kAXhq8qvj954z71iHw_wI,913
5
+ deltafi/domain.py,sha256=98295Cpm-y6BlbI2b7LvHj4OPD6LXOw1bqK9E8Pm5no,12030
6
+ deltafi/exception.py,sha256=Z8LwxxTiTyuG3v7FAsjfz6cAqRAJFKK2q_2TbEDrIJE,943
7
+ deltafi/genericmodel.py,sha256=LBIhU1rLU4HjoD8ooMfpbEhcRkrTIeGXCP1-0palKic,1152
8
+ deltafi/input.py,sha256=2qQcOWqz7lOXZIZipTz5XtcGESpjdnUAsZ7b9YqHw7M,1656
9
+ deltafi/logger.py,sha256=b6vTKSJjfXfzJIKB7bLrefIvlaIQAxWkeDJYzT1EXes,2141
10
+ deltafi/metric.py,sha256=eIDjZQVO53KuAFoEtjLNFwqMrp_7BC0Td9GLD1tb6sE,967
11
+ deltafi/plugin.py,sha256=4PMvA22_mo2JOohvqbX96KeT6MAQQygVNuznp5vGSW4,12462
12
+ deltafi/result.py,sha256=AMjGygjvix9PdUbQvSa_gZEkTn9BJh2p-BdirqdjJpM,8212
13
+ deltafi/storage.py,sha256=toq58EPZgzj2TfDF-YpFUmRnsWSjACA0KQAZzkM04xU,2740
14
+ deltafi/test_kit/__init__.py,sha256=qv6y7PpBG0ekTN9EuD9Lj8JYOLVqZA6tvHwgjplncAM,709
15
+ deltafi/test_kit/assertions.py,sha256=2eahqmbedhnHXMguiJHdaV-6sx4_jvCbxH4HSzx6PV8,1378
16
+ deltafi/test_kit/compare_helpers.py,sha256=Q0e14q4XQ4rlMUbPt3aMHThAXHFRXlue3-M4oAayyJE,12957
17
+ deltafi/test_kit/constants.py,sha256=epz0OS-qILcc8t7iIs5B3m2-wvZx8FpYpyb19ZsImbI,833
18
+ deltafi/test_kit/egress.py,sha256=nF7YYak-_X35m7h2rSIcju86IJBf8cVaFHs7xw7-_b8,1899
19
+ deltafi/test_kit/framework.py,sha256=mgKR1Yd75p76wIqWO5XpP6eMgC8fvz9MAfS01QV9WuU,14910
20
+ deltafi/test_kit/transform.py,sha256=q9zQdZswTKwU5Om8E9Lwg0G5JI8LEXuRZjT9oam-Zoo,4085
21
+ deltafi-2.0rc1722532930396.dist-info/METADATA,sha256=gqXgmsLvr4NqA-DzrCPXs3gNnSKjrz_ptfUVbeZ_i9w,1446
22
+ deltafi-2.0rc1722532930396.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
23
+ deltafi-2.0rc1722532930396.dist-info/RECORD,,
@@ -1,59 +0,0 @@
1
- #
2
- # DeltaFi - Data transformation and enrichment platform
3
- #
4
- # Copyright 2021-2023 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
- from deltafi.result import DomainResult
20
-
21
- from .assertions import *
22
- from .framework import TestCaseBase, ActionTest
23
-
24
-
25
- class DomainTestCase(TestCaseBase):
26
- def __init__(self, fields: Dict):
27
- super().__init__(fields)
28
- self.annotations = {}
29
-
30
- def expect_domain_result(self, annotations: Dict):
31
- self.expected_result_type = DomainResult
32
- self.annotations = annotations
33
-
34
-
35
- class DomainActionTest(ActionTest):
36
- def __init__(self, package_name: str):
37
- """
38
- Provides structure for testing DeltaFi Domain action
39
- Args:
40
- package_name: name of the actions package for finding resources
41
- """
42
- super().__init__(package_name)
43
-
44
- def domain(self, test_case: DomainTestCase):
45
- if test_case.expected_result_type == DomainResult:
46
- self.expect_domain_result(test_case)
47
- else:
48
- super().execute(test_case)
49
-
50
- def expect_domain_result(self, test_case: DomainTestCase):
51
- result = super().run_and_check_result_type(test_case, DomainResult)
52
- self.assert_domain_result(test_case, result)
53
-
54
- def assert_domain_result(self, test_case: DomainTestCase, result: DomainResult):
55
- # Check metrics
56
- self.compare_metrics(test_case.expected_metrics, result.metrics)
57
-
58
- # Check annotations
59
- assert_keys_and_values(test_case.annotations, result.annotations)
@@ -1,70 +0,0 @@
1
- #
2
- # DeltaFi - Data transformation and enrichment platform
3
- #
4
- # Copyright 2021-2023 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
- from deltafi.result import EnrichResult
20
-
21
- from .assertions import *
22
- from .framework import TestCaseBase, ActionTest
23
-
24
-
25
- class EnrichTestCase(TestCaseBase):
26
- def __init__(self, fields: Dict):
27
- super().__init__(fields)
28
- self.enrichments = []
29
- self.annotations = {}
30
-
31
- def expect_enrich_result(self, annotations: Dict):
32
- self.expected_result_type = EnrichResult
33
- self.annotations = annotations
34
-
35
- def add_enrichment(self, name: str, value: str, media_type: str):
36
- self.enrichments.append({'name': name, 'value': value, 'mediaType': media_type})
37
-
38
-
39
- class EnrichActionTest(ActionTest):
40
- def __init__(self, package_name: str):
41
- """
42
- Provides structure for testing DeltaFi Enrich action
43
- Args:
44
- package_name: name of the actions package for finding resources
45
- """
46
- super().__init__(package_name)
47
-
48
- def enrich(self, test_case: EnrichTestCase):
49
- if test_case.expected_result_type == EnrichResult:
50
- self.expect_enrich_result(test_case)
51
- else:
52
- super().execute(test_case)
53
-
54
- def expect_enrich_result(self, test_case: EnrichTestCase):
55
- result = super().run_and_check_result_type(test_case, EnrichResult)
56
- self.assert_enrich_result(test_case, result)
57
-
58
- def assert_enrich_result(self, test_case: EnrichTestCase, result: EnrichResult):
59
- # Check metrics
60
- self.compare_metrics(test_case.expected_metrics, result.metrics)
61
-
62
- # Check annotations
63
- assert_keys_and_values(test_case.annotations, result.annotations)
64
-
65
- # Check enrichments
66
- assert_equal_len(test_case.enrichments, result.enrichments)
67
- if len(test_case.enrichments) > 0:
68
- for index, expected in enumerate(test_case.enrichments):
69
- actual = result.enrichments[index]
70
- assert_equal(expected, actual)
@@ -1,105 +0,0 @@
1
- #
2
- # DeltaFi - Data transformation and enrichment platform
3
- #
4
- # Copyright 2021-2023 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
- from typing import List
20
-
21
- from deltafi.result import FormatResult, FormatManyResult
22
-
23
- from .assertions import *
24
- from .framework import TestCaseBase, ActionTest
25
-
26
-
27
- class FormatTestCase(TestCaseBase):
28
- def __init__(self, fields: Dict):
29
- super().__init__(fields)
30
- self.metadata = {}
31
- self.delete_metadata_keys = []
32
- self.expected_format_many_result = []
33
-
34
- def expect_format_result(self, metadata: Dict, delete_metadata_keys: List[str]):
35
- self.expected_result_type = FormatResult
36
- self.metadata = metadata
37
- self.delete_metadata_keys = delete_metadata_keys
38
-
39
- def add_format_many_result(self, metadata: Dict, delete_metadata_keys: List):
40
- self.expected_result_type = FormatManyResult
41
- self.expected_format_many_result.append(
42
- {
43
- "metadata": metadata,
44
- "delete_metadata_keys": delete_metadata_keys
45
- }
46
- )
47
-
48
-
49
- class FormatActionTest(ActionTest):
50
- def __init__(self, package_name: str):
51
- """
52
- Provides structure for testing DeltaFi Format action
53
- Args:
54
- package_name: name of the actions package for finding resources
55
- """
56
- super().__init__(package_name)
57
-
58
- def format(self, test_case: FormatTestCase):
59
- if test_case.expected_result_type == FormatManyResult:
60
- self.expect_format_many_result(test_case)
61
- elif test_case.expected_result_type == FormatResult:
62
- self.expect_format_result(test_case)
63
- else:
64
- super().execute(test_case)
65
-
66
- def expect_format_result(self, test_case: FormatTestCase):
67
- result = super().run_and_check_result_type(test_case, FormatResult)
68
- self.assert_format_result(test_case, result)
69
-
70
- def expect_format_many_result(self, test_case: FormatTestCase):
71
- result = super().run_and_check_result_type(test_case, FormatManyResult)
72
- self.assert_format_many_result(test_case, result)
73
-
74
- def assert_format_result(self, test_case: FormatTestCase, result: FormatResult):
75
- # Check metrics
76
- self.compare_metrics(test_case.expected_metrics, result.metrics)
77
-
78
- # Check output
79
- if result.content is None:
80
- self.compare_all_output(test_case.compare_tool, [])
81
- else:
82
- self.compare_all_output(test_case.compare_tool, [result.content])
83
-
84
- # Check metadata
85
- assert_keys_and_values(test_case.metadata, result.metadata)
86
-
87
- # Check deleted metadata
88
- for key in test_case.delete_metadata_keys:
89
- assert_key_in(key, result.delete_metadata_keys)
90
-
91
- def assert_format_many_result(self, test_case: FormatTestCase, actual: FormatManyResult):
92
- # Check metrics
93
- self.compare_metrics(test_case.expected_metrics, actual.metrics)
94
-
95
- assert_equal_len(test_case.expected_format_many_result, actual.format_results)
96
- for index, expected_child_result in enumerate(test_case.expected_format_many_result):
97
- actual_child = actual.format_results[index]
98
- self.compare_one_content(
99
- test_case.compare_tool,
100
- self.expected_outputs[index],
101
- actual_child.format_result.content, index)
102
-
103
- assert_keys_and_values(expected_child_result['metadata'], actual_child.format_result.metadata)
104
- for key in expected_child_result['delete_metadata_keys']:
105
- assert_key_in(key, actual_child.format_result.delete_metadata_keys)