feldera 0.166.0__py3-none-any.whl → 0.177.0__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.
@@ -1,10 +1,13 @@
1
- from threading import Thread
2
- from typing import Callable, Optional
1
+ from threading import Thread, Event
2
+ from typing import Callable, List, Optional, Mapping, Any
3
3
 
4
4
  import pandas as pd
5
5
  from feldera import FelderaClient
6
6
  from feldera._helpers import dataframe_from_response
7
7
  from feldera.enums import PipelineFieldSelector
8
+ from feldera.rest.sql_table import SQLTable
9
+ from feldera.rest.sql_view import SQLView
10
+ from feldera.rest.pipeline import Pipeline
8
11
 
9
12
 
10
13
  class CallbackRunner(Thread):
@@ -15,7 +18,17 @@ class CallbackRunner(Thread):
15
18
  view_name: str,
16
19
  callback: Callable[[pd.DataFrame, int], None],
17
20
  exception_callback: Callable[[BaseException], None],
21
+ event: Event,
18
22
  ):
23
+ """
24
+ :param client: The :class:`.FelderaClient` to use.
25
+ :param pipeline_name: The name of the current pipeline.
26
+ :param view_name: The name of the view we are listening to.
27
+ :param callback: The callback function to call on the data we receive.
28
+ :param exception_callback: The callback function to call when an exception occurs.
29
+ :param event: The event to wait for before starting the callback runner.
30
+ """
31
+
19
32
  super().__init__()
20
33
  self.daemon = True
21
34
  self.client: FelderaClient = client
@@ -23,7 +36,32 @@ class CallbackRunner(Thread):
23
36
  self.view_name: str = view_name
24
37
  self.callback: Callable[[pd.DataFrame, int], None] = callback
25
38
  self.exception_callback: Callable[[BaseException], None] = exception_callback
26
- self.schema: Optional[dict] = None
39
+ self.event: Event = event
40
+
41
+ self.pipeline: Pipeline = self.client.get_pipeline(
42
+ self.pipeline_name, PipelineFieldSelector.ALL
43
+ )
44
+
45
+ view_schema = None
46
+
47
+ schemas: List[SQLTable | SQLView] = self.pipeline.tables + self.pipeline.views
48
+ for schema in schemas:
49
+ if schema.name == self.view_name:
50
+ view_schema = schema
51
+ break
52
+
53
+ if view_schema is None:
54
+ raise ValueError(
55
+ f"Table or View {self.view_name} not found in the pipeline schema."
56
+ )
57
+
58
+ self.schema: SQLTable | SQLView = view_schema
59
+
60
+ def to_callback(self, chunk: Mapping[str, Any]):
61
+ data: Optional[list[Mapping[str, Any]]] = chunk.get("json_data")
62
+ seq_no: Optional[int] = chunk.get("sequence_number")
63
+ if data is not None and seq_no is not None:
64
+ self.callback(dataframe_from_response([data], self.schema.fields), seq_no)
27
65
 
28
66
  def run(self):
29
67
  """
@@ -33,21 +71,6 @@ class CallbackRunner(Thread):
33
71
  """
34
72
 
35
73
  try:
36
- pipeline = self.client.get_pipeline(
37
- self.pipeline_name, PipelineFieldSelector.ALL
38
- )
39
-
40
- schemas = pipeline.tables + pipeline.views
41
- for schema in schemas:
42
- if schema.name == self.view_name:
43
- self.schema = schema
44
- break
45
-
46
- if self.schema is None:
47
- raise ValueError(
48
- f"Table or View {self.view_name} not found in the pipeline schema."
49
- )
50
-
51
74
  gen_obj = self.client.listen_to_pipeline(
52
75
  self.pipeline_name,
53
76
  self.view_name,
@@ -57,13 +80,16 @@ class CallbackRunner(Thread):
57
80
 
58
81
  iterator = gen_obj()
59
82
 
83
+ # Trigger the HTTP call
84
+ chunk = next(iterator)
85
+
86
+ # Unblock the main thread
87
+ self.event.set()
88
+
89
+ self.to_callback(chunk)
90
+
60
91
  for chunk in iterator:
61
- chunk: dict = chunk
62
- data: Optional[list[dict]] = chunk.get("json_data")
63
- seq_no: Optional[int] = chunk.get("sequence_number")
64
- if data is not None and seq_no is not None:
65
- self.callback(
66
- dataframe_from_response([data], self.schema.fields), seq_no
67
- )
92
+ self.to_callback(chunk)
93
+
68
94
  except BaseException as e:
69
95
  self.exception_callback(e)
feldera/_helpers.py CHANGED
@@ -2,6 +2,7 @@ import uuid
2
2
 
3
3
  import pandas as pd
4
4
  from decimal import Decimal
5
+ from typing import Mapping, Any
5
6
 
6
7
 
7
8
  def sql_type_to_pandas_type(sql_type: str):
@@ -60,9 +61,14 @@ def ensure_dataframe_has_columns(df: pd.DataFrame):
60
61
  )
61
62
 
62
63
 
63
- def dataframe_from_response(buffer: list[list[dict]], fields: list[dict]):
64
+ def dataframe_from_response(
65
+ buffer: list[list[Mapping[str, Any]]], fields: list[Mapping[str, Any]]
66
+ ):
64
67
  """
65
68
  Converts the response from Feldera to a pandas DataFrame.
69
+
70
+ :param buffer: A buffer of a list of JSON formatted output of the view you are listening to.
71
+ :param fields: The schema (list of fields) of the view you are listening to.
66
72
  """
67
73
 
68
74
  pd_schema = {}
feldera/enums.py CHANGED
@@ -352,3 +352,15 @@ class BootstrapPolicy(Enum):
352
352
  AWAIT_APPROVAL = "await_approval"
353
353
  ALLOW = "allow"
354
354
  REJECT = "reject"
355
+
356
+
357
+ class CompletionTokenStatus(Enum):
358
+ COMPLETE = "complete"
359
+ """
360
+ Feldera has completed processing all inputs represented by this token.
361
+ """
362
+
363
+ IN_PROGRESS = "inprogress"
364
+ """
365
+ Feldera is still processing the inputs represented by this token.
366
+ """
feldera/output_handler.py CHANGED
@@ -1,6 +1,7 @@
1
1
  import pandas as pd
2
2
 
3
3
  from typing import Optional
4
+ from threading import Event
4
5
 
5
6
  from feldera import FelderaClient
6
7
  from feldera._callback_runner import CallbackRunner
@@ -23,6 +24,7 @@ class OutputHandler:
23
24
  self.view_name: str = view_name
24
25
  self.buffer: list[pd.DataFrame] = []
25
26
  self.exception: Optional[BaseException] = None
27
+ self.event = Event()
26
28
 
27
29
  # the callback that is passed to the `CallbackRunner`
28
30
  def callback(df: pd.DataFrame, _: int):
@@ -39,6 +41,7 @@ class OutputHandler:
39
41
  self.view_name,
40
42
  callback,
41
43
  exception_callback,
44
+ self.event,
42
45
  )
43
46
 
44
47
  def start(self):
@@ -47,6 +50,7 @@ class OutputHandler:
47
50
  """
48
51
 
49
52
  self.handler.start()
53
+ _ = self.event.wait()
50
54
 
51
55
  def to_pandas(self, clear_buffer: bool = True):
52
56
  """
feldera/pipeline.py CHANGED
@@ -7,11 +7,13 @@ import pandas
7
7
  from uuid import UUID
8
8
 
9
9
  from typing import List, Dict, Callable, Optional, Generator, Mapping, Any
10
+ from threading import Event
10
11
  from collections import deque
11
12
 
12
13
  from feldera.rest.errors import FelderaAPIError
13
14
  from feldera.enums import (
14
15
  BootstrapPolicy,
16
+ CompletionTokenStatus,
15
17
  PipelineFieldSelector,
16
18
  PipelineStatus,
17
19
  ProgramStatus,
@@ -294,10 +296,12 @@ class Pipeline:
294
296
  if self.status() not in [PipelineStatus.RUNNING, PipelineStatus.PAUSED]:
295
297
  raise RuntimeError("Pipeline must be running or paused to listen to output")
296
298
 
299
+ event = Event()
297
300
  handler = CallbackRunner(
298
- self.client, self.name, view_name, callback, lambda exception: None
301
+ self.client, self.name, view_name, callback, lambda exception: None, event
299
302
  )
300
303
  handler.start()
304
+ event.wait()
301
305
 
302
306
  def wait_for_completion(
303
307
  self, force_stop: bool = False, timeout_s: float | None = None
@@ -696,6 +700,17 @@ metrics"""
696
700
  err.message = f"Pipeline with name {name} not found"
697
701
  raise err
698
702
 
703
+ @staticmethod
704
+ def all(client: FelderaClient) -> List["Pipeline"]:
705
+ """
706
+ Get all pipelines.
707
+
708
+ :param client: The FelderaClient instance.
709
+ :return: A list of Pipeline objects.
710
+ """
711
+
712
+ return [Pipeline._from_inner(p, client) for p in client.pipelines()]
713
+
699
714
  def checkpoint(self, wait: bool = False, timeout_s: Optional[float] = None) -> int:
700
715
  """
701
716
  Checkpoints this pipeline.
@@ -1377,3 +1392,31 @@ pipeline '{self.name}' to sync checkpoint '{uuid}'"""
1377
1392
  print(f"Support bundle written to {path}")
1378
1393
 
1379
1394
  return support_bundle_bytes
1395
+
1396
+ def generate_completion_token(self, table_name: str, connector_name: str) -> str:
1397
+ """
1398
+ Returns a completion token that can be passed to :meth:`.Pipeline.completion_token_status` to
1399
+ check whether the pipeline has finished processing all inputs received from the connector before
1400
+ the token was generated.
1401
+ """
1402
+
1403
+ return self.client.generate_completion_token(
1404
+ self.name, table_name, connector_name
1405
+ )
1406
+
1407
+ def completion_token_status(self, token: str) -> CompletionTokenStatus:
1408
+ """
1409
+ Returns the status of the completion token.
1410
+ """
1411
+
1412
+ if self.client.completion_token_processed(self.name, token):
1413
+ return CompletionTokenStatus.COMPLETE
1414
+ else:
1415
+ return CompletionTokenStatus.IN_PROGRESS
1416
+
1417
+ def wait_for_token(self, token: str):
1418
+ """
1419
+ Blocks until the pipeline processes all inputs represented by the completion token.
1420
+ """
1421
+
1422
+ self.client.wait_for_token(self.name, token)
@@ -1,12 +1,12 @@
1
1
  import os
2
2
  from typing import Optional
3
3
 
4
+ from feldera.enums import CompilationProfile, PipelineFieldSelector
5
+ from feldera.pipeline import Pipeline
6
+ from feldera.rest.errors import FelderaAPIError
4
7
  from feldera.rest.feldera_client import FelderaClient
5
8
  from feldera.rest.pipeline import Pipeline as InnerPipeline
6
- from feldera.pipeline import Pipeline
7
- from feldera.enums import CompilationProfile, PipelineFieldSelector
8
9
  from feldera.runtime_config import RuntimeConfig
9
- from feldera.rest.errors import FelderaAPIError
10
10
 
11
11
 
12
12
  class PipelineBuilder:
@@ -49,10 +49,11 @@ class PipelineBuilder:
49
49
  "FELDERA_RUNTIME_VERSION", runtime_version
50
50
  )
51
51
 
52
- def create(self) -> Pipeline:
52
+ def create(self, wait: bool = True) -> Pipeline:
53
53
  """
54
54
  Create the pipeline if it does not exist.
55
55
 
56
+ :param wait: Whether to wait for the pipeline to be created. True by default
56
57
  :return: The created pipeline
57
58
  """
58
59
 
@@ -82,17 +83,20 @@ class PipelineBuilder:
82
83
  runtime_config=self.runtime_config.to_dict(),
83
84
  )
84
85
 
85
- inner = self.client.create_pipeline(inner)
86
+ inner = self.client.create_pipeline(inner, wait=wait)
86
87
  pipeline = Pipeline(self.client)
87
88
  pipeline._inner = inner
88
89
 
89
90
  return pipeline
90
91
 
91
- def create_or_replace(self) -> Pipeline:
92
+ def create_or_replace(self, wait: bool = True) -> Pipeline:
92
93
  """
93
94
  Creates a pipeline if it does not exist and replaces it if it exists.
94
95
 
95
96
  If the pipeline exists and is running, it will be stopped and replaced.
97
+
98
+ :param wait: Whether to wait for the pipeline to be created. True by default
99
+ :return: The created pipeline
96
100
  """
97
101
 
98
102
  if self.name is None or self.sql is None:
@@ -121,7 +125,7 @@ class PipelineBuilder:
121
125
  runtime_config=self.runtime_config.to_dict(),
122
126
  )
123
127
 
124
- inner = self.client.create_or_update_pipeline(inner)
128
+ inner = self.client.create_or_update_pipeline(inner, wait=wait)
125
129
  pipeline = Pipeline(self.client)
126
130
  pipeline._inner = inner
127
131
 
@@ -1,19 +1,18 @@
1
+ import json
1
2
  import logging
3
+ import time
4
+ from typing import Any, Callable, List, Mapping, Optional, Sequence, Union
2
5
 
3
- from feldera.rest.config import Config
6
+ import requests
7
+ from requests.packages import urllib3
4
8
 
9
+ from feldera.rest.config import Config
5
10
  from feldera.rest.errors import (
6
11
  FelderaAPIError,
7
- FelderaTimeoutError,
8
12
  FelderaCommunicationError,
13
+ FelderaTimeoutError,
9
14
  )
10
15
 
11
- import json
12
- import requests
13
- from requests.packages import urllib3
14
- from typing import Callable, Optional, Any, Union, Mapping, Sequence, List
15
- import time
16
-
17
16
 
18
17
  def json_serialize(body: Any) -> str:
19
18
  # serialize as string if this object cannot be serialized (e.g. UUID)
@@ -111,11 +110,12 @@ class HttpRequests:
111
110
  logging.debug("got response: %s", str(resp))
112
111
  return resp
113
112
  except FelderaAPIError as err:
114
- # Only retry on 503
115
- if err.status_code == 503:
113
+ # Only retry on 503 and 408
114
+ if err.status_code in [503, 408]:
116
115
  if attempt < max_retries:
117
116
  logging.warning(
118
- "HTTP 503 received for %s, retrying (%d/%d)...",
117
+ "HTTP %d received for %s, retrying (%d/%d)...",
118
+ err.status_code,
119
119
  path,
120
120
  attempt + 1,
121
121
  max_retries,
@@ -1,20 +1,20 @@
1
- import pathlib
2
- from typing import Any, Dict, Optional
1
+ import json
3
2
  import logging
3
+ import pathlib
4
4
  import time
5
- import json
6
5
  from decimal import Decimal
7
- from typing import Generator, Mapping
6
+ from typing import Any, Dict, Generator, Mapping, Optional
8
7
  from urllib.parse import quote
8
+
9
9
  import requests
10
10
 
11
11
  from feldera.enums import BootstrapPolicy, PipelineFieldSelector, PipelineStatus
12
+ from feldera.rest._helpers import client_version
13
+ from feldera.rest._httprequests import HttpRequests
12
14
  from feldera.rest.config import Config
15
+ from feldera.rest.errors import FelderaAPIError, FelderaTimeoutError
13
16
  from feldera.rest.feldera_config import FelderaConfig
14
- from feldera.rest.errors import FelderaTimeoutError, FelderaAPIError
15
17
  from feldera.rest.pipeline import Pipeline
16
- from feldera.rest._httprequests import HttpRequests
17
- from feldera.rest._helpers import client_version
18
18
 
19
19
 
20
20
  def _validate_no_none_keys_in_map(data):
@@ -126,13 +126,15 @@ class FelderaClient:
126
126
 
127
127
  return runtime_config
128
128
 
129
- def pipelines(self) -> list[Pipeline]:
129
+ def pipelines(
130
+ self, selector: PipelineFieldSelector = PipelineFieldSelector.STATUS
131
+ ) -> list[Pipeline]:
130
132
  """
131
133
  Get all pipelines
132
134
  """
133
135
 
134
136
  resp = self.http.get(
135
- path="/pipelines",
137
+ path=f"/pipelines?selector={selector.value}",
136
138
  )
137
139
 
138
140
  return [Pipeline.from_dict(pipeline) for pipeline in resp]
@@ -256,12 +258,12 @@ Reason: The pipeline is in a STOPPED state due to the following error:
256
258
  )
257
259
  time.sleep(0.1)
258
260
 
259
- def create_pipeline(self, pipeline: Pipeline) -> Pipeline:
261
+ def create_pipeline(self, pipeline: Pipeline, wait: bool = True) -> Pipeline:
260
262
  """
261
263
  Create a pipeline if it doesn't exist and wait for it to compile
262
264
 
263
-
264
- :name: The name of the pipeline
265
+ :param pipeline: The pipeline to create
266
+ :param wait: Whether to wait for the pipeline to compile. True by default
265
267
  """
266
268
 
267
269
  body = {
@@ -279,12 +281,21 @@ Reason: The pipeline is in a STOPPED state due to the following error:
279
281
  body=body,
280
282
  )
281
283
 
284
+ if not wait:
285
+ return pipeline
286
+
282
287
  return self.__wait_for_compilation(pipeline.name)
283
288
 
284
- def create_or_update_pipeline(self, pipeline: Pipeline) -> Pipeline:
289
+ def create_or_update_pipeline(
290
+ self, pipeline: Pipeline, wait: bool = True
291
+ ) -> Pipeline:
285
292
  """
286
293
  Create a pipeline if it doesn't exist or update a pipeline and wait for
287
294
  it to compile
295
+
296
+ :param pipeline: The pipeline to create or update
297
+ :param wait: Whether to wait for the pipeline to compile. True by default
298
+ :return: The created or updated pipeline
288
299
  """
289
300
 
290
301
  body = {
@@ -302,6 +313,9 @@ Reason: The pipeline is in a STOPPED state due to the following error:
302
313
  body=body,
303
314
  )
304
315
 
316
+ if not wait:
317
+ return pipeline
318
+
305
319
  return self.__wait_for_compilation(pipeline.name)
306
320
 
307
321
  def patch_pipeline(
@@ -883,6 +897,35 @@ Reason: The pipeline is in a STOPPED state due to the following error:
883
897
 
884
898
  return token
885
899
 
900
+ def completion_token_processed(self, pipeline_name: str, token: str) -> bool:
901
+ """
902
+ Check whether the pipeline has finished processing all inputs received from the connector before
903
+ the token was generated.
904
+
905
+ :param pipeline_name: The name of the pipeline
906
+ :param token: The token to check for completion
907
+ :return: True if the pipeline has finished processing all inputs represented by the token, False otherwise
908
+ """
909
+
910
+ params = {
911
+ "token": token,
912
+ }
913
+
914
+ resp = self.http.get(
915
+ path=f"/pipelines/{quote(pipeline_name, safe='')}/completion_status",
916
+ params=params,
917
+ )
918
+
919
+ status: Optional[str] = resp.get("status")
920
+
921
+ if status is None:
922
+ raise FelderaAPIError(
923
+ f"got empty status when checking for completion status for token: {token}",
924
+ resp,
925
+ )
926
+
927
+ return status.lower() == "complete"
928
+
886
929
  def wait_for_token(
887
930
  self, pipeline_name: str, token: str, timeout_s: Optional[float] = None
888
931
  ):
@@ -896,10 +939,6 @@ Reason: The pipeline is in a STOPPED state due to the following error:
896
939
  to process these records.
897
940
  """
898
941
 
899
- params = {
900
- "token": token,
901
- }
902
-
903
942
  start = time.monotonic()
904
943
  end = start + timeout_s if timeout_s else None
905
944
  initial_backoff = 0.1
@@ -916,18 +955,7 @@ Reason: The pipeline is in a STOPPED state due to the following error:
916
955
  + f" {timeout_s}"
917
956
  )
918
957
 
919
- resp = self.http.get(
920
- path=f"/pipelines/{pipeline_name}/completion_status", params=params
921
- )
922
-
923
- status: Optional[str] = resp.get("status")
924
- if status is None:
925
- raise FelderaAPIError(
926
- f"got empty status when checking for completion status for token: {token}",
927
- resp,
928
- )
929
-
930
- if status.lower() == "complete":
958
+ if self.completion_token_processed(pipeline_name, token):
931
959
  break
932
960
 
933
961
  elapsed = time.monotonic() - start
@@ -1191,3 +1219,31 @@ Reason: The pipeline is in a STOPPED state due to the following error:
1191
1219
  buffer += chunk
1192
1220
 
1193
1221
  return buffer
1222
+
1223
+ def generate_completion_token(
1224
+ self, pipeline_name: str, table_name: str, connector_name: str
1225
+ ) -> str:
1226
+ """
1227
+ Generate a completion token that can be passed to :meth:`.FelderaClient.completion_token_processed` to
1228
+ check whether the pipeline has finished processing all inputs received from the connector before
1229
+ the token was generated.
1230
+
1231
+ :param pipeline_name: The name of the pipeline
1232
+ :param table_name: The name of the table associated with this connector.
1233
+ :param connector_name: The name of the connector.
1234
+
1235
+ :raises FelderaAPIError: If the connector cannot be found, or if the pipeline is not running.
1236
+ """
1237
+
1238
+ resp = self.http.get(
1239
+ path=f"/pipelines/{pipeline_name}/tables/{table_name}/connectors/{connector_name}/completion_token",
1240
+ )
1241
+
1242
+ token: str | None = resp.get("token")
1243
+
1244
+ if token is None:
1245
+ raise ValueError(
1246
+ "got invalid response from feldera when generating completion token"
1247
+ )
1248
+
1249
+ return token
feldera/testutils.py CHANGED
@@ -256,7 +256,6 @@ def build_pipeline(
256
256
  compilation_profile=CompilationProfile.OPTIMIZED,
257
257
  runtime_config=RuntimeConfig(
258
258
  provisioning_timeout_secs=60,
259
- dev_tweaks={"backfill_avoidance": True},
260
259
  resources=resources,
261
260
  ),
262
261
  ).create_or_replace()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: feldera
3
- Version: 0.166.0
3
+ Version: 0.177.0
4
4
  Summary: The feldera python client
5
5
  Author-email: Feldera Team <dev@feldera.com>
6
6
  License: MIT
@@ -1,26 +1,26 @@
1
1
  feldera/__init__.py,sha256=EiY3bTj_mnfNhCGrZo6J__brfovIJ-YYAdy77PyaEoo,378
2
- feldera/_callback_runner.py,sha256=aa-CVfIxZMqfFDs1q7MGEL77org2n0BrFgUp_ye_ohY,2333
3
- feldera/_helpers.py,sha256=TQnDQW19fpljD19ppd5dASy1gUC4y8GNnnJjXxbaUmM,3019
4
- feldera/enums.py,sha256=Ro6rDgoQKCDxxX5VKJ4ndyIaRK2o98n0XeEPfvecQpk,8563
5
- feldera/output_handler.py,sha256=J3Z3w3JG_hDGO-42FMHk34HrI20zwBI9upNAN04pi40,2118
6
- feldera/pipeline.py,sha256=3FVj2Sp_N44ZSNZO_FKC9oZciCH1h7uC5C081H0hTjM,50428
7
- feldera/pipeline_builder.py,sha256=nOKoMyB47YxwrrvByKGn4CagO-dMQNFip3c5PK1DDhQ,4351
2
+ feldera/_callback_runner.py,sha256=cTYbUxSILZDcTrjsWWPiTFdMDlQ9FPoWiMqPfnvQGDg,3226
3
+ feldera/_helpers.py,sha256=wQX2d-C4an7xGXTg6VKo9VMBROXN7TUrS90LITFKQEw,3262
4
+ feldera/enums.py,sha256=p11z4PgdcL4UQLnaPPnZBB_dHTBpNaJLqsT7qJ-R0QA,8835
5
+ feldera/output_handler.py,sha256=VvDkPSfhllH3nEwg3nPkPk-uXGAXs0fdrZ0mrMqijJI,2229
6
+ feldera/pipeline.py,sha256=dDKu-RPjFx0PMpZet0_vaZh4FfuGNoIKP4xB3eM59mo,51855
7
+ feldera/pipeline_builder.py,sha256=qrXaQz0HGGNMo0wPJJSH-gooTVSlm1XODaK9643eoL8,4620
8
8
  feldera/runtime_config.py,sha256=w6rPkZyijca9jY1G8PKeqP8txXjnn5MPJYmM7B8iE3U,4602
9
9
  feldera/stats.py,sha256=YeDQwE_CixTMb2DjBCgt5jTaJAZRsrHtG-3pYuuII-8,5256
10
- feldera/testutils.py,sha256=z-efiWz8k6f1skAQ4fw21GJQzELaLrX1zYS7t1ffCVY,12624
10
+ feldera/testutils.py,sha256=ITIqXTRD44j4AhjF-41GOWKOYh3_BAV-GQzQ7HOkgDw,12571
11
11
  feldera/testutils_oidc.py,sha256=hv0IQAcVOt4uysWW3iE-5p46ZGfL1X7Vt7PjRefkXz8,12552
12
12
  feldera/rest/__init__.py,sha256=Eg-EKUU3RSTDcdxTR_7wNDnCly8VpXEzsZCQUmf-y2M,308
13
13
  feldera/rest/_helpers.py,sha256=51oJV2pF4U1NBpjIEZuc9nIEcS0qlbUNJoefhiY-PmM,1129
14
- feldera/rest/_httprequests.py,sha256=rpoq4_700hP1flEnMbGIFIyc7xeGLXs3Yh4nY387_Qg,8579
14
+ feldera/rest/_httprequests.py,sha256=vMnWJEiXB5xd3zMdLE3y5w2Zg1lvTDGOE9Hqw5D6ByU,8641
15
15
  feldera/rest/config.py,sha256=1_D22PQ1x50_aNGo-WwI-q0gBQID4qJGDJr4MURyYB4,1992
16
16
  feldera/rest/errors.py,sha256=wKWwlL5WI3SVXC8rQTy3rS3wQ9Hjjn_EY7iRHXZFIVE,2341
17
- feldera/rest/feldera_client.py,sha256=BDPvQV6J239i7VTG3Cplvm5C2c6l4fKOqLxhlhJ8Kh0,42168
17
+ feldera/rest/feldera_client.py,sha256=AA6wgmiHtzaj-71cyN7HZPS4TFsUPe8Hehfizrz6g6o,44350
18
18
  feldera/rest/feldera_config.py,sha256=1pnGbLFMSLvp7Qh_OlPLALSKCSHIktNWKvx6gYU00U4,1374
19
19
  feldera/rest/pipeline.py,sha256=Q6TM44a7-SYRhLWbBGQMriCOcMRDk4WVKjfxd8vumys,3696
20
20
  feldera/rest/sql_table.py,sha256=qrw-YwMzx5T81zDefNO1KOx7EyypFz1vPwGBzSUB7kc,652
21
21
  feldera/rest/sql_view.py,sha256=hN12mPM0mvwLCIPYywpb12s9Hd2Ws31IlTMXPriMisw,644
22
22
  feldera/tests/test_datafusionize.py,sha256=NGriTaTWf_WnXFud1wmpFwLFa_-XGjfCh6La3dWc3QA,1337
23
- feldera-0.166.0.dist-info/METADATA,sha256=pJX4S_egCCqle-hmabLkJq0ynF3BCMT48wJjGUtQpmo,2306
24
- feldera-0.166.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
- feldera-0.166.0.dist-info/top_level.txt,sha256=fB6yTqrQiO6RCbY1xP2T_mpPoTjDFtJvkJJodiee7d0,8
26
- feldera-0.166.0.dist-info/RECORD,,
23
+ feldera-0.177.0.dist-info/METADATA,sha256=QexyupSHzqF4FDRhGB_n18odxKrXPmsIygzNcBi3JbE,2306
24
+ feldera-0.177.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ feldera-0.177.0.dist-info/top_level.txt,sha256=fB6yTqrQiO6RCbY1xP2T_mpPoTjDFtJvkJJodiee7d0,8
26
+ feldera-0.177.0.dist-info/RECORD,,