vantiqservicesdk 0.2.2__tar.gz → 0.3.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.
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vantiqservicesdk
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: SDK for building Vantiq service connectors in Python
5
5
  Author-email: Vantiq <sfitts@vantiq.com>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/Vantiq/vantiq-service-connectors
8
8
  Classifier: Development Status :: 4 - Beta
9
9
  Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3.9
11
10
  Classifier: Programming Language :: Python :: 3.10
12
11
  Classifier: Programming Language :: Python :: 3.11
13
12
  Classifier: Programming Language :: Python :: 3.12
14
- Requires-Python: >=3.9
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Requires-Python: >=3.10
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
17
  Requires-Dist: fastapi
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vantiqservicesdk"
7
- version = "0.2.2"
7
+ version = "0.3.0"
8
8
  description = "SDK for building Vantiq service connectors in Python"
9
9
  authors = [
10
10
  { name = "Vantiq", email = "sfitts@vantiq.com" },
@@ -12,15 +12,15 @@ authors = [
12
12
  classifiers = [
13
13
  "Development Status :: 4 - Beta",
14
14
  "License :: OSI Approved :: MIT License",
15
- "Programming Language :: Python :: 3.9",
16
15
  "Programming Language :: Python :: 3.10",
17
16
  "Programming Language :: Python :: 3.11",
18
17
  "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
19
  ]
20
20
  dynamic = [
21
21
  "readme",
22
22
  ]
23
- requires-python = ">=3.9"
23
+ requires-python = ">=3.10"
24
24
  dependencies = [
25
25
  "fastapi",
26
26
  "uvicorn[standard]",
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vantiqservicesdk
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: SDK for building Vantiq service connectors in Python
5
5
  Author-email: Vantiq <sfitts@vantiq.com>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/Vantiq/vantiq-service-connectors
8
8
  Classifier: Development Status :: 4 - Beta
9
9
  Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3.9
11
10
  Classifier: Programming Language :: Python :: 3.10
12
11
  Classifier: Programming Language :: Python :: 3.11
13
12
  Classifier: Programming Language :: Python :: 3.12
14
- Requires-Python: >=3.9
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Requires-Python: >=3.10
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
17
  Requires-Dist: fastapi
@@ -223,7 +223,18 @@ class BaseVantiqServiceConnector:
223
223
  async for data in result:
224
224
  response = {"requestId": request.get("requestId"), "result": data}
225
225
  encoded_response = self.encode_response(response)
226
- self._check_message_size(encoded_response)
226
+ max_size = self._max_message_size
227
+ if 0 < max_size < len(encoded_response):
228
+ # Envelope overhead without re-serializing data: encode the wrapper with a null result.
229
+ overhead = len(self.encode_response({**response, "result": None})) - len(b"null")
230
+ reduced = self.reduce_oversized_result(data, max_size - overhead)
231
+ if reduced is not None:
232
+ # service trimmed it; re-encode once
233
+ response["result"] = reduced
234
+ encoded_response = self.encode_response(response)
235
+
236
+ # raises if still over, or service declined
237
+ self._check_message_size(encoded_response)
227
238
  await websocket.send({"type": "websocket.send", "bytes": encoded_response})
228
239
 
229
240
  # Initialize the final response
@@ -251,22 +262,34 @@ class BaseVantiqServiceConnector:
251
262
  if response is None:
252
263
  return b''
253
264
 
254
- # Remove the result (if any) and add the error message
265
+ # Remove the result (if any) and add the error message. An error response always terminates the
266
+ # request, so mark it as the final response -- this matters for errors raised mid-stream, where
267
+ # the in-progress response does not yet carry isEOF.
255
268
  error_str = str(e)
256
269
  response.pop("result", None)
257
270
  if isinstance(e, KeyError):
258
271
  error_str = f"Failed to find expected dict key: {error_str}"
259
272
  response["errorMsg"] = error_str
273
+ response["isEOF"] = True
260
274
 
261
275
  # Serialize to JSON and encode (duplicated here to record JSON serialization errors)
262
276
  return json.dumps(response, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
263
-
277
+
278
+ @property
279
+ def _max_message_size(self):
280
+ config = self._client_config or {}
281
+ return config.get("maxMessageSize", -1)
282
+
264
283
  def _check_message_size(self, encoded_message: bytes) -> None:
265
284
  config = self._client_config or {}
266
285
  max_size = config.get("maxMessageSize", -1)
267
286
  if (max_size > 0) and (len(encoded_message) > max_size):
268
287
  raise Exception(f"Message size {len(encoded_message)} exceeds maximum size {max_size}")
269
288
 
289
+ def reduce_oversized_result(self, result: Any, max_size: int) -> Any:
290
+ # Return a trimmed result to send, or None to make no change (the caller then raises).
291
+ return None
292
+
270
293
  def encode_response(self, response: dict) -> bytes:
271
294
  text = json.dumps(response, separators=(",", ":"), ensure_ascii=False,
272
295
  default=lambda obj: self.to_json(obj))