feldera 0.96.0__tar.gz → 0.99.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.
- {feldera-0.96.0 → feldera-0.99.0}/PKG-INFO +24 -6
- {feldera-0.96.0 → feldera-0.99.0}/README.md +21 -2
- feldera-0.99.0/feldera/enums.py +277 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/pipeline.py +154 -133
- {feldera-0.96.0 → feldera-0.99.0}/feldera/pipeline_builder.py +4 -1
- {feldera-0.96.0 → feldera-0.99.0}/feldera/rest/feldera_client.py +58 -37
- {feldera-0.96.0 → feldera-0.99.0}/feldera/rest/pipeline.py +1 -0
- feldera-0.99.0/feldera/stats.py +149 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera.egg-info/PKG-INFO +24 -6
- {feldera-0.96.0 → feldera-0.99.0}/feldera.egg-info/SOURCES.txt +1 -0
- {feldera-0.96.0 → feldera-0.99.0}/pyproject.toml +3 -4
- {feldera-0.96.0 → feldera-0.99.0}/tests/test_pipeline.py +30 -8
- {feldera-0.96.0 → feldera-0.99.0}/tests/test_pipeline_builder.py +59 -89
- {feldera-0.96.0 → feldera-0.99.0}/tests/test_udf.py +2 -2
- {feldera-0.96.0 → feldera-0.99.0}/tests/test_variant.py +1 -1
- feldera-0.96.0/feldera/enums.py +0 -260
- {feldera-0.96.0 → feldera-0.99.0}/feldera/__init__.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/_callback_runner.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/_helpers.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/output_handler.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/rest/__init__.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/rest/_httprequests.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/rest/config.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/rest/errors.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/rest/feldera_config.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/rest/sql_table.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/rest/sql_view.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera/runtime_config.py +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera.egg-info/dependency_links.txt +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera.egg-info/requires.txt +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/feldera.egg-info/top_level.txt +0 -0
- {feldera-0.96.0 → feldera-0.99.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: feldera
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.99.0
|
|
4
4
|
Summary: The feldera python client
|
|
5
5
|
Author-email: Feldera Team <dev@feldera.com>
|
|
6
6
|
License: MIT
|
|
@@ -10,10 +10,9 @@ Project-URL: Repository, https://github.com/feldera/feldera
|
|
|
10
10
|
Project-URL: Issues, https://github.com/feldera/feldera/issues
|
|
11
11
|
Keywords: feldera,python
|
|
12
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
14
|
Classifier: Operating System :: OS Independent
|
|
16
|
-
Requires-Python: >=3.
|
|
15
|
+
Requires-Python: >=3.12
|
|
17
16
|
Description-Content-Type: text/markdown
|
|
18
17
|
Requires-Dist: requests
|
|
19
18
|
Requires-Dist: pandas>=2.1.2
|
|
@@ -81,6 +80,8 @@ To run unit tests:
|
|
|
81
80
|
(cd python && python3 -m unittest)
|
|
82
81
|
```
|
|
83
82
|
|
|
83
|
+
> ⚠️ Running the unit tests will **delete all existing pipelines**.
|
|
84
|
+
|
|
84
85
|
The following command runs end-to-end tests. You'll need a pipeline
|
|
85
86
|
manager running at `http://localhost:8080`. For the pipeline builder
|
|
86
87
|
tests, you'll also need a broker available at `localhost:9092` and
|
|
@@ -88,13 +89,13 @@ tests, you'll also need a broker available at `localhost:9092` and
|
|
|
88
89
|
set the environment variables listed in `python/tests/__init__.py`.)
|
|
89
90
|
|
|
90
91
|
```bash
|
|
91
|
-
(cd python
|
|
92
|
+
(cd python && python3 -m pytest tests)
|
|
92
93
|
```
|
|
93
94
|
|
|
94
95
|
To run tests from a specific file:
|
|
95
96
|
|
|
96
97
|
```bash
|
|
97
|
-
(cd python
|
|
98
|
+
(cd python && python3 -m unittest ./tests/path-to-file.py)
|
|
98
99
|
```
|
|
99
100
|
|
|
100
101
|
To run the aggregate tests use:
|
|
@@ -103,3 +104,20 @@ To run the aggregate tests use:
|
|
|
103
104
|
cd python
|
|
104
105
|
PYTHONPATH=`pwd` python3 ./tests/aggregate_tests/main.py
|
|
105
106
|
```
|
|
107
|
+
|
|
108
|
+
## Linting and formatting
|
|
109
|
+
|
|
110
|
+
Use [Ruff] to run the lint checks that will be executed by the
|
|
111
|
+
precommit hook when a PR is submitted:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
ruff check python/
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
To reformat the code in the same way as the precommit hook:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
ruff format
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
[Ruff]: https://github.com/astral-sh/ruff
|
|
@@ -57,6 +57,8 @@ To run unit tests:
|
|
|
57
57
|
(cd python && python3 -m unittest)
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
+
> ⚠️ Running the unit tests will **delete all existing pipelines**.
|
|
61
|
+
|
|
60
62
|
The following command runs end-to-end tests. You'll need a pipeline
|
|
61
63
|
manager running at `http://localhost:8080`. For the pipeline builder
|
|
62
64
|
tests, you'll also need a broker available at `localhost:9092` and
|
|
@@ -64,13 +66,13 @@ tests, you'll also need a broker available at `localhost:9092` and
|
|
|
64
66
|
set the environment variables listed in `python/tests/__init__.py`.)
|
|
65
67
|
|
|
66
68
|
```bash
|
|
67
|
-
(cd python
|
|
69
|
+
(cd python && python3 -m pytest tests)
|
|
68
70
|
```
|
|
69
71
|
|
|
70
72
|
To run tests from a specific file:
|
|
71
73
|
|
|
72
74
|
```bash
|
|
73
|
-
(cd python
|
|
75
|
+
(cd python && python3 -m unittest ./tests/path-to-file.py)
|
|
74
76
|
```
|
|
75
77
|
|
|
76
78
|
To run the aggregate tests use:
|
|
@@ -79,3 +81,20 @@ To run the aggregate tests use:
|
|
|
79
81
|
cd python
|
|
80
82
|
PYTHONPATH=`pwd` python3 ./tests/aggregate_tests/main.py
|
|
81
83
|
```
|
|
84
|
+
|
|
85
|
+
## Linting and formatting
|
|
86
|
+
|
|
87
|
+
Use [Ruff] to run the lint checks that will be executed by the
|
|
88
|
+
precommit hook when a PR is submitted:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
ruff check python/
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
To reformat the code in the same way as the precommit hook:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
ruff format
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
[Ruff]: https://github.com/astral-sh/ruff
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CompilationProfile(Enum):
|
|
6
|
+
"""
|
|
7
|
+
The compilation profile to use when compiling the program.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
SERVER_DEFAULT = None
|
|
11
|
+
"""
|
|
12
|
+
The compiler server default compilation profile.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
DEV = "dev"
|
|
16
|
+
"""
|
|
17
|
+
The development compilation profile.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
UNOPTIMIZED = "unoptimized"
|
|
21
|
+
"""
|
|
22
|
+
The unoptimized compilation profile.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
OPTIMIZED = "optimized"
|
|
26
|
+
"""
|
|
27
|
+
The optimized compilation profile, the default for this API.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class BuildMode(Enum):
|
|
32
|
+
CREATE = 1
|
|
33
|
+
GET = 2
|
|
34
|
+
GET_OR_CREATE = 3
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class PipelineStatus(Enum):
|
|
38
|
+
"""
|
|
39
|
+
Represents the state that this pipeline is currently in.
|
|
40
|
+
|
|
41
|
+
.. code-block:: text
|
|
42
|
+
|
|
43
|
+
Stopped ◄─────────── Stopping ◄───── All states can transition
|
|
44
|
+
│ ▲ to Stopping by either:
|
|
45
|
+
/start or /pause │ │ (1) user calling /stop?force=true, or;
|
|
46
|
+
▼ │ (2) pipeline encountering a fatal
|
|
47
|
+
⌛Provisioning Suspending resource or runtime error,
|
|
48
|
+
│ ▲ having the system call /stop?force=true
|
|
49
|
+
▼ │ /stop effectively
|
|
50
|
+
⌛Initializing ─────────────┤ ?force=false
|
|
51
|
+
│ │
|
|
52
|
+
┌─────────┼────────────────────┴─────┐
|
|
53
|
+
│ ▼ │
|
|
54
|
+
│ Paused ◄──────► Unavailable │
|
|
55
|
+
│ │ ▲ ▲ │
|
|
56
|
+
│ /start │ │ /pause │ │
|
|
57
|
+
│ ▼ │ │ │
|
|
58
|
+
│ Running ◄─────────────┘ │
|
|
59
|
+
└────────────────────────────────────┘
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
NOT_FOUND = 0
|
|
63
|
+
"""
|
|
64
|
+
The pipeline has not been created yet.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
STOPPED = 1
|
|
68
|
+
"""
|
|
69
|
+
The pipeline has not (yet) been started or has been stopped either
|
|
70
|
+
manually by the user or automatically by the system due to a
|
|
71
|
+
resource or runtime error.
|
|
72
|
+
|
|
73
|
+
The pipeline remains in this state until:
|
|
74
|
+
|
|
75
|
+
1. The user starts it via `/start` or `/pause`, transitioning to `PROVISIONING`.
|
|
76
|
+
2. Early start fails (e.g., compilation failure), transitioning to `STOPPING`.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
PROVISIONING = 2
|
|
80
|
+
"""
|
|
81
|
+
Compute (and optionally storage) resources needed for running the pipeline
|
|
82
|
+
are being provisioned.
|
|
83
|
+
|
|
84
|
+
The pipeline remains in this state until:
|
|
85
|
+
|
|
86
|
+
1. Resources are provisioned successfully, transitioning to `INITIALIZING`.
|
|
87
|
+
2. Provisioning fails or times out, transitioning to `STOPPING`.
|
|
88
|
+
3. The user cancels the pipeline via `/stop`, transitioning to `STOPPING`.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
INITIALIZING = 3
|
|
92
|
+
"""
|
|
93
|
+
The pipeline is initializing its internal state and connectors.
|
|
94
|
+
|
|
95
|
+
The pipeline remains in this state until:
|
|
96
|
+
|
|
97
|
+
1. Initialization succeeds, transitioning to `PAUSED`.
|
|
98
|
+
2. Initialization fails or times out, transitioning to `STOPPING`.
|
|
99
|
+
3. The user suspends the pipeline via `/suspend`, transitioning to `SUSPENDING`.
|
|
100
|
+
4. The user stops the pipeline via `/stop`, transitioning to `STOPPING`.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
PAUSED = 4
|
|
104
|
+
"""
|
|
105
|
+
The pipeline is initialized but data processing is paused.
|
|
106
|
+
|
|
107
|
+
The pipeline remains in this state until:
|
|
108
|
+
|
|
109
|
+
1. The user starts it via `/start`, transitioning to `RUNNING`.
|
|
110
|
+
2. A runtime error occurs, transitioning to `STOPPING`.
|
|
111
|
+
3. The user suspends it via `/suspend`, transitioning to `SUSPENDING`.
|
|
112
|
+
4. The user stops it via `/stop`, transitioning to `STOPPING`.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
RUNNING = 5
|
|
116
|
+
"""
|
|
117
|
+
The pipeline is processing data.
|
|
118
|
+
|
|
119
|
+
The pipeline remains in this state until:
|
|
120
|
+
|
|
121
|
+
1. The user pauses it via `/pause`, transitioning to `PAUSED`.
|
|
122
|
+
2. A runtime error occurs, transitioning to `STOPPING`.
|
|
123
|
+
3. The user suspends it via `/suspend`, transitioning to `SUSPENDING`.
|
|
124
|
+
4. The user stops it via `/stop`, transitioning to `STOPPING`.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
UNAVAILABLE = 6
|
|
128
|
+
"""
|
|
129
|
+
The pipeline was initialized at least once but is currently unreachable
|
|
130
|
+
or not ready.
|
|
131
|
+
|
|
132
|
+
The pipeline remains in this state until:
|
|
133
|
+
|
|
134
|
+
1. A successful status check transitions it back to `PAUSED` or `RUNNING`.
|
|
135
|
+
2. A runtime error occurs, transitioning to `STOPPING`.
|
|
136
|
+
3. The user suspends it via `/suspend`, transitioning to `SUSPENDING`.
|
|
137
|
+
4. The user stops it via `/stop`, transitioning to `STOPPING`.
|
|
138
|
+
|
|
139
|
+
Note: While in this state, `/start` or `/pause` express desired state but
|
|
140
|
+
are only applied once the pipeline becomes reachable.
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
SUSPENDING = 7
|
|
144
|
+
"""
|
|
145
|
+
The pipeline is being suspended to storage.
|
|
146
|
+
|
|
147
|
+
The pipeline remains in this state until:
|
|
148
|
+
|
|
149
|
+
1. Suspension succeeds, transitioning to `STOPPING`.
|
|
150
|
+
2. A runtime error occurs, transitioning to `STOPPING`.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
STOPPING = 8
|
|
154
|
+
"""
|
|
155
|
+
The pipeline's compute resources are being scaled down to zero.
|
|
156
|
+
|
|
157
|
+
The pipeline remains in this state until deallocation completes,
|
|
158
|
+
transitioning to `STOPPED`.
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
@staticmethod
|
|
162
|
+
def from_str(value):
|
|
163
|
+
for member in PipelineStatus:
|
|
164
|
+
if member.name.lower() == value.lower():
|
|
165
|
+
return member
|
|
166
|
+
raise ValueError(f"Unknown value '{value}' for enum {PipelineStatus.__name__}")
|
|
167
|
+
|
|
168
|
+
def __eq__(self, other):
|
|
169
|
+
return self.value == other.value
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class ProgramStatus(Enum):
|
|
173
|
+
Pending = 1
|
|
174
|
+
CompilingSql = 2
|
|
175
|
+
SqlCompiled = 3
|
|
176
|
+
CompilingRust = 4
|
|
177
|
+
Success = 5
|
|
178
|
+
SqlError = 6
|
|
179
|
+
RustError = 7
|
|
180
|
+
SystemError = 8
|
|
181
|
+
|
|
182
|
+
def __init__(self, value):
|
|
183
|
+
self.error: Optional[dict] = None
|
|
184
|
+
self._value_ = value
|
|
185
|
+
|
|
186
|
+
@staticmethod
|
|
187
|
+
def from_value(value):
|
|
188
|
+
error = None
|
|
189
|
+
if isinstance(value, dict):
|
|
190
|
+
error = value
|
|
191
|
+
value = list(value.keys())[0]
|
|
192
|
+
|
|
193
|
+
for member in ProgramStatus:
|
|
194
|
+
if member.name.lower() == value.lower():
|
|
195
|
+
member.error = error
|
|
196
|
+
return member
|
|
197
|
+
raise ValueError(f"Unknown value '{value}' for enum {ProgramStatus.__name__}")
|
|
198
|
+
|
|
199
|
+
def __eq__(self, other):
|
|
200
|
+
return self.value == other.value
|
|
201
|
+
|
|
202
|
+
def __str__(self):
|
|
203
|
+
return self.name + (f": ({self.error})" if self.error else "")
|
|
204
|
+
|
|
205
|
+
def get_error(self) -> Optional[dict]:
|
|
206
|
+
"""
|
|
207
|
+
Returns the compilation error, if any.
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
return self.error
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class CheckpointStatus(Enum):
|
|
214
|
+
Success = 1
|
|
215
|
+
Failure = 2
|
|
216
|
+
InProgress = 3
|
|
217
|
+
Unknown = 4
|
|
218
|
+
|
|
219
|
+
def __init__(self, value):
|
|
220
|
+
self.error: Optional[str] = None
|
|
221
|
+
self._value_ = value
|
|
222
|
+
|
|
223
|
+
def __eq__(self, other):
|
|
224
|
+
return self.value == other.value
|
|
225
|
+
|
|
226
|
+
def get_error(self) -> Optional[str]:
|
|
227
|
+
"""
|
|
228
|
+
Returns the error, if any.
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
return self.error
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class StorageStatus(Enum):
|
|
235
|
+
"""
|
|
236
|
+
Represents the current storage usage status of the pipeline.
|
|
237
|
+
"""
|
|
238
|
+
|
|
239
|
+
CLEARED = 0
|
|
240
|
+
"""
|
|
241
|
+
The pipeline has not been started before, or the user has cleared storage.
|
|
242
|
+
|
|
243
|
+
In this state, the pipeline has no storage resources bound to it.
|
|
244
|
+
"""
|
|
245
|
+
|
|
246
|
+
INUSE = 1
|
|
247
|
+
"""
|
|
248
|
+
The pipeline was (attempted to be) started before, transitioning from `STOPPED`
|
|
249
|
+
to `PROVISIONING`, which caused the storage status to become `INUSE`.
|
|
250
|
+
|
|
251
|
+
Being in the `INUSE` state restricts certain edits while the pipeline is `STOPPED`.
|
|
252
|
+
|
|
253
|
+
The pipeline remains in this state until the user invokes `/clear`, transitioning
|
|
254
|
+
it to `CLEARING`.
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
CLEARING = 2
|
|
258
|
+
"""
|
|
259
|
+
The pipeline is in the process of becoming unbound from its storage resources.
|
|
260
|
+
|
|
261
|
+
If storage resources are configured to be deleted upon clearing, their deletion
|
|
262
|
+
occurs before transitioning to `CLEARED`. Otherwise, no actual work is required,
|
|
263
|
+
and the transition happens immediately.
|
|
264
|
+
|
|
265
|
+
If storage is not deleted during clearing, the responsibility to manage or delete
|
|
266
|
+
those resources lies with the user.
|
|
267
|
+
"""
|
|
268
|
+
|
|
269
|
+
@staticmethod
|
|
270
|
+
def from_str(value):
|
|
271
|
+
for member in StorageStatus:
|
|
272
|
+
if member.name.lower() == value.lower():
|
|
273
|
+
return member
|
|
274
|
+
raise ValueError(f"Unknown value '{value}' for enum {StorageStatus.__name__}")
|
|
275
|
+
|
|
276
|
+
def __eq__(self, other):
|
|
277
|
+
return self.value == other.value
|