feldera 0.131.0__py3-none-any.whl → 0.192.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.

Potentially problematic release.


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

@@ -0,0 +1,368 @@
1
+ """
2
+ OIDC Authentication Test Helper
3
+
4
+ Utilities for testing OIDC authentication integration with remote providers.
5
+ Provides token generation, validation helpers, and test configuration.
6
+ """
7
+
8
+ import os
9
+ import time
10
+ import json
11
+ import requests
12
+ import jwt
13
+ import logging
14
+ from typing import Optional, Dict, Any
15
+ from dataclasses import dataclass
16
+
17
+
18
+ @dataclass
19
+ class OidcTestConfig:
20
+ """Configuration for OIDC authentication tests using Resource Owner Password Flow"""
21
+
22
+ issuer: str
23
+ client_id: str
24
+ client_secret: str
25
+ username: str
26
+ password: str
27
+ scope: str = "openid profile email"
28
+
29
+ @classmethod
30
+ def from_environment(cls) -> Optional["OidcTestConfig"]:
31
+ """Load OIDC test configuration from environment variables"""
32
+ issuer = os.getenv("OIDC_TEST_ISSUER")
33
+ client_id = os.getenv("OIDC_TEST_CLIENT_ID")
34
+ client_secret = os.getenv("OIDC_TEST_CLIENT_SECRET")
35
+ username = os.getenv("OIDC_TEST_USERNAME")
36
+ password = os.getenv("OIDC_TEST_PASSWORD")
37
+
38
+ # All fields are required
39
+ if not all([issuer, client_id, client_secret, username, password]):
40
+ return None
41
+
42
+ return cls(
43
+ issuer=issuer,
44
+ client_id=client_id,
45
+ client_secret=client_secret,
46
+ username=username,
47
+ password=password,
48
+ scope=os.getenv("OIDC_TEST_SCOPE", "openid profile email"),
49
+ )
50
+
51
+
52
+ class OidcTestHelper:
53
+ """Helper class for OIDC authentication testing"""
54
+
55
+ def __init__(self, config: OidcTestConfig):
56
+ self.config = config
57
+ self._discovery_doc = None
58
+ self._jwks = None
59
+ self._access_token = None
60
+ self._token_expires_at = 0
61
+
62
+ def get_discovery_document(self) -> Dict[str, Any]:
63
+ """Fetch and cache the OIDC discovery document"""
64
+ if self._discovery_doc is None:
65
+ discovery_url = (
66
+ f"{self.config.issuer.rstrip('/')}/.well-known/openid-configuration"
67
+ )
68
+ response = requests.get(discovery_url, timeout=30)
69
+ response.raise_for_status()
70
+ self._discovery_doc = response.json()
71
+ return self._discovery_doc
72
+
73
+ def get_jwks(self) -> Dict[str, Any]:
74
+ """Fetch and cache the JSON Web Key Set"""
75
+ if self._jwks is None:
76
+ discovery_doc = self.get_discovery_document()
77
+ jwks_uri = discovery_doc["jwks_uri"]
78
+ response = requests.get(jwks_uri, timeout=30)
79
+ response.raise_for_status()
80
+ self._jwks = response.json()
81
+ return self._jwks
82
+
83
+ def get_token_endpoint(self) -> str:
84
+ """Get the token endpoint URL from discovery document"""
85
+ discovery_doc = self.get_discovery_document()
86
+ token_endpoint = discovery_doc.get("token_endpoint")
87
+ if not token_endpoint:
88
+ raise ValueError("Token endpoint not found in OIDC discovery document")
89
+ return token_endpoint
90
+
91
+ def obtain_access_token(self, pytest_cache=None) -> str:
92
+ """
93
+ Obtain access token using environment variable set by pytest master node.
94
+
95
+ The actual token fetching is handled by pytest_configure hooks in conftest.py,
96
+ which guarantees only one auth request per test session across all workers.
97
+
98
+ If OIDC is configured but no token is available, this will fail fast.
99
+ """
100
+ logger = logging.getLogger(__name__)
101
+ current_time = time.time()
102
+
103
+ # Check environment variable for cross-process token sharing
104
+ token_data = get_cached_token_from_env()
105
+ if token_data:
106
+ logger.info("Using environment variable cached access token")
107
+ # Cache in instance for future calls to avoid repeated parsing
108
+ self._access_token = token_data["access_token"]
109
+ self._token_expires_at = token_data["expires_at"]
110
+ return token_data["access_token"]
111
+
112
+ # Fallback: Check instance cache
113
+ if self._access_token and current_time < self._token_expires_at - 30:
114
+ logger.info("Using instance cached access token")
115
+ return self._access_token
116
+
117
+ # If OIDC is configured but no token is available, this is a critical failure
118
+ raise RuntimeError(
119
+ "OIDC authentication is configured but no valid token is available. "
120
+ "This indicates the oidc_token_fixture failed to retrieve a token. "
121
+ "Check OIDC configuration and ensure pytest hooks ran properly."
122
+ )
123
+
124
+ def decode_token_claims(self, token: str) -> Dict[str, Any]:
125
+ """Decode JWT token claims without signature verification (for testing)"""
126
+ return jwt.decode(token, options={"verify_signature": False})
127
+
128
+ def is_token_expired(self, token: str) -> bool:
129
+ """Check if a JWT token is expired"""
130
+ try:
131
+ claims = self.decode_token_claims(token)
132
+ exp = claims.get("exp")
133
+ if exp is None:
134
+ return False # No expiration claim
135
+ return time.time() > exp
136
+ except Exception:
137
+ return True # Invalid token is considered expired
138
+
139
+ def validate_token_structure(self, token: str) -> bool:
140
+ """Validate that token has correct JWT structure"""
141
+ try:
142
+ # Just check if it can be decoded (ignoring signature)
143
+ self.decode_token_claims(token)
144
+ return True
145
+ except Exception:
146
+ return False
147
+
148
+ def create_authenticated_headers(self) -> Dict[str, str]:
149
+ """Create HTTP headers with valid authentication token"""
150
+ token = self.obtain_access_token()
151
+ return {"Accept": "application/json", "Authorization": f"Bearer {token}"}
152
+
153
+ def get_malformed_test_tokens(self) -> Dict[str, str]:
154
+ """Get various malformed tokens for negative testing"""
155
+ return {
156
+ "malformed_structure": "not.a.jwt",
157
+ "empty": "",
158
+ "malformed_header": "eyJhbGciOiJub25lIn0.eyJzdWIiOiJ0ZXN0In0.invalid",
159
+ "wrong_issuer": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwczovL3dyb25nLWlzc3Vlci5jb20iLCJhdWQiOiJ0ZXN0IiwiZXhwIjo5OTk5OTk5OTk5fQ.signature",
160
+ }
161
+
162
+
163
+ def skip_if_oidc_not_configured():
164
+ """Decorator to skip tests if OIDC test environment is not configured"""
165
+ import pytest
166
+
167
+ config = OidcTestConfig.from_environment()
168
+ return pytest.mark.skipif(
169
+ config is None,
170
+ reason="OIDC test environment not configured. Set OIDC_TEST_ISSUER, OIDC_TEST_CLIENT_ID, OIDC_TEST_CLIENT_SECRET, OIDC_TEST_USERNAME, OIDC_TEST_PASSWORD",
171
+ )
172
+
173
+
174
+ # Global test helper instance (lazy loaded)
175
+ _test_helper = None
176
+
177
+
178
+ def get_oidc_test_helper() -> Optional[OidcTestHelper]:
179
+ """Get global OIDC test helper instance"""
180
+ global _test_helper
181
+ if _test_helper is None:
182
+ config = OidcTestConfig.from_environment()
183
+ if config:
184
+ _test_helper = OidcTestHelper(config)
185
+ return _test_helper
186
+
187
+
188
+ def parse_cached_token(env_token: str) -> Optional[Dict[str, Any]]:
189
+ """
190
+ Parse and validate a base64-encoded token from environment variable.
191
+
192
+ Args:
193
+ env_token: Base64-encoded JSON token data from environment variable
194
+
195
+ Returns:
196
+ Parsed token data dict if valid, None if invalid or expired
197
+ """
198
+ try:
199
+ import base64
200
+
201
+ token_json = base64.b64decode(env_token.encode()).decode()
202
+ token_data = json.loads(token_json)
203
+ return token_data
204
+ except Exception as e:
205
+ logging.getLogger(__name__).warning(f"Failed to parse cached token: {e}")
206
+ return None
207
+
208
+
209
+ def is_token_valid(token_data: Dict[str, Any], buffer_seconds: int = 30) -> bool:
210
+ """
211
+ Check if token data is valid and not expired.
212
+
213
+ Args:
214
+ token_data: Dictionary containing token information
215
+ buffer_seconds: Safety buffer before expiration (default 30 seconds)
216
+
217
+ Returns:
218
+ True if token is valid and not expired, False otherwise
219
+ """
220
+ if not token_data:
221
+ return False
222
+
223
+ access_token = token_data.get("access_token")
224
+ expires_at = token_data.get("expires_at", 0)
225
+
226
+ if not access_token:
227
+ return False
228
+
229
+ current_time = time.time()
230
+ return current_time < expires_at - buffer_seconds
231
+
232
+
233
+ def encode_token_for_env(token_data: Dict[str, Any]) -> str:
234
+ """
235
+ Encode token data as base64 for storage in environment variables.
236
+
237
+ Args:
238
+ token_data: Dictionary containing token information
239
+
240
+ Returns:
241
+ Base64-encoded JSON string suitable for environment variable storage
242
+ """
243
+ import base64
244
+
245
+ token_json = json.dumps(token_data)
246
+ return base64.b64encode(token_json.encode()).decode()
247
+
248
+
249
+ def get_cached_token_from_env(
250
+ env_var_name: str = "FELDERA_PYTEST_OIDC_TOKEN",
251
+ ) -> Optional[Dict[str, Any]]:
252
+ """
253
+ Retrieve and validate cached token from environment variable.
254
+
255
+ Args:
256
+ env_var_name: Name of environment variable containing cached token
257
+
258
+ Returns:
259
+ Valid token data if available and not expired, None otherwise
260
+ """
261
+ import os
262
+
263
+ env_token = os.getenv(env_var_name)
264
+ if not env_token:
265
+ return None
266
+
267
+ token_data = parse_cached_token(env_token)
268
+ if token_data and is_token_valid(token_data):
269
+ return token_data
270
+
271
+ return None
272
+
273
+
274
+ def setup_token_cache() -> Optional[Dict[str, Any]]:
275
+ """
276
+ Set up OIDC token cache in environment variable if not already present.
277
+
278
+ This function:
279
+ 1. Checks if a valid token is already cached
280
+ 2. If not, fetches a new token
281
+ 3. Stores the token in environment variable for cross-process access
282
+
283
+ Used by both pytest hooks and demo runners to ensure consistent token caching.
284
+
285
+ Returns:
286
+ Token data if successfully cached, None if OIDC not configured
287
+ """
288
+ import os
289
+
290
+ # Check if token is already cached and still valid
291
+ cached_token = get_cached_token_from_env()
292
+ if cached_token:
293
+ print("🔐 AUTH: Using existing cached OIDC token")
294
+ return cached_token
295
+
296
+ # Fetch new token if needed
297
+ token_data = fetch_oidc_token()
298
+ if token_data:
299
+ # Store in environment variable for reuse by subsequent processes
300
+ token_b64 = encode_token_for_env(token_data)
301
+ os.environ["FELDERA_PYTEST_OIDC_TOKEN"] = token_b64
302
+ print("🔐 AUTH: Token cached in environment for cross-process access")
303
+ return token_data
304
+ else:
305
+ print("🔐 AUTH: No OIDC configuration found, using fallback authentication")
306
+ return None
307
+
308
+
309
+ def fetch_oidc_token() -> Optional[Dict[str, Any]]:
310
+ """
311
+ Fetch OIDC token using Resource Owner Password Grant flow.
312
+
313
+ This function is used by both pytest hooks and demo runners to ensure
314
+ consistent token fetching behavior across the entire test infrastructure.
315
+
316
+ Returns:
317
+ Dict containing access_token, expires_at, and cached_at if successful,
318
+ None if OIDC is not configured.
319
+ """
320
+ oidc_helper = get_oidc_test_helper()
321
+ if oidc_helper is None:
322
+ return None
323
+
324
+ print("🔐 AUTH: Fetching OIDC token")
325
+
326
+ try:
327
+ token_endpoint = oidc_helper.get_token_endpoint()
328
+ data = {
329
+ "grant_type": "password",
330
+ "username": oidc_helper.config.username,
331
+ "password": oidc_helper.config.password,
332
+ "client_id": oidc_helper.config.client_id,
333
+ "client_secret": oidc_helper.config.client_secret,
334
+ "scope": oidc_helper.config.scope,
335
+ "audience": "feldera-api",
336
+ }
337
+
338
+ headers = {
339
+ "Content-Type": "application/x-www-form-urlencoded",
340
+ "Accept": "application/json",
341
+ }
342
+
343
+ response = requests.post(token_endpoint, data=data, headers=headers, timeout=30)
344
+
345
+ if not response.ok:
346
+ print(f"🔐 AUTH: ❌ Token request FAILED: {response.status_code}")
347
+ raise Exception(
348
+ f"Token request failed: {response.status_code} - {response.text}"
349
+ )
350
+
351
+ token_response = response.json()
352
+ print("🔐 AUTH: ✅ Token request SUCCESS!")
353
+
354
+ access_token = token_response["access_token"]
355
+ expires_in = token_response.get("expires_in", 3600)
356
+ expires_at = time.time() + expires_in
357
+
358
+ return {
359
+ "access_token": access_token,
360
+ "expires_at": expires_at,
361
+ "cached_at": time.time(),
362
+ }
363
+
364
+ except Exception as e:
365
+ print(f"🔐 AUTH: CRITICAL FAILURE - Failed to fetch OIDC token: {e}")
366
+ raise RuntimeError(
367
+ f"OIDC authentication is configured but token retrieval failed: {e}"
368
+ ) from e
@@ -0,0 +1,163 @@
1
+ Metadata-Version: 2.4
2
+ Name: feldera
3
+ Version: 0.192.0
4
+ Summary: The feldera python client
5
+ Author-email: Feldera Team <dev@feldera.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://www.feldera.com
8
+ Project-URL: Documentation, https://docs.feldera.com/python
9
+ Project-URL: Repository, https://github.com/feldera/feldera
10
+ Project-URL: Issues, https://github.com/feldera/feldera/issues
11
+ Keywords: feldera,python
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Operating System :: OS Independent
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: requests
18
+ Requires-Dist: pandas>=2.1.2
19
+ Requires-Dist: typing-extensions
20
+ Requires-Dist: numpy>=2.2.4
21
+ Requires-Dist: pretty-errors
22
+ Requires-Dist: ruff>=0.6.9
23
+ Requires-Dist: PyJWT>=2.8.0
24
+
25
+ # Feldera Python SDK
26
+
27
+ The `feldera` Python package is the Python client for the Feldera HTTP API.
28
+
29
+ The Python SDK documentation is available at: https://docs.feldera.com/python
30
+
31
+ ## Getting started
32
+
33
+ ### Installation
34
+
35
+ ```bash
36
+ uv pip install feldera
37
+ ```
38
+
39
+ ### Example usage
40
+
41
+ The Python client interacts with the API server of the Feldera instance.
42
+
43
+ ```python
44
+ # File: example.py
45
+ from feldera import FelderaClient, PipelineBuilder, Pipeline
46
+
47
+ # Instantiate client
48
+ client = FelderaClient() # Default: http://localhost:8080 without authentication
49
+ # client = FelderaClient(url="https://localhost:8080", api_key="apikey:...", requests_verify="/path/to/tls.crt")
50
+
51
+ # (Re)create pipeline
52
+ name = "example"
53
+ sql = """
54
+ CREATE TABLE t1 (i1 INT) WITH ('materialized' = 'true');
55
+ CREATE MATERIALIZED VIEW v1 AS SELECT * FROM t1;
56
+ """
57
+ print("(Re)creating pipeline...")
58
+ pipeline = PipelineBuilder(client, name, sql).create_or_replace()
59
+ pipeline.start()
60
+ print(f"Pipeline status: {pipeline.status()}")
61
+ pipeline.pause()
62
+ print(f"Pipeline status: {pipeline.status()}")
63
+ pipeline.stop(force=True)
64
+
65
+ # Find existing pipeline
66
+ pipeline = Pipeline.get(name, client)
67
+ pipeline.start()
68
+ print(f"Pipeline status: {pipeline.status()}")
69
+ pipeline.stop(force=True)
70
+ pipeline.clear_storage()
71
+ ```
72
+
73
+ Run using:
74
+ ```bash
75
+ uv run python example.py
76
+ ```
77
+
78
+ ### Environment variables
79
+
80
+ Some default parameter values in the Python SDK can be overridden via environment variables.
81
+
82
+ **Environment variables for `FelderaClient(...)`**
83
+
84
+ ```bash
85
+ export FELDERA_HOST="https://localhost:8080" # Overrides default for `url`
86
+ export FELDERA_API_KEY="apikey:..." # Overrides default for `api_key`
87
+
88
+ # The following together override default for `requests_verify`
89
+ # export FELDERA_TLS_INSECURE="false" # If set to "1", "true" or "yes" (all case-insensitive), disables TLS certificate verification
90
+ # export FELDERA_HTTPS_TLS_CERT="/path/to/tls.crt" # Custom TLS certificate
91
+ ```
92
+
93
+ **Environment variables for `PipelineBuilder(...)`**
94
+
95
+ ```bash
96
+ export FELDERA_RUNTIME_VERSION="..." # Overrides default for `runtime_version`
97
+ ```
98
+
99
+ ## Development
100
+
101
+ Development assumes you have cloned the Feldera code repository.
102
+
103
+ ### Installation
104
+
105
+ ```bash
106
+ cd python
107
+ # Optional: create and activate virtual environment if you don't have one
108
+ uv venv
109
+ source .venv/bin/activate
110
+ # Install in editable mode
111
+ uv pip install -e .
112
+ ```
113
+
114
+ ### Formatting
115
+
116
+ Formatting requires the `ruff` package: `uv pip install ruff`
117
+
118
+ ```bash
119
+ cd python
120
+ ruff check
121
+ ruff format
122
+ ```
123
+
124
+ ### Tests
125
+
126
+ Running the test requires the `pytest` package: `uv pip install pytest`
127
+
128
+ ```bash
129
+ # All tests
130
+ cd python
131
+ uv run python -m pytest tests/
132
+
133
+ # Specific tests directory
134
+ uv run python -m pytest tests/platform/
135
+
136
+ # Specific test file
137
+ uv run python -m pytest tests/platform/test_pipeline_crud.py
138
+ ```
139
+
140
+ For further information about the tests, please see `tests/README.md`.
141
+
142
+ ### Documentation
143
+
144
+ Building documentation requires the `sphinx` package: `uv pip install sphinx`
145
+
146
+ ```bash
147
+ cd python/docs
148
+ sphinx-apidoc -o . ../feldera
149
+ make html
150
+ make clean # Cleanup afterwards
151
+ ```
152
+
153
+ ### Installation from GitHub
154
+
155
+ Latest `main` branch:
156
+ ```bash
157
+ uv pip install git+https://github.com/feldera/feldera#subdirectory=python
158
+ ```
159
+
160
+ Different branch (replace `BRANCH_NAME`):
161
+ ```bash
162
+ uv pip install git+https://github.com/feldera/feldera@BRANCH_NAME#subdirectory=python
163
+ ```
@@ -0,0 +1,26 @@
1
+ feldera/__init__.py,sha256=ynWeVeHQ0Rsocte8P8Tso1l9z50uTCojY5jJxmgmVeQ,398
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
+ feldera/runtime_config.py,sha256=w6rPkZyijca9jY1G8PKeqP8txXjnn5MPJYmM7B8iE3U,4602
9
+ feldera/stats.py,sha256=YeDQwE_CixTMb2DjBCgt5jTaJAZRsrHtG-3pYuuII-8,5256
10
+ feldera/testutils.py,sha256=_mfue_AZhedodNOdN_fNkFTBDiB_fqv8XuvvfkDPAIY,12343
11
+ feldera/testutils_oidc.py,sha256=hv0IQAcVOt4uysWW3iE-5p46ZGfL1X7Vt7PjRefkXz8,12552
12
+ feldera/rest/__init__.py,sha256=Eg-EKUU3RSTDcdxTR_7wNDnCly8VpXEzsZCQUmf-y2M,308
13
+ feldera/rest/_helpers.py,sha256=thq5FBb9bmkbzuyXbRzHI2SxUCwyIN4poHsQyw2Hzr8,1139
14
+ feldera/rest/_httprequests.py,sha256=-g9Luo8KwFNSb4tOxJTMTAosbUANqQmsLiuNNcrCyes,13760
15
+ feldera/rest/config.py,sha256=fTn8gMLzxKB3CJYkQ6HdDH_gDktda3oFaXpEHVVZdSA,1740
16
+ feldera/rest/errors.py,sha256=wKWwlL5WI3SVXC8rQTy3rS3wQ9Hjjn_EY7iRHXZFIVE,2341
17
+ feldera/rest/feldera_client.py,sha256=JMXmY4fKwcPMOUtucgJ4Du9msEOhmm975t38N2pjh5E,45760
18
+ feldera/rest/feldera_config.py,sha256=1pnGbLFMSLvp7Qh_OlPLALSKCSHIktNWKvx6gYU00U4,1374
19
+ feldera/rest/pipeline.py,sha256=Q6TM44a7-SYRhLWbBGQMriCOcMRDk4WVKjfxd8vumys,3696
20
+ feldera/rest/sql_table.py,sha256=qrw-YwMzx5T81zDefNO1KOx7EyypFz1vPwGBzSUB7kc,652
21
+ feldera/rest/sql_view.py,sha256=hN12mPM0mvwLCIPYywpb12s9Hd2Ws31IlTMXPriMisw,644
22
+ feldera/tests/test_datafusionize.py,sha256=NGriTaTWf_WnXFud1wmpFwLFa_-XGjfCh6La3dWc3QA,1337
23
+ feldera-0.192.0.dist-info/METADATA,sha256=qXUiHPr6lgByIWQN0srw1WWt3NQxJmbZAglflvYAomo,4122
24
+ feldera-0.192.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ feldera-0.192.0.dist-info/top_level.txt,sha256=fB6yTqrQiO6RCbY1xP2T_mpPoTjDFtJvkJJodiee7d0,8
26
+ feldera-0.192.0.dist-info/RECORD,,
@@ -1,102 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: feldera
3
- Version: 0.131.0
4
- Summary: The feldera python client
5
- Author-email: Feldera Team <dev@feldera.com>
6
- License: MIT
7
- Project-URL: Homepage, https://www.feldera.com
8
- Project-URL: Documentation, https://docs.feldera.com/python
9
- Project-URL: Repository, https://github.com/feldera/feldera
10
- Project-URL: Issues, https://github.com/feldera/feldera/issues
11
- Keywords: feldera,python
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Programming Language :: Python :: 3.10
14
- Classifier: Operating System :: OS Independent
15
- Requires-Python: >=3.10
16
- Description-Content-Type: text/markdown
17
- Requires-Dist: requests
18
- Requires-Dist: pandas>=2.1.2
19
- Requires-Dist: typing-extensions
20
- Requires-Dist: numpy>=2.2.4
21
- Requires-Dist: pretty-errors
22
- Requires-Dist: ruff>=0.6.9
23
-
24
- # Feldera Python SDK
25
-
26
- Feldera Python is the Feldera SDK for Python developers.
27
-
28
- ## Installation
29
-
30
- ```bash
31
- uv pip install feldera
32
- ```
33
-
34
- ### Installing from Github
35
-
36
- ```bash
37
- uv pip install git+https://github.com/feldera/feldera#subdirectory=python
38
- ```
39
-
40
- Similarly, to install from a specific branch:
41
-
42
- ```bash
43
- uv pip install git+https://github.com/feldera/feldera@{BRANCH_NAME}#subdirectory=python
44
- ```
45
-
46
- Replace `{BRANCH_NAME}` with the name of the branch you want to install from.
47
-
48
- ### Installing from Local Directory
49
-
50
- If you have cloned the Feldera repo, you can install the python SDK as follows:
51
-
52
- ```bash
53
- # the Feldera Python SDK is present inside the python/ directory
54
- cd python
55
- # If you don't have a virtual environment, create one
56
- uv venv
57
- source .venv/activate
58
- # Install the SDK in editable mode
59
- uv pip install .
60
- ```
61
-
62
- You also have to install the `pytest` module:
63
-
64
- ```bash
65
- python3 -m pip install pytest
66
- ```
67
-
68
- ## Documentation
69
-
70
- The Python SDK documentation is available at
71
- [Feldera Python SDK Docs](https://docs.feldera.com/python).
72
-
73
- To build the html documentation run:
74
-
75
- Ensure that you have sphinx installed. If not, install it using `uv pip install sphinx`.
76
-
77
- Then run the following commands:
78
-
79
- ```bash
80
- cd docs
81
- sphinx-apidoc -o . ../feldera
82
- make html
83
- ```
84
-
85
- To clean the build, run `make clean`.
86
-
87
- ## Linting and formatting
88
-
89
- Use [Ruff] to run the lint checks that will be executed by the
90
- precommit hook when a PR is submitted:
91
-
92
- ```bash
93
- ruff check python/
94
- ```
95
-
96
- To reformat the code in the same way as the precommit hook:
97
-
98
- ```bash
99
- ruff format
100
- ```
101
-
102
- [Ruff]: https://github.com/astral-sh/ruff
@@ -1,23 +0,0 @@
1
- feldera/__init__.py,sha256=EiY3bTj_mnfNhCGrZo6J__brfovIJ-YYAdy77PyaEoo,378
2
- feldera/_callback_runner.py,sha256=-2hYG70cEkvz4BiOfUTARaH-2Rlv0Qcz-ilvodgyK10,4797
3
- feldera/_helpers.py,sha256=rN0WuGSCCQlXWFMimZUQrgs-LJAfUo074d79sLElncQ,3023
4
- feldera/enums.py,sha256=MTHBojVANsdRnjbrzCyIOniDIUaH8nTYRfxB7QvajEE,9570
5
- feldera/output_handler.py,sha256=64J3ljhOaKIhxdjOKYi-BUz_HnMwROfmN8eE-btYygU,1930
6
- feldera/pipeline.py,sha256=yhUGKbagA--_D-vB8k8Mm9rZFhc7NbcpXh1OK8zPmBo,41742
7
- feldera/pipeline_builder.py,sha256=a750hp5SgTmlyrobTHFh1fTaK9Ed4A5qnXaYRctRM-8,4250
8
- feldera/runtime_config.py,sha256=MuYJPd5G_hnu_eDz4ge4BfYvSBSOvOEtv4NYh5sEwqU,4452
9
- feldera/stats.py,sha256=1qDlWhI-ORx3FktxH3b93mXWwtCOb4XuP0iJePHJTrE,5030
10
- feldera/rest/__init__.py,sha256=Eg-EKUU3RSTDcdxTR_7wNDnCly8VpXEzsZCQUmf-y2M,308
11
- feldera/rest/_helpers.py,sha256=q7jWInKp9IiIli8N5o31lDG3hNUbcsJqufZXYHG04ps,222
12
- feldera/rest/_httprequests.py,sha256=WbMeFodRV0ZHjA4LhcsbGUtVO-j8HQ98SRfgogOFA8A,8074
13
- feldera/rest/config.py,sha256=ag8Vh1Ul0wmo--3kvfwL_vUfu4CHESnn07xUuIJRbv4,1213
14
- feldera/rest/errors.py,sha256=b4i2JjrbSmej7jdko_FL8UeXklLKenSipwMT80jowaM,1720
15
- feldera/rest/feldera_client.py,sha256=Crt0WHBucC4YiRZi2M0GKQ1isdMjCm_Y-_fElOjoK3o,37095
16
- feldera/rest/feldera_config.py,sha256=1pnGbLFMSLvp7Qh_OlPLALSKCSHIktNWKvx6gYU00U4,1374
17
- feldera/rest/pipeline.py,sha256=Rmbflbwjvd86iZ5aSJ5b_bTSs6vgvEKQFwMZDtm0nxE,2835
18
- feldera/rest/sql_table.py,sha256=qrw-YwMzx5T81zDefNO1KOx7EyypFz1vPwGBzSUB7kc,652
19
- feldera/rest/sql_view.py,sha256=hN12mPM0mvwLCIPYywpb12s9Hd2Ws31IlTMXPriMisw,644
20
- feldera-0.131.0.dist-info/METADATA,sha256=wqRKF-g1N0ZL6INiAWfBxw5BVyZzBzcroTzoUXSAaN8,2368
21
- feldera-0.131.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
- feldera-0.131.0.dist-info/top_level.txt,sha256=fB6yTqrQiO6RCbY1xP2T_mpPoTjDFtJvkJJodiee7d0,8
23
- feldera-0.131.0.dist-info/RECORD,,