feldera 0.40.0__tar.gz → 0.42.0__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.

Potentially problematic release.


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

Files changed (29) hide show
  1. {feldera-0.40.0 → feldera-0.42.0}/PKG-INFO +4 -4
  2. {feldera-0.40.0 → feldera-0.42.0}/feldera/pipeline.py +1 -1
  3. {feldera-0.40.0 → feldera-0.42.0}/feldera/rest/feldera_client.py +30 -3
  4. {feldera-0.40.0 → feldera-0.42.0}/feldera.egg-info/PKG-INFO +4 -4
  5. {feldera-0.40.0 → feldera-0.42.0}/feldera.egg-info/requires.txt +2 -2
  6. {feldera-0.40.0 → feldera-0.42.0}/pyproject.toml +3 -3
  7. {feldera-0.40.0 → feldera-0.42.0}/tests/test_pipeline_builder.py +52 -0
  8. {feldera-0.40.0 → feldera-0.42.0}/README.md +0 -0
  9. {feldera-0.40.0 → feldera-0.42.0}/feldera/__init__.py +0 -0
  10. {feldera-0.40.0 → feldera-0.42.0}/feldera/_callback_runner.py +0 -0
  11. {feldera-0.40.0 → feldera-0.42.0}/feldera/_helpers.py +0 -0
  12. {feldera-0.40.0 → feldera-0.42.0}/feldera/enums.py +0 -0
  13. {feldera-0.40.0 → feldera-0.42.0}/feldera/output_handler.py +0 -0
  14. {feldera-0.40.0 → feldera-0.42.0}/feldera/pipeline_builder.py +0 -0
  15. {feldera-0.40.0 → feldera-0.42.0}/feldera/rest/__init__.py +0 -0
  16. {feldera-0.40.0 → feldera-0.42.0}/feldera/rest/_httprequests.py +0 -0
  17. {feldera-0.40.0 → feldera-0.42.0}/feldera/rest/config.py +0 -0
  18. {feldera-0.40.0 → feldera-0.42.0}/feldera/rest/errors.py +0 -0
  19. {feldera-0.40.0 → feldera-0.42.0}/feldera/rest/pipeline.py +0 -0
  20. {feldera-0.40.0 → feldera-0.42.0}/feldera/rest/sql_table.py +0 -0
  21. {feldera-0.40.0 → feldera-0.42.0}/feldera/rest/sql_view.py +0 -0
  22. {feldera-0.40.0 → feldera-0.42.0}/feldera/runtime_config.py +0 -0
  23. {feldera-0.40.0 → feldera-0.42.0}/feldera.egg-info/SOURCES.txt +0 -0
  24. {feldera-0.40.0 → feldera-0.42.0}/feldera.egg-info/dependency_links.txt +0 -0
  25. {feldera-0.40.0 → feldera-0.42.0}/feldera.egg-info/top_level.txt +0 -0
  26. {feldera-0.40.0 → feldera-0.42.0}/setup.cfg +0 -0
  27. {feldera-0.40.0 → feldera-0.42.0}/tests/test_pipeline.py +0 -0
  28. {feldera-0.40.0 → feldera-0.42.0}/tests/test_udf.py +0 -0
  29. {feldera-0.40.0 → feldera-0.42.0}/tests/test_variant.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: feldera
3
- Version: 0.40.0
3
+ Version: 0.42.0
4
4
  Summary: The feldera python client
5
5
  Author-email: Abhinav <abhinav.gyawali@feldera.com>
6
6
  License: MIT
@@ -16,9 +16,9 @@ Classifier: Operating System :: OS Independent
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  Requires-Dist: requests
19
- Requires-Dist: pandas
19
+ Requires-Dist: pandas>=2.1.2
20
20
  Requires-Dist: typing-extensions
21
- Requires-Dist: numpy<2
21
+ Requires-Dist: numpy>=2.2.4
22
22
  Requires-Dist: pretty-errors
23
23
  Requires-Dist: ruff>=0.6.9
24
24
 
@@ -534,7 +534,7 @@ resume a paused pipeline."""
534
534
  def checkpoint(self):
535
535
  """
536
536
  Checkpoints this pipeline, if fault-tolerance is enabled.
537
- Fault Tolerance in Feldera: <https://docs.feldera.com/fault-tolerance/>
537
+ Fault Tolerance in Feldera: <https://docs.feldera.com/pipelines/fault-tolerance/>
538
538
 
539
539
  :raises FelderaAPIError: If checkpointing is not enabled.
540
540
  """
@@ -1,5 +1,5 @@
1
1
  import pathlib
2
- from typing import Optional
2
+ from typing import Any, Dict, Optional
3
3
  import logging
4
4
  import time
5
5
  import json
@@ -12,6 +12,21 @@ from feldera.rest.pipeline import Pipeline
12
12
  from feldera.rest._httprequests import HttpRequests
13
13
 
14
14
 
15
+ def _validate_no_none_keys_in_map(data):
16
+ def validate_no_none_keys(d: Dict[Any, Any]) -> None:
17
+ for k, v in d.items():
18
+ if isinstance(v, dict) and any(k is None for k in v.keys()):
19
+ raise ValueError("keys of SQL MAP objects cannot be NULL")
20
+
21
+ if isinstance(data, list):
22
+ for datum in data:
23
+ validate_no_none_keys(datum)
24
+ elif isinstance(data, dict):
25
+ validate_no_none_keys(data)
26
+ else:
27
+ return
28
+
29
+
15
30
  def _prepare_boolean_input(value: bool) -> str:
16
31
  return "true" if value else "false"
17
32
 
@@ -57,7 +72,7 @@ class FelderaClient:
57
72
  Create a FelderaClient that connects to the local Feldera instance
58
73
  """
59
74
 
60
- return FelderaClient(f"http://localhost:{port}")
75
+ return FelderaClient(f"http://127.0.0.1:{port}")
61
76
 
62
77
  def get_pipeline(self, pipeline_name) -> Pipeline:
63
78
  """
@@ -343,7 +358,7 @@ Reason: The pipeline is in a FAILED state due to the following error:
343
358
  pipeline_name: str,
344
359
  table_name: str,
345
360
  format: str,
346
- data: list[list | str | dict],
361
+ data: list[list | str | dict] | dict,
347
362
  array: bool = False,
348
363
  force: bool = False,
349
364
  update_format: str = "raw",
@@ -393,6 +408,18 @@ Reason: The pipeline is in a FAILED state due to the following error:
393
408
  "json_flavor must be one of 'default', 'debezium_mysql', 'snowflake', 'kafka_connect_json_converter', 'pandas'"
394
409
  )
395
410
 
411
+ if update_format == "insert_delete":
412
+ if array:
413
+ for datum in data:
414
+ _validate_no_none_keys_in_map(datum.get("insert", {}))
415
+ _validate_no_none_keys_in_map(datum.get("delete", {}))
416
+ else:
417
+ data: dict = data
418
+ _validate_no_none_keys_in_map(data.get("insert", {}))
419
+ _validate_no_none_keys_in_map(data.get("delete", {}))
420
+ else:
421
+ _validate_no_none_keys_in_map(data)
422
+
396
423
  # python sends `True` which isn't accepted by the backend
397
424
  array = _prepare_boolean_input(array)
398
425
  force = _prepare_boolean_input(force)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: feldera
3
- Version: 0.40.0
3
+ Version: 0.42.0
4
4
  Summary: The feldera python client
5
5
  Author-email: Abhinav <abhinav.gyawali@feldera.com>
6
6
  License: MIT
@@ -16,9 +16,9 @@ Classifier: Operating System :: OS Independent
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  Requires-Dist: requests
19
- Requires-Dist: pandas
19
+ Requires-Dist: pandas>=2.1.2
20
20
  Requires-Dist: typing-extensions
21
- Requires-Dist: numpy<2
21
+ Requires-Dist: numpy>=2.2.4
22
22
  Requires-Dist: pretty-errors
23
23
  Requires-Dist: ruff>=0.6.9
24
24
 
@@ -1,6 +1,6 @@
1
1
  requests
2
- pandas
2
+ pandas>=2.1.2
3
3
  typing-extensions
4
- numpy<2
4
+ numpy>=2.2.4
5
5
  pretty-errors
6
6
  ruff>=0.6.9
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
  name = "feldera"
7
7
  readme = "README.md"
8
8
  description = "The feldera python client"
9
- version = "0.40.0"
9
+ version = "0.42.0"
10
10
  license = { text = "MIT" }
11
11
  requires-python = ">=3.10"
12
12
  authors = [
@@ -24,9 +24,9 @@ classifiers = [
24
24
  ]
25
25
  dependencies = [
26
26
  "requests",
27
- "pandas",
27
+ "pandas>=2.1.2",
28
28
  "typing-extensions",
29
- "numpy<2",
29
+ "numpy>=2.2.4",
30
30
  "pretty-errors",
31
31
  "ruff>=0.6.9",
32
32
  ]
@@ -912,9 +912,20 @@ Code snippet:
912
912
  pipeline.start()
913
913
  pipeline.input_json("t0", data)
914
914
  pipeline.wait_for_completion(True)
915
+ pipeline.shutdown()
916
+
915
917
  got = out.to_dict()
918
+ assert expected == got
916
919
 
920
+ pipeline.start()
921
+ out = pipeline.listen("v0")
922
+ pipeline.input_json("t0", {"c1": {"a": 1, "b": 2}})
923
+ pipeline.wait_for_completion(True)
924
+ pipeline.shutdown()
925
+
926
+ got = out.to_dict()
917
927
  assert expected == got
928
+
918
929
  pipeline.delete()
919
930
 
920
931
  def test_failed_pipeline_shutdown(self):
@@ -1089,6 +1100,47 @@ Code snippet:
1089
1100
 
1090
1101
  assert got == data
1091
1102
 
1103
+ def test_issue3754(self):
1104
+ name = "test_issue3754"
1105
+ sql = """
1106
+ CREATE TABLE map_tbl(m_var MAP<VARCHAR, VARCHAR>);
1107
+ CREATE MATERIALIZED VIEW v AS SELECT * FROM map_tbl;
1108
+ """
1109
+
1110
+ pipeline = PipelineBuilder(TEST_CLIENT, name, sql=sql).create_or_replace()
1111
+ pipeline.start()
1112
+
1113
+ with self.assertRaises(ValueError):
1114
+ data = [{"insert": {"m_var": {None: 1}}}]
1115
+ TEST_CLIENT.push_to_pipeline(name, "map_tbl", "insert_delete", data)
1116
+
1117
+ with self.assertRaises(ValueError):
1118
+ data = [{"delete": {"m_var": {None: 1}}}]
1119
+ TEST_CLIENT.push_to_pipeline(name, "map_tbl", "insert_delete", data)
1120
+
1121
+ with self.assertRaises(ValueError):
1122
+ data = {"insert": {"m_var": {None: 1}}}
1123
+ TEST_CLIENT.push_to_pipeline(name, "map_tbl", "insert_delete", data)
1124
+
1125
+ with self.assertRaises(ValueError):
1126
+ data = {"delete": {"m_var": {None: 1}}}
1127
+ TEST_CLIENT.push_to_pipeline(name, "map_tbl", "insert_delete", data)
1128
+
1129
+ with self.assertRaises(ValueError):
1130
+ data = [{"m_var": {None: 1}}]
1131
+ TEST_CLIENT.push_to_pipeline(name, "map_tbl", "raw", data)
1132
+
1133
+ with self.assertRaises(ValueError):
1134
+ data = {"m_var": {None: 1}}
1135
+ TEST_CLIENT.push_to_pipeline(name, "map_tbl", "raw", data)
1136
+
1137
+ with self.assertRaises(ValueError):
1138
+ data = {"m_var": {None: 1}}
1139
+ pipeline.input_json("map_tbl", data)
1140
+
1141
+ pipeline.shutdown()
1142
+ pipeline.delete()
1143
+
1092
1144
 
1093
1145
  if __name__ == "__main__":
1094
1146
  unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes