flopscope-server 0.4.2__tar.gz → 0.4.3__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.
Files changed (23) hide show
  1. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/PKG-INFO +2 -2
  2. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/pyproject.toml +2 -2
  3. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/src/flopscope_server/__init__.py +1 -1
  4. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/src/flopscope_server/_request_handler.py +40 -9
  5. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/.gitignore +0 -0
  6. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/README.md +0 -0
  7. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/src/flopscope_server/__main__.py +0 -0
  8. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/src/flopscope_server/_array_store.py +0 -0
  9. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/src/flopscope_server/_comms_tracker.py +0 -0
  10. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/src/flopscope_server/_protocol.py +0 -0
  11. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/src/flopscope_server/_server.py +0 -0
  12. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/src/flopscope_server/_session.py +0 -0
  13. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_array_store.py +0 -0
  14. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_bugfixes_round2.py +0 -0
  15. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_bugfixes_round3.py +0 -0
  16. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_comms_tracker.py +0 -0
  17. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_new_types.py +0 -0
  18. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_protocol.py +0 -0
  19. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_request_handler.py +0 -0
  20. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_server.py +0 -0
  21. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_session.py +0 -0
  22. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/tests/test_version_handshake.py +0 -0
  23. {flopscope_server-0.4.2 → flopscope_server-0.4.3}/uv.lock +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flopscope-server
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: Backend server for flopscope client-server architecture
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.10
7
- Requires-Dist: flopscope==0.4.2
7
+ Requires-Dist: flopscope==0.4.3
8
8
  Requires-Dist: msgpack>=1.0.0
9
9
  Requires-Dist: numpy<2.5.0,>=2.0.0
10
10
  Requires-Dist: pyzmq>=26.0.0
@@ -4,13 +4,13 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "flopscope-server"
7
- version = "0.4.2"
7
+ version = "0.4.3"
8
8
  description = "Backend server for flopscope client-server architecture"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  license = "MIT"
12
12
  dependencies = [
13
- "flopscope==0.4.2",
13
+ "flopscope==0.4.3",
14
14
  "numpy>=2.0.0,<2.5.0",
15
15
  "pyzmq>=26.0.0",
16
16
  "msgpack>=1.0.0",
@@ -1,3 +1,3 @@
1
1
  """Flopscope backend server — executes numpy operations on behalf of remote clients."""
2
2
 
3
- __version__ = "0.4.2"
3
+ __version__ = "0.4.3"
@@ -49,6 +49,28 @@ def _make_serializable(obj):
49
49
  return obj
50
50
 
51
51
 
52
+ _MSGPACK_SCALARS = (type(None), bool, int, float, str, bytes)
53
+
54
+
55
+ def _is_msgpack_native(obj) -> bool:
56
+ """True if *obj* is composed only of msgpack-encodable Python types.
57
+
58
+ ``_make_serializable`` flattens numpy types but passes unknown objects
59
+ through unchanged; this distinguishes a genuinely-encodable result from one
60
+ that would only fail later inside ``msgpack.packb``.
61
+ """
62
+ if isinstance(obj, _MSGPACK_SCALARS):
63
+ return True
64
+ if isinstance(obj, (list, tuple)):
65
+ return all(_is_msgpack_native(item) for item in obj)
66
+ if isinstance(obj, dict):
67
+ return all(
68
+ isinstance(k, (str, bytes, int)) and _is_msgpack_native(v)
69
+ for k, v in obj.items()
70
+ )
71
+ return False
72
+
73
+
52
74
  #: Maximum allowed array size in bytes (configurable via environment variable).
53
75
  MAX_ARRAY_BYTES = int(os.environ.get("FLOPSCOPE_MAX_ARRAY_BYTES", 100 * 1024 * 1024))
54
76
 
@@ -113,6 +135,12 @@ class RequestHandler:
113
135
  "error_type": "UnsupportedFunctionError",
114
136
  "message": str(e),
115
137
  }
138
+ except flops.UnsupportedReturnType as e:
139
+ return {
140
+ "status": "error",
141
+ "error_type": "UnsupportedReturnType",
142
+ "message": str(e),
143
+ }
116
144
  except (ValueError, TypeError) as e:
117
145
  return {
118
146
  "status": "error",
@@ -420,16 +448,19 @@ class RequestHandler:
420
448
  handle = self._session.store_generator(result)
421
449
  return {"status": "ok", "result": {"gen_id": handle}, "budget": budget}
422
450
 
423
- # Fallback: try to make it serializable
424
- try:
425
- serializable = _make_serializable(result)
451
+ # Fallback: flatten nested numpy structures to JSON-safe values. If the
452
+ # result still isn't msgpack-native, fail loudly + attributably rather
453
+ # than silently str()-degrading (which previously surfaced downstream as
454
+ # an opaque "failed to serialize response" error). The registry-driven
455
+ # conformance test (tests/test_registry_conformance.py) catches any op
456
+ # whose return type lands here.
457
+ serializable = _make_serializable(result)
458
+ if _is_msgpack_native(serializable):
426
459
  return {"status": "ok", "result": {"value": serializable}, "budget": budget}
427
- except Exception:
428
- return {
429
- "status": "ok",
430
- "result": {"value": str(result), "dtype": "str"},
431
- "budget": budget,
432
- }
460
+ raise flops.UnsupportedReturnType(
461
+ f"{type(result).__name__} is not serializable across the "
462
+ f"client/server boundary"
463
+ )
433
464
 
434
465
 
435
466
  # ---------------------------------------------------------------------------