feldera 0.134.0__tar.gz → 0.136.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 (31) hide show
  1. {feldera-0.134.0 → feldera-0.136.0}/PKG-INFO +1 -1
  2. {feldera-0.134.0 → feldera-0.136.0}/feldera/_callback_runner.py +10 -9
  3. {feldera-0.134.0 → feldera-0.136.0}/feldera/_helpers.py +2 -2
  4. {feldera-0.134.0 → feldera-0.136.0}/feldera/pipeline.py +10 -0
  5. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/_httprequests.py +1 -1
  6. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/config.py +19 -5
  7. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/feldera_client.py +14 -7
  8. {feldera-0.134.0 → feldera-0.136.0}/feldera/testutils.py +7 -1
  9. {feldera-0.134.0 → feldera-0.136.0}/feldera.egg-info/PKG-INFO +1 -1
  10. {feldera-0.134.0 → feldera-0.136.0}/pyproject.toml +4 -1
  11. {feldera-0.134.0 → feldera-0.136.0}/README.md +0 -0
  12. {feldera-0.134.0 → feldera-0.136.0}/feldera/__init__.py +0 -0
  13. {feldera-0.134.0 → feldera-0.136.0}/feldera/enums.py +0 -0
  14. {feldera-0.134.0 → feldera-0.136.0}/feldera/output_handler.py +0 -0
  15. {feldera-0.134.0 → feldera-0.136.0}/feldera/pipeline_builder.py +0 -0
  16. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/__init__.py +0 -0
  17. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/_helpers.py +0 -0
  18. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/errors.py +0 -0
  19. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/feldera_config.py +0 -0
  20. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/pipeline.py +0 -0
  21. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/sql_table.py +0 -0
  22. {feldera-0.134.0 → feldera-0.136.0}/feldera/rest/sql_view.py +0 -0
  23. {feldera-0.134.0 → feldera-0.136.0}/feldera/runtime_config.py +0 -0
  24. {feldera-0.134.0 → feldera-0.136.0}/feldera/stats.py +0 -0
  25. {feldera-0.134.0 → feldera-0.136.0}/feldera/tests/test_datafusionize.py +0 -0
  26. {feldera-0.134.0 → feldera-0.136.0}/feldera.egg-info/SOURCES.txt +0 -0
  27. {feldera-0.134.0 → feldera-0.136.0}/feldera.egg-info/dependency_links.txt +0 -0
  28. {feldera-0.134.0 → feldera-0.136.0}/feldera.egg-info/requires.txt +0 -0
  29. {feldera-0.134.0 → feldera-0.136.0}/feldera.egg-info/top_level.txt +0 -0
  30. {feldera-0.134.0 → feldera-0.136.0}/setup.cfg +0 -0
  31. {feldera-0.134.0 → feldera-0.136.0}/tests/test_uda.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: feldera
3
- Version: 0.134.0
3
+ Version: 0.136.0
4
4
  Summary: The feldera python client
5
5
  Author-email: Feldera Team <dev@feldera.com>
6
6
  License: MIT
@@ -39,14 +39,12 @@ class CallbackRunner(Thread):
39
39
  """
40
40
 
41
41
  pipeline = self.client.get_pipeline(self.pipeline_name)
42
- schema = pipeline.program_info["schema"]
43
42
 
44
- if schema:
45
- schemas = [relation for relation in schema["inputs"] + schema["outputs"]]
46
- for schema in schemas:
47
- if schema["name"] == self.view_name:
48
- self.schema = schema
49
- break
43
+ schemas = pipeline.tables + pipeline.views
44
+ for schema in schemas:
45
+ if schema.name == self.view_name:
46
+ self.schema = schema
47
+ break
50
48
 
51
49
  if self.schema is None:
52
50
  raise ValueError(
@@ -66,7 +64,10 @@ class CallbackRunner(Thread):
66
64
  case _CallbackRunnerInstruction.PipelineStarted:
67
65
  # listen to the pipeline
68
66
  gen_obj = self.client.listen_to_pipeline(
69
- self.pipeline_name, self.view_name, format="json"
67
+ self.pipeline_name,
68
+ self.view_name,
69
+ format="json",
70
+ case_sensitive=self.schema.case_sensitive,
70
71
  )
71
72
 
72
73
  # if there is a queue set up, inform the main thread that the listener has been started, and it can
@@ -83,7 +84,7 @@ class CallbackRunner(Thread):
83
84
  seq_no: Optional[int] = chunk.get("sequence_number")
84
85
  if data is not None and seq_no is not None:
85
86
  self.callback(
86
- dataframe_from_response([data], self.schema), seq_no
87
+ dataframe_from_response([data], self.schema.fields), seq_no
87
88
  )
88
89
 
89
90
  if self.queue:
@@ -60,7 +60,7 @@ def ensure_dataframe_has_columns(df: pd.DataFrame):
60
60
  )
61
61
 
62
62
 
63
- def dataframe_from_response(buffer: list[list[dict]], schema: dict):
63
+ def dataframe_from_response(buffer: list[list[dict]], fields: list[dict]):
64
64
  """
65
65
  Converts the response from Feldera to a pandas DataFrame.
66
66
  """
@@ -70,7 +70,7 @@ def dataframe_from_response(buffer: list[list[dict]], schema: dict):
70
70
  decimal_col = []
71
71
  uuid_col = []
72
72
 
73
- for column in schema["fields"]:
73
+ for column in fields:
74
74
  column_name = column["name"]
75
75
  if not column["case_sensitive"]:
76
76
  column_name = column_name.lower()
@@ -685,6 +685,7 @@ pipeline '{self.name}' to make checkpoint '{seq}'"""
685
685
  checkpoint to complete syncing.
686
686
 
687
687
  :raises FelderaAPIError: If no checkpoints have been made.
688
+ :raises RuntimeError: If syncing the checkpoint fails.
688
689
  """
689
690
 
690
691
  uuid = self.client.sync_checkpoint(self.name)
@@ -702,6 +703,11 @@ pipeline '{self.name}' to make checkpoint '{seq}'"""
702
703
  pipeline '{self.name}' to sync checkpoint '{uuid}'"""
703
704
  )
704
705
  status = self.sync_checkpoint_status(uuid)
706
+ if status == CheckpointStatus.Failure:
707
+ raise RuntimeError(
708
+ f"failed to sync checkpoint '{uuid}': ", status.get_error()
709
+ )
710
+
705
711
  if status in [CheckpointStatus.InProgress, CheckpointStatus.Unknown]:
706
712
  time.sleep(0.1)
707
713
  continue
@@ -716,6 +722,9 @@ pipeline '{self.name}' to sync checkpoint '{uuid}'"""
716
722
  If the checkpoint is currently being synchronized, returns
717
723
  `CheckpointStatus.Unknown`.
718
724
 
725
+ Failures are not raised as runtime errors and must be explicitly
726
+ checked.
727
+
719
728
  :param uuid: The checkpoint uuid.
720
729
  """
721
730
 
@@ -731,6 +740,7 @@ pipeline '{self.name}' to sync checkpoint '{uuid}'"""
731
740
  if uuid == fail.get("uuid"):
732
741
  failure = CheckpointStatus.Failure
733
742
  failure.error = fail.get("error", "")
743
+ logging.error(f"failed to sync checkpoint '{uuid}': {failure.error}")
734
744
  return failure
735
745
 
736
746
  if (success is None) or UUID(uuid) > UUID(success):
@@ -26,7 +26,7 @@ class HttpRequests:
26
26
  self.headers = {"User-Agent": "feldera-python-sdk/v1"}
27
27
  self.requests_verify = config.requests_verify
28
28
 
29
- if not self.requests_verify:
29
+ if isinstance(self.requests_verify, bool) and not self.requests_verify:
30
30
  urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
31
31
 
32
32
  if self.config.api_key:
@@ -1,4 +1,5 @@
1
1
  from typing import Optional
2
+ import os
2
3
 
3
4
 
4
5
  class Config:
@@ -8,12 +9,12 @@ class Config:
8
9
 
9
10
  def __init__(
10
11
  self,
11
- url: str,
12
+ url: Optional[str] = None,
12
13
  api_key: Optional[str] = None,
13
14
  version: Optional[str] = None,
14
15
  timeout: Optional[float] = None,
15
16
  connection_timeout: Optional[float] = None,
16
- requests_verify: bool = True,
17
+ requests_verify: bool | str = True,
17
18
  ) -> None:
18
19
  """
19
20
  :param url: The url to the Feldera API (ex: https://try.feldera.com)
@@ -25,9 +26,22 @@ class Config:
25
26
  library. `True` by default.
26
27
  """
27
28
 
28
- self.url: str = url
29
- self.api_key: Optional[str] = api_key
29
+ BASE_URL = (
30
+ url
31
+ or os.environ.get("FELDERA_HOST")
32
+ or os.environ.get("FELDERA_BASE_URL")
33
+ or "http://localhost:8080"
34
+ )
35
+ self.url: str = BASE_URL
36
+ self.api_key: Optional[str] = os.environ.get("FELDERA_API_KEY", api_key)
30
37
  self.version: Optional[str] = version or "v0"
31
38
  self.timeout: Optional[float] = timeout
32
39
  self.connection_timeout: Optional[float] = connection_timeout
33
- self.requests_verify: bool = requests_verify
40
+
41
+ FELDERA_TLS_INSECURE = True if os.environ.get("FELDERA_TLS_INSECURE") else False
42
+ FELDERA_HTTPS_TLS_CERT = os.environ.get("FELDERA_HTTPS_TLS_CERT")
43
+ requests_verify = not FELDERA_TLS_INSECURE
44
+ if requests_verify and FELDERA_HTTPS_TLS_CERT is not None:
45
+ requests_verify = FELDERA_HTTPS_TLS_CERT
46
+
47
+ self.requests_verify: bool | str = requests_verify
@@ -43,21 +43,24 @@ class FelderaClient:
43
43
 
44
44
  def __init__(
45
45
  self,
46
- url: str,
46
+ url: Optional[str] = None,
47
47
  api_key: Optional[str] = None,
48
48
  timeout: Optional[float] = None,
49
49
  connection_timeout: Optional[float] = None,
50
- requests_verify: bool = True,
50
+ requests_verify: bool | str = True,
51
51
  ) -> None:
52
52
  """
53
- :param url: The url to Feldera API (ex: https://try.feldera.com)
53
+ :param url: The url to Feldera API (ex: https://try.feldera.com). If
54
+ not set, attempts to read from the environment variable
55
+ `FELDERA_HOST`. Default: `http://localhost:8080`
54
56
  :param api_key: The optional API key for Feldera
55
57
  :param timeout: (optional) The amount of time in seconds that the
56
58
  client will wait for a response before timing out.
57
- :param connection_timeout: (optional) The amount of time in seconds that
58
- the client will wait to establish connection before timing out.
59
+ :param connection_timeout: (optional) The amount of time in seconds
60
+ that the client will wait to establish connection before timing out
59
61
  :param requests_verify: The `verify` parameter passed to the requests
60
- library. `True` by default.
62
+ library. `True` by default. To use a self signed certificate, set
63
+ it to the path to the certificate.
61
64
  """
62
65
 
63
66
  self.config = Config(
@@ -830,6 +833,7 @@ Reason: The pipeline is in a STOPPED state due to the following error:
830
833
  backpressure: bool = True,
831
834
  array: bool = False,
832
835
  timeout: Optional[float] = None,
836
+ case_sensitive: bool = False,
833
837
  ):
834
838
  """
835
839
  Listen for updates to views for pipeline, yields the chunks of data
@@ -845,6 +849,7 @@ Reason: The pipeline is in a STOPPED state due to the following error:
845
849
  "json" format, the default value is False
846
850
 
847
851
  :param timeout: The amount of time in seconds to listen to the stream for
852
+ :param case_sensitive: True if the table name is case sensitive or a reserved keyword, False by default
848
853
  """
849
854
 
850
855
  params = {
@@ -855,6 +860,8 @@ Reason: The pipeline is in a STOPPED state due to the following error:
855
860
  if format == "json":
856
861
  params["array"] = _prepare_boolean_input(array)
857
862
 
863
+ table_name = f'"{table_name}"' if case_sensitive else table_name
864
+
858
865
  resp = self.http.post(
859
866
  path=f"/pipelines/{pipeline_name}/egress/{table_name}",
860
867
  params=params,
@@ -982,7 +989,7 @@ Reason: The pipeline is in a STOPPED state due to the following error:
982
989
  stream=True,
983
990
  )
984
991
 
985
- for chunk in resp.iter_lines(chunk_size=50000000):
992
+ for chunk in resp.iter_lines(chunk_size=1024):
986
993
  if chunk:
987
994
  yield json.loads(chunk, parse_float=Decimal)
988
995
 
@@ -23,6 +23,12 @@ KAFKA_SERVER = os.environ.get("FELDERA_KAFKA_SERVER", "localhost:19092")
23
23
  PIPELINE_TO_KAFKA_SERVER = os.environ.get(
24
24
  "FELDERA_PIPELINE_TO_KAFKA_SERVER", "redpanda:9092"
25
25
  )
26
+ FELDERA_TLS_INSECURE = True if os.environ.get("FELDERA_TLS_INSECURE") else False
27
+ FELDERA_HTTPS_TLS_CERT = os.environ.get("FELDERA_HTTPS_TLS_CERT")
28
+ if not FELDERA_TLS_INSECURE and FELDERA_HTTPS_TLS_CERT is not None:
29
+ FELDERA_REQUESTS_VERIFY = FELDERA_HTTPS_TLS_CERT
30
+ else:
31
+ FELDERA_REQUESTS_VERIFY = not FELDERA_TLS_INSECURE
26
32
 
27
33
 
28
34
  class _LazyClient:
@@ -36,7 +42,7 @@ class _LazyClient:
36
42
  def _ensure(self):
37
43
  if self._client is None:
38
44
  self._client = FelderaClient(
39
- BASE_URL, api_key=API_KEY, connection_timeout=10, requests_verify=False
45
+ connection_timeout=10,
40
46
  )
41
47
  return self._client
42
48
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: feldera
3
- Version: 0.134.0
3
+ Version: 0.136.0
4
4
  Summary: The feldera python client
5
5
  Author-email: Feldera Team <dev@feldera.com>
6
6
  License: MIT
@@ -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.134.0"
9
+ version = "0.136.0"
10
10
  license = { text = "MIT" }
11
11
  requires-python = ">=3.10"
12
12
  authors = [
@@ -45,3 +45,6 @@ dev-dependencies = [
45
45
  "sphinx==7.3.7",
46
46
  "simplejson==3.20.1"
47
47
  ]
48
+
49
+ [tool.pytest.ini_options]
50
+ pythonpath = "feldera"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes