vortexpy 4.3.6__tar.gz → 6.0.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.
- vortexpy-6.0.0/LICENSE +22 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/PKG-INFO +10 -7
- {vortexpy-4.3.6 → vortexpy-6.0.0}/README.md +9 -6
- {vortexpy-4.3.6 → vortexpy-6.0.0}/pyproject.toml +1 -15
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/DeferUtil.py +2 -25
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/DeferUtil_test.py +0 -58
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/Jsonable.py +4 -22
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PayloadEndpoint.py +31 -39
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PayloadEndpointTest.py +3 -2
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PayloadEnvelope.py +9 -9
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PayloadIO.py +11 -13
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PayloadPriority.py +1 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PayloadResponse.py +3 -8
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/SerialiseUtil.py +6 -85
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/Tuple.py +9 -50
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/TuplePolymorphicTupleTypeFieldArgTest.py +1 -4
- vortexpy-4.3.6/vortex/TupleDocumentConverter.py → vortexpy-6.0.0/vortex/TupleRestful.py +89 -288
- vortexpy-6.0.0/vortex/TupleRestfulTest.py +267 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexAccessControlContextABC.py +47 -13
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexAuthenticatorABC.py +6 -1
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexFactory.py +1 -9
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexPayloadProtocol.py +4 -9
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexPermission.py +0 -1
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexPermissionError.py +0 -1
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexServer.py +20 -3
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexServerConnection.py +2 -2
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexServerHttpResource.py +1 -10
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexServerWebsocket.py +7 -27
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexSession.py +65 -14
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexTcpMemoryLeakPayloadTest.py +24 -24
- vortexpy-6.0.0/vortex/VortexUserDetailsABC.py +40 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexUtil.py +0 -2
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexWritePushProducer.py +8 -9
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexWritePushProducer_test.py +8 -12
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/__init__.py +1 -1
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/data_loader/TupleDataLiveLockManager.py +147 -65
- vortexpy-6.0.0/vortex/data_loader/TupleDataLiveLockManager_test.py +336 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/data_loader/TupleDataLoader.py +16 -28
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/data_loader/TupleDataLoaderDelegate.py +4 -14
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/data_loader/TupleDataLoaderTuples.py +13 -9
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/event_bus/TupleChangeEventBus.py +8 -7
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleActionProcessor.py +87 -103
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleActionProcessorProxy.py +13 -13
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleActionProcessorTestHandler.py +3 -3
- vortexpy-6.0.0/vortex/handler/TupleActionProcessor_test.py +147 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleDataAccessGranterABC.py +4 -4
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleDataObservableCache.py +7 -7
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleDataObservableHandler.py +100 -107
- vortexpy-6.0.0/vortex/handler/TupleDataObservableHandler_test.py +280 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleDataObservableProxyHandler.py +78 -83
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleDataObserverClient.py +6 -20
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleDataProviderABC.py +1 -3
- vortexpy-6.0.0/vortex/restful/RestfulHttpClientTest.py +68 -0
- vortexpy-6.0.0/vortex/restful/RestfulResourceTest.py +108 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/rpc/RPC.py +44 -73
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/sqla_orm/OrmCrudHandler.py +34 -8
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/storage/TupleStorageSqlite.py +3 -3
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/tuple_json_schema/tuple_json_schema_builder.py +1 -3
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/tuple_json_schema/tuple_json_schema_test.py +2 -4
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/twisted_runtime_metrics.py +48 -92
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/twisted_runtime_metrics_test.py +7 -7
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortexpy.egg-info/PKG-INFO +10 -7
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortexpy.egg-info/SOURCES.txt +7 -25
- vortexpy-6.0.0/vortexpy.egg-info/top_level.txt +1 -0
- vortexpy-4.3.6/example/TwistedDeferredTimeout.py +0 -50
- vortexpy-4.3.6/example/__init__.py +0 -1
- vortexpy-4.3.6/example/run_http_upgraded_websocket_ping_client.py +0 -68
- vortexpy-4.3.6/example/run_http_upgraded_websocket_ping_server.py +0 -71
- vortexpy-4.3.6/example/run_http_upgraded_websocket_rpc_test_client.py +0 -67
- vortexpy-4.3.6/example/run_http_upgraded_websocket_rpc_test_server.py +0 -45
- vortexpy-4.3.6/example/run_websocket_rpc_test_client.py +0 -64
- vortexpy-4.3.6/example/run_websocket_rpc_test_server.py +0 -29
- vortexpy-4.3.6/example/setup_example_logging.py +0 -44
- vortexpy-4.3.6/example/store_and_load_json.py +0 -68
- vortexpy-4.3.6/vortex/PayloadResponse_test.py +0 -42
- vortexpy-4.3.6/vortex/SerialiseUtil_test.py +0 -186
- vortexpy-4.3.6/vortex/TupleBson.py +0 -203
- vortexpy-4.3.6/vortex/TupleBson_test.py +0 -300
- vortexpy-4.3.6/vortex/TupleRestful.py +0 -139
- vortexpy-4.3.6/vortex/TupleRestful_test.py +0 -209
- vortexpy-4.3.6/vortex/VortexServerWebsocket_test.py +0 -22
- vortexpy-4.3.6/vortex/VortexServer_test.py +0 -134
- vortexpy-4.3.6/vortex/handler/TupleDataObservableCache_test.py +0 -28
- vortexpy-4.3.6/vortex/handler/TupleDataObservableHandler_test.py +0 -392
- vortexpy-4.3.6/vortex/handler/TupleDataObservableProxyHandler_test.py +0 -214
- vortexpy-4.3.6/vortex/payload_many_tuples_benchmark_test.py +0 -71
- vortexpy-4.3.6/vortex/restful/restful_http_client_test.py +0 -73
- vortexpy-4.3.6/vortex/restful/restful_resource_test.py +0 -76
- vortexpy-4.3.6/vortex/rpc/RPC_test.py +0 -114
- vortexpy-4.3.6/vortex/tuple_test_fixtures.py +0 -206
- vortexpy-4.3.6/vortexpy.egg-info/top_level.txt +0 -2
- {vortexpy-4.3.6 → vortexpy-6.0.0}/setup.cfg +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/DataWrapTuple.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/MtlsAuthorizedClientRegistry.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/MtlsAuthorizedClientRegistry_test.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/MtlsServerSslOptions.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/Payload.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PayloadFilterKeys.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PayloadResponseTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PayloadTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/PerformTestActionTuple.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/TestTuple.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/TupleAction.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/TupleDataForTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/TuplePerfTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/TupleSelector.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/TupleTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexABC.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexClientHttp.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexClientHttpTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexClientTcp.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexClientWebsocketFactory.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexConnectionABC.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexEndpointPermission.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexFactory_test.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexServerConnection_test.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexServerTcp.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexSession_test.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexTcpMemoryLeakRawTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/VortexTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/data_loader/TupleDataLoaderTupleABC.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/data_loader/__init__.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/event_bus/TupleChangeEventABC.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/event_bus/TupleChangeEventBusObserverABC.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/event_bus/__init__.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleActionProcessor_shutdown_test.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleActionPushOffline.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleActionPushOffline_test.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleDataActionClient.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/TupleDataObservableTestHandler.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/VortexJSTupleLoaderTestHandler.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/handler/__init__.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/mypy_plugin.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/py.typed +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/restful/GzippedDataHttpClient.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/restful/GzippedDataHttpClientTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/restful/GzippedPayloadHttpClient.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/restful/RestfulHttpClient.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/restful/RestfulResource.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/restful/__init__.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/rpc/RPCTest.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/rpc/__init__.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/sqla_orm/TupleProviderForDb.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/sqla_orm/VortexTupleJson.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/sqla_orm/__init__.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/storage/TupleActionStorageSqlite.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/storage/__init__.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/tuple_json_schema/__init__.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/tuple_json_schema/constants.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/tuple_json_schema/json_schema_node_tuple.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortex/tuple_json_schema/tuple_json_schema_test_tuples.py +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortexpy.egg-info/dependency_links.txt +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortexpy.egg-info/entry_points.txt +0 -0
- {vortexpy-4.3.6 → vortexpy-6.0.0}/vortexpy.egg-info/requires.txt +0 -0
vortexpy-6.0.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016-2026 Flying Ion Pty Ltd
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vortexpy
|
|
3
|
-
Version:
|
|
3
|
+
Version: 6.0.0
|
|
4
4
|
Summary: Flying Ion's observable, routable, data serialisation and transport code.
|
|
5
5
|
Author-email: Flying Ion Pty Ltd <contact@flyingion.com>
|
|
6
6
|
License: MIT
|
|
@@ -32,17 +32,20 @@ Requires-Dist: txhttputil>=1.2.0
|
|
|
32
32
|
Flying Ion's observable, routable, data serialisation and transport code.
|
|
33
33
|
|
|
34
34
|
See [README_PERMISSIONS.md](README_PERMISSIONS.md) for the two-level permission
|
|
35
|
-
system (endpoint guards + access control context) introduced in
|
|
36
|
-
|
|
37
|
-
**Tuple and Payload tutorials:** [docs/README.md](docs/README.md) (simple → full features, encode/decode, threaded decode).
|
|
35
|
+
system (endpoint guards + access control context) introduced in v6.0.
|
|
38
36
|
|
|
39
37
|
Why PY at the end? To be consistent with VortexJS, which is the Browser side package.
|
|
40
38
|
See https://gitlab.com/flyingion/vortexjs
|
|
41
39
|
|
|
42
40
|
Requirements:
|
|
43
|
-
* Python 3.
|
|
44
|
-
* Twisted
|
|
45
|
-
* SQLAlchemy
|
|
41
|
+
* Python 3.12 (development target)
|
|
42
|
+
* Twisted (autobahn / txwebsocket)
|
|
43
|
+
* SQLAlchemy >= 2.0
|
|
44
|
+
|
|
45
|
+
See `pyproject.toml` for the authoritative dependency list.
|
|
46
|
+
|
|
47
|
+
See [README_MIGRATION.md](README_MIGRATION.md) for breaking changes and
|
|
48
|
+
migration guides (4.4.0, 6.0.0).
|
|
46
49
|
|
|
47
50
|
The "vortex" is designed to transport "Payloads" from a web browser (VortexJS) to a
|
|
48
51
|
twisted web server (VortexPY). There is also a python client for python client to python server
|
|
@@ -3,17 +3,20 @@
|
|
|
3
3
|
Flying Ion's observable, routable, data serialisation and transport code.
|
|
4
4
|
|
|
5
5
|
See [README_PERMISSIONS.md](README_PERMISSIONS.md) for the two-level permission
|
|
6
|
-
system (endpoint guards + access control context) introduced in
|
|
7
|
-
|
|
8
|
-
**Tuple and Payload tutorials:** [docs/README.md](docs/README.md) (simple → full features, encode/decode, threaded decode).
|
|
6
|
+
system (endpoint guards + access control context) introduced in v6.0.
|
|
9
7
|
|
|
10
8
|
Why PY at the end? To be consistent with VortexJS, which is the Browser side package.
|
|
11
9
|
See https://gitlab.com/flyingion/vortexjs
|
|
12
10
|
|
|
13
11
|
Requirements:
|
|
14
|
-
* Python 3.
|
|
15
|
-
* Twisted
|
|
16
|
-
* SQLAlchemy
|
|
12
|
+
* Python 3.12 (development target)
|
|
13
|
+
* Twisted (autobahn / txwebsocket)
|
|
14
|
+
* SQLAlchemy >= 2.0
|
|
15
|
+
|
|
16
|
+
See `pyproject.toml` for the authoritative dependency list.
|
|
17
|
+
|
|
18
|
+
See [README_MIGRATION.md](README_MIGRATION.md) for breaking changes and
|
|
19
|
+
migration guides (4.4.0, 6.0.0).
|
|
17
20
|
|
|
18
21
|
The "vortex" is designed to transport "Payloads" from a web browser (VortexJS) to a
|
|
19
22
|
twisted web server (VortexPY). There is also a python client for python client to python server
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vortexpy"
|
|
7
|
-
version = "
|
|
7
|
+
version = "6.0.0"
|
|
8
8
|
license = {text = "MIT"}
|
|
9
9
|
authors = [{name = "Flying Ion Pty Ltd", email = "contact@flyingion.com"}]
|
|
10
10
|
description = "Flying Ion's observable, routable, data serialisation and transport code."
|
|
@@ -53,17 +53,3 @@ namespaces = false
|
|
|
53
53
|
|
|
54
54
|
[project.entry-points."mypy.plugins"]
|
|
55
55
|
vortex_defer = "vortex.mypy_plugin:plugin"
|
|
56
|
-
|
|
57
|
-
[tool.pytest.ini_options]
|
|
58
|
-
testpaths = ["vortex"]
|
|
59
|
-
python_files = ["*_test.py"]
|
|
60
|
-
python_functions = ["test*"]
|
|
61
|
-
norecursedirs = ["_trial_temp", "example", "old_fork"]
|
|
62
|
-
markers = [
|
|
63
|
-
"trial: legacy Twisted Trial *Test.py modules (not collected; run with trial CLI)",
|
|
64
|
-
"slow: large payload or timing benchmarks",
|
|
65
|
-
"integration: docker or multi-process integration suites under test-integration/",
|
|
66
|
-
]
|
|
67
|
-
|
|
68
|
-
[tool.taskipy.tasks]
|
|
69
|
-
test-integrations = "bash -c 'pytest test-integration/ -xvs -m integration'"
|
|
@@ -32,7 +32,6 @@ def callMethodLater(func):
|
|
|
32
32
|
def wrapper(*args, **kwargs):
|
|
33
33
|
return reactor.callLater(0, func, *args, **kwargs)
|
|
34
34
|
|
|
35
|
-
wrapper.__wrapped__ = func
|
|
36
35
|
return wrapper
|
|
37
36
|
|
|
38
37
|
|
|
@@ -47,7 +46,7 @@ def nonConcurrentMethod(method):
|
|
|
47
46
|
call.running = False
|
|
48
47
|
|
|
49
48
|
call.running = False
|
|
50
|
-
|
|
49
|
+
|
|
51
50
|
return call
|
|
52
51
|
|
|
53
52
|
|
|
@@ -61,7 +60,6 @@ def maybeDeferredWrap(funcToWrap):
|
|
|
61
60
|
def func(*args, **kwargs):
|
|
62
61
|
return maybeDeferred(funcToWrap, *args, **kwargs)
|
|
63
62
|
|
|
64
|
-
func.__wrapped__ = funcToWrap
|
|
65
63
|
return func
|
|
66
64
|
|
|
67
65
|
|
|
@@ -80,7 +78,6 @@ def ensureDeferredWrap(funcToWrap):
|
|
|
80
78
|
def func(*args, **kwargs):
|
|
81
79
|
return ensureDeferred(funcToWrap(*args, **kwargs))
|
|
82
80
|
|
|
83
|
-
func.__wrapped__ = funcToWrap
|
|
84
81
|
return func
|
|
85
82
|
|
|
86
83
|
|
|
@@ -143,7 +140,6 @@ def vortexInlineCallbacksLogAndConsumeFailure(loggerArg):
|
|
|
143
140
|
d.addErrback(vortexLogAndConsumeFailure, loggerArg)
|
|
144
141
|
return d
|
|
145
142
|
|
|
146
|
-
called.__wrapped__ = funcToWrap
|
|
147
143
|
return called
|
|
148
144
|
|
|
149
145
|
return wrapper
|
|
@@ -157,7 +153,6 @@ def deferToThreadWrapWithLogger(
|
|
|
157
153
|
loggerArg: logging.Logger,
|
|
158
154
|
consumeError: bool = False,
|
|
159
155
|
checkMainThread: bool = True,
|
|
160
|
-
logException: bool = True,
|
|
161
156
|
) -> Callable[[Callable[_P, _R]], Callable[_P, Deferred[_R]]]:
|
|
162
157
|
"""Defer To Thread Wrap With Logger
|
|
163
158
|
|
|
@@ -168,9 +163,6 @@ def deferToThreadWrapWithLogger(
|
|
|
168
163
|
:param checkMainThread: Don't use this parameter, it's only needed during reactor
|
|
169
164
|
startup when the reactors thread isn't properly set and the check
|
|
170
165
|
fails.
|
|
171
|
-
:param logException: When True, thread exceptions are logged at ERROR with a full
|
|
172
|
-
traceback. When False, the same events are logged at DEBUG with a
|
|
173
|
-
neutral message so log analysers are not triggered.
|
|
174
166
|
|
|
175
167
|
:return: A decorator that makes the wrapped callable return a Deferred.
|
|
176
168
|
|
|
@@ -238,26 +230,11 @@ def deferToThreadWrapWithLogger(
|
|
|
238
230
|
methodFrame,
|
|
239
231
|
)
|
|
240
232
|
|
|
241
|
-
def handleFailure(failure):
|
|
242
|
-
if logException:
|
|
243
|
-
return vortexLogFailure(
|
|
244
|
-
failure, loggerArg, consumeError=consumeError
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
loggerArg.debug(
|
|
248
|
-
"Threaded call failed in %s.%s: %s",
|
|
249
|
-
funcToWrap.__module__,
|
|
250
|
-
funcToWrap.__qualname__,
|
|
251
|
-
failure.getErrorMessage(),
|
|
252
|
-
)
|
|
253
|
-
return True if consumeError else failure
|
|
254
|
-
|
|
255
233
|
d: Deferred[_R] = deferToThread(timedFuncToRun, *args, **kwargs)
|
|
256
234
|
d.addCallback(checkForInlineCallbackYield)
|
|
257
|
-
d.addErrback(
|
|
235
|
+
d.addErrback(vortexLogFailure, loggerArg, consumeError=consumeError)
|
|
258
236
|
return d
|
|
259
237
|
|
|
260
|
-
func.__wrapped__ = funcToWrap
|
|
261
238
|
return func
|
|
262
239
|
|
|
263
240
|
return wrapper
|
|
@@ -84,61 +84,3 @@ async def testDeferToThreadWrapWithLoggerCapturesSlowCallFrame() -> None:
|
|
|
84
84
|
assert "twisted_runtime_metrics.py" not in snapshot.longestThreadedMethodFrame, (
|
|
85
85
|
"captured frame must skip metrics collector internals"
|
|
86
86
|
)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@deferToThreadWrapWithLogger(logger, logException=False)
|
|
90
|
-
def _deferUtilTestFailingWorkQuiet() -> str:
|
|
91
|
-
raise ValueError("expected quiet failure")
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
@deferToThreadWrapWithLogger(logger)
|
|
95
|
-
def _deferUtilTestFailingWorkLoud() -> str:
|
|
96
|
-
raise ValueError("expected loud failure")
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
@pytest.mark.twisted
|
|
100
|
-
@ensureDeferred
|
|
101
|
-
async def testDeferToThreadWrapWithLoggerLogExceptionFalseLogsDebug(
|
|
102
|
-
caplog: pytest.LogCaptureFixture,
|
|
103
|
-
) -> None:
|
|
104
|
-
with caplog.at_level(logging.DEBUG, logger=logger.name):
|
|
105
|
-
try:
|
|
106
|
-
await _deferUtilTestFailingWorkQuiet()
|
|
107
|
-
raise AssertionError("wrapped call must propagate the failure")
|
|
108
|
-
except ValueError:
|
|
109
|
-
pass
|
|
110
|
-
|
|
111
|
-
errorRecords = [r for r in caplog.records if r.levelno >= logging.ERROR]
|
|
112
|
-
assert errorRecords == [], (
|
|
113
|
-
"logException=False must not log thread failures at ERROR"
|
|
114
|
-
)
|
|
115
|
-
debugRecords = [
|
|
116
|
-
r
|
|
117
|
-
for r in caplog.records
|
|
118
|
-
if r.levelno == logging.DEBUG and "expected quiet failure" in r.message
|
|
119
|
-
]
|
|
120
|
-
assert len(debugRecords) == 1, (
|
|
121
|
-
"logException=False must log one neutral DEBUG record"
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
@pytest.mark.twisted
|
|
126
|
-
@ensureDeferred
|
|
127
|
-
async def testDeferToThreadWrapWithLoggerDefaultLogsError(
|
|
128
|
-
caplog: pytest.LogCaptureFixture,
|
|
129
|
-
) -> None:
|
|
130
|
-
with caplog.at_level(logging.DEBUG, logger=logger.name):
|
|
131
|
-
try:
|
|
132
|
-
await _deferUtilTestFailingWorkLoud()
|
|
133
|
-
raise AssertionError("wrapped call must propagate the failure")
|
|
134
|
-
except ValueError:
|
|
135
|
-
pass
|
|
136
|
-
|
|
137
|
-
errorRecords = [
|
|
138
|
-
r
|
|
139
|
-
for r in caplog.records
|
|
140
|
-
if r.levelno >= logging.ERROR and "expected loud failure" in r.getMessage()
|
|
141
|
-
]
|
|
142
|
-
assert errorRecords, (
|
|
143
|
-
"default logException=True must log thread failures at ERROR"
|
|
144
|
-
)
|
|
@@ -107,11 +107,9 @@ class Jsonable(object):
|
|
|
107
107
|
try:
|
|
108
108
|
valueType = V_NULL if value is None else toRapuiType(value)
|
|
109
109
|
except KeyError as e:
|
|
110
|
-
unsupportedType = e.args[0] if e.args else value.__class__
|
|
111
110
|
raise KeyError(
|
|
112
|
-
"%
|
|
113
|
-
|
|
114
|
-
) from e
|
|
111
|
+
"%s field name is %s, type is %s", e, name, value.__class__
|
|
112
|
+
)
|
|
115
113
|
|
|
116
114
|
# Payloads and Tuples
|
|
117
115
|
if self.__isRawJsonableField(name):
|
|
@@ -292,8 +290,6 @@ class Jsonable(object):
|
|
|
292
290
|
Returns and instance of this object populated with data from the json dict
|
|
293
291
|
"""
|
|
294
292
|
|
|
295
|
-
hints = utilTypeHintsForClass(type(self))
|
|
296
|
-
|
|
297
293
|
# Use the fromJsonField code to convert all the values
|
|
298
294
|
for name, value in list(jsonDict.items()):
|
|
299
295
|
if name.startswith("_"):
|
|
@@ -301,21 +297,7 @@ class Jsonable(object):
|
|
|
301
297
|
|
|
302
298
|
if self.__isRawJsonableField(name):
|
|
303
299
|
setattr(self, name, value)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
value = self.fromJsonField(value)
|
|
307
|
-
|
|
308
|
-
# Reconstruct enum members for fields annotated with an enum type.
|
|
309
|
-
# Serialisation emits the primitive value; the receiving class's
|
|
310
|
-
# annotation carries the enum class back into the member.
|
|
311
|
-
enumClass = utilEnumClassFromTypeHint(hints.get(name))
|
|
312
|
-
if (
|
|
313
|
-
enumClass is not None
|
|
314
|
-
and value is not None
|
|
315
|
-
and not isinstance(value, enumClass)
|
|
316
|
-
):
|
|
317
|
-
value = enumClass(value)
|
|
318
|
-
|
|
319
|
-
setattr(self, name, value)
|
|
300
|
+
else:
|
|
301
|
+
setattr(self, name, self.fromJsonField(value))
|
|
320
302
|
|
|
321
303
|
return self
|
|
@@ -22,32 +22,18 @@ from vortex.VortexAccessControlContextABC import (
|
|
|
22
22
|
NO_AUTH_ACCESS_CONTROL_CONTEXT,
|
|
23
23
|
VortexAccessControlContextABC,
|
|
24
24
|
)
|
|
25
|
-
from vortex.VortexEndpointPermission import
|
|
26
|
-
EndpointPermissionsType as PermissionsType,
|
|
27
|
-
)
|
|
25
|
+
from vortex.VortexEndpointPermission import EndpointPermissionsType as PermissionsType
|
|
28
26
|
from vortex.VortexSession import (
|
|
29
27
|
_callableLabel,
|
|
30
28
|
checkAccessControlContextSignature,
|
|
29
|
+
checkEndpointPermissionsSignature,
|
|
31
30
|
checkNoHttpSessionInSignature,
|
|
31
|
+
checkNoVortexSessionInSignature,
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
logger = logging.getLogger(__name__)
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
# TODO: typings needs to support keyword args before tbis will work.
|
|
38
|
-
# PayloadEndpointProcessCallable = Callable[
|
|
39
|
-
# [
|
|
40
|
-
# ...
|
|
41
|
-
# # PayloadEnvelope, # payloadEnvelope
|
|
42
|
-
# # str, # vortexUuid
|
|
43
|
-
# # str, # vortexName
|
|
44
|
-
# # Any, # vortexSession
|
|
45
|
-
# # SendVortexMsgResponseCallable # sendResponse
|
|
46
|
-
# ],
|
|
47
|
-
# Optional[Deferred] # Return
|
|
48
|
-
# ]
|
|
49
|
-
|
|
50
|
-
|
|
51
37
|
class PayloadEndpoint:
|
|
52
38
|
"""
|
|
53
39
|
The payload endpoint is responsible for matching payloads filters against
|
|
@@ -71,7 +57,6 @@ class PayloadEndpoint:
|
|
|
71
57
|
acceptOnlyFromVortex: Optional[Union[str, tuple]] = None,
|
|
72
58
|
ignoreFromVortex: Optional[Union[str, tuple]] = None,
|
|
73
59
|
requiredPermissions: Optional[PermissionsType] = None,
|
|
74
|
-
logProcessException: bool = True,
|
|
75
60
|
) -> None:
|
|
76
61
|
"""
|
|
77
62
|
:param filt: The filter to match against payloads
|
|
@@ -83,13 +68,8 @@ class PayloadEndpoint:
|
|
|
83
68
|
the caller's session must hold. Pass an empty frozenset to
|
|
84
69
|
explicitly declare "no permissions required". Omitting the
|
|
85
70
|
parameter (``None``) emits a deprecation warning.
|
|
86
|
-
:param logProcessException: When True, handler exceptions log at ERROR.
|
|
87
|
-
When False, the same events log at DEBUG with neutral wording.
|
|
88
71
|
"""
|
|
89
|
-
self._requiredPermissions: Optional[PermissionsType] =
|
|
90
|
-
requiredPermissions
|
|
91
|
-
)
|
|
92
|
-
self._logProcessException = logProcessException
|
|
72
|
+
self._requiredPermissions: Optional[PermissionsType] = requiredPermissions
|
|
93
73
|
|
|
94
74
|
if requiredPermissions is None:
|
|
95
75
|
logger.warning(self._NO_PERMISSIONS_WARNING, filt)
|
|
@@ -97,13 +77,18 @@ class PayloadEndpoint:
|
|
|
97
77
|
callableDesc = (
|
|
98
78
|
f"PayloadEndpoint filt={filt} callback={_callableLabel(callable_)}"
|
|
99
79
|
)
|
|
100
|
-
self._callableAcceptsAccessControlContext = (
|
|
101
|
-
|
|
80
|
+
self._callableAcceptsAccessControlContext = checkAccessControlContextSignature(
|
|
81
|
+
callable_,
|
|
82
|
+
callableDescription=callableDesc,
|
|
83
|
+
)
|
|
84
|
+
self._callableAcceptsEndpointPermissions = (
|
|
85
|
+
checkEndpointPermissionsSignature(
|
|
102
86
|
callable_,
|
|
103
87
|
callableDescription=callableDesc,
|
|
104
88
|
)
|
|
105
89
|
)
|
|
106
90
|
checkNoHttpSessionInSignature(callable_, callableDesc)
|
|
91
|
+
checkNoVortexSessionInSignature(callable_, callableDesc)
|
|
107
92
|
|
|
108
93
|
self._acceptOnlyFromVortex = acceptOnlyFromVortex
|
|
109
94
|
if isinstance(self._acceptOnlyFromVortex, str):
|
|
@@ -178,10 +163,7 @@ class PayloadEndpoint:
|
|
|
178
163
|
return False
|
|
179
164
|
|
|
180
165
|
# Filter for the backend vortexes.
|
|
181
|
-
if
|
|
182
|
-
self._acceptOnlyFromVortex
|
|
183
|
-
and vortexName not in self._acceptOnlyFromVortex
|
|
184
|
-
):
|
|
166
|
+
if self._acceptOnlyFromVortex and vortexName not in self._acceptOnlyFromVortex:
|
|
185
167
|
return False
|
|
186
168
|
|
|
187
169
|
def removeUnhashable(filt):
|
|
@@ -225,14 +207,13 @@ class PayloadEndpoint:
|
|
|
225
207
|
if not self.check(payloadEnvelope, vortexName):
|
|
226
208
|
return
|
|
227
209
|
|
|
228
|
-
if self.PERMITTER and not self.PERMITTER.check(
|
|
229
|
-
payloadEnvelope, vortexSession
|
|
230
|
-
):
|
|
210
|
+
if self.PERMITTER and not self.PERMITTER.check(payloadEnvelope, vortexSession):
|
|
231
211
|
logger.debug("Permission failed for %s", payloadEnvelope.filt)
|
|
232
212
|
return
|
|
233
213
|
|
|
234
214
|
# Level 1: Endpoint permission check
|
|
235
215
|
auth = VortexFactory.getAuthenticator()
|
|
216
|
+
endpointPermissions = None
|
|
236
217
|
if self._requiredPermissions:
|
|
237
218
|
if not auth:
|
|
238
219
|
logger.error(
|
|
@@ -259,16 +240,26 @@ class PayloadEndpoint:
|
|
|
259
240
|
)
|
|
260
241
|
return
|
|
261
242
|
|
|
243
|
+
# Level 1 injection: when the callable declares endpointPermissions,
|
|
244
|
+
# compute the caller's permissions once here at the boundary so
|
|
245
|
+
# handlers never see the session or the authenticator.
|
|
246
|
+
if (
|
|
247
|
+
self._callableAcceptsEndpointPermissions
|
|
248
|
+
and endpointPermissions is None
|
|
249
|
+
and auth
|
|
250
|
+
and vortexSession
|
|
251
|
+
):
|
|
252
|
+
endpointPermissions = yield maybeDeferred(
|
|
253
|
+
auth.getEndpointPermissions, vortexSession
|
|
254
|
+
)
|
|
255
|
+
|
|
262
256
|
# Level 2: Get access control context, but only if the callback uses it.
|
|
263
257
|
# Default to the sentinel so handlers always receive a non-None value
|
|
264
258
|
# with a clear error on attribute access when auth is unavailable.
|
|
265
259
|
accessControlContext = NO_AUTH_ACCESS_CONTROL_CONTEXT
|
|
266
260
|
if self._callableAcceptsAccessControlContext and auth and vortexSession:
|
|
267
261
|
raw_ctx = yield maybeDeferred(
|
|
268
|
-
auth.getAccessControlContext,
|
|
269
|
-
vortexSession,
|
|
270
|
-
vortexName,
|
|
271
|
-
vortexUuid,
|
|
262
|
+
auth.getAccessControlContext, vortexSession, vortexName, vortexUuid
|
|
272
263
|
)
|
|
273
264
|
if not isinstance(raw_ctx, VortexAccessControlContextABC):
|
|
274
265
|
logger.error(
|
|
@@ -283,15 +274,16 @@ class PayloadEndpoint:
|
|
|
283
274
|
|
|
284
275
|
callable_ = self._wref()
|
|
285
276
|
if callable_:
|
|
286
|
-
kwargs = dict(
|
|
277
|
+
kwargs: Dict[str, object] = dict(
|
|
287
278
|
payloadEnvelope=payloadEnvelope,
|
|
288
279
|
vortexUuid=vortexUuid,
|
|
289
280
|
vortexName=vortexName,
|
|
290
281
|
sendResponse=sendResponse,
|
|
291
|
-
vortexSession=vortexSession,
|
|
292
282
|
)
|
|
293
283
|
if self._callableAcceptsAccessControlContext:
|
|
294
284
|
kwargs["accessControlContext"] = accessControlContext
|
|
285
|
+
if self._callableAcceptsEndpointPermissions:
|
|
286
|
+
kwargs["endpointPermissions"] = endpointPermissions
|
|
295
287
|
return (yield maybeDeferred(callable_, **kwargs))
|
|
296
288
|
else:
|
|
297
289
|
PayloadIO().remove(self)
|
|
@@ -54,7 +54,6 @@ class PayloadEndpointPyTest(unittest.TestCase):
|
|
|
54
54
|
payloadEnvelope=PayloadEnvelope(filt=payload.filt),
|
|
55
55
|
vortexUuid="test",
|
|
56
56
|
vortexName="test",
|
|
57
|
-
vortexSession=None,
|
|
58
57
|
sendResponse=lambda x: x,
|
|
59
58
|
)
|
|
60
59
|
|
|
@@ -143,7 +142,9 @@ class PayloadEndpointPyTest(unittest.TestCase):
|
|
|
143
142
|
|
|
144
143
|
def subScope():
|
|
145
144
|
inst = PayloadEndpointPyTestAssignPayload(self)
|
|
146
|
-
PayloadEndpoint(
|
|
145
|
+
PayloadEndpoint(
|
|
146
|
+
filt, inst.process, requiredPermissions=frozenset()
|
|
147
|
+
)
|
|
147
148
|
|
|
148
149
|
self._processEnvelope(payload)
|
|
149
150
|
yield self._flushReactor()
|
|
@@ -57,9 +57,9 @@ class PayloadEnvelope(Jsonable):
|
|
|
57
57
|
) -> None:
|
|
58
58
|
Jsonable.__init__(self)
|
|
59
59
|
"""Constructor"""
|
|
60
|
-
assert not (
|
|
61
|
-
|
|
62
|
-
)
|
|
60
|
+
assert not (
|
|
61
|
+
data and encodedPayload
|
|
62
|
+
), "You can not pass encodedData and encodedPayload"
|
|
63
63
|
|
|
64
64
|
self.filt: Dict = {} if filt is None else filt
|
|
65
65
|
self.data: Union[Any, str, None] = data if data else encodedPayload
|
|
@@ -75,18 +75,18 @@ class PayloadEnvelope(Jsonable):
|
|
|
75
75
|
@property
|
|
76
76
|
def encodedPayload(self) -> Optional[str]:
|
|
77
77
|
# self.data could be from VortexJS/Typescript where we allow `str` data
|
|
78
|
-
assert self.data is None or isinstance(
|
|
79
|
-
|
|
80
|
-
)
|
|
78
|
+
assert self.data is None or isinstance(
|
|
79
|
+
self.data, str
|
|
80
|
+
), "Encoded payload is not None or a string"
|
|
81
81
|
return self.data
|
|
82
82
|
|
|
83
83
|
@encodedPayload.setter
|
|
84
84
|
def encodedPayload(self, val: Optional[str]):
|
|
85
85
|
# This value should only be set from users of VortexPy and
|
|
86
86
|
# Payload.toEncodedPayload so we only allow str or None
|
|
87
|
-
assert val is None or isinstance(
|
|
88
|
-
|
|
89
|
-
)
|
|
87
|
+
assert val is None or isinstance(
|
|
88
|
+
val, str
|
|
89
|
+
), "Encoded payload is not None or a string"
|
|
90
90
|
self.data = val
|
|
91
91
|
|
|
92
92
|
def isEmpty(self):
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import logging
|
|
10
10
|
from datetime import datetime
|
|
11
|
+
from typing import Optional
|
|
11
12
|
|
|
12
13
|
import pytz
|
|
13
14
|
from twisted.internet import reactor
|
|
@@ -59,8 +60,8 @@ class PayloadIO(object):
|
|
|
59
60
|
payloadEnvelope: PayloadEnvelope,
|
|
60
61
|
vortexUuid: str,
|
|
61
62
|
vortexName: str,
|
|
62
|
-
vortexSession,
|
|
63
|
-
sendResponse: SendVortexMsgResponseCallable,
|
|
63
|
+
vortexSession=None,
|
|
64
|
+
sendResponse: Optional[SendVortexMsgResponseCallable] = None,
|
|
64
65
|
):
|
|
65
66
|
from vortex.VortexFactory import VortexFactory
|
|
66
67
|
|
|
@@ -95,8 +96,8 @@ class PayloadIO(object):
|
|
|
95
96
|
payloadEnvelope: PayloadEnvelope,
|
|
96
97
|
vortexUuid: str,
|
|
97
98
|
vortexName: str,
|
|
98
|
-
vortexSession,
|
|
99
|
-
sendResponse: SendVortexMsgResponseCallable,
|
|
99
|
+
vortexSession=None,
|
|
100
|
+
sendResponse: Optional[SendVortexMsgResponseCallable] = None,
|
|
100
101
|
):
|
|
101
102
|
startDate = datetime.now(pytz.utc)
|
|
102
103
|
|
|
@@ -106,6 +107,10 @@ class PayloadIO(object):
|
|
|
106
107
|
common function
|
|
107
108
|
"""
|
|
108
109
|
try:
|
|
110
|
+
assert sendResponse is not None, (
|
|
111
|
+
"PayloadIO._processLater: sendResponse must be set"
|
|
112
|
+
" to respond to an exception"
|
|
113
|
+
)
|
|
109
114
|
sendResponse(
|
|
110
115
|
PayloadEnvelope(
|
|
111
116
|
filt=payloadEnvelope.filt,
|
|
@@ -115,15 +120,8 @@ class PayloadIO(object):
|
|
|
115
120
|
except Exception as e:
|
|
116
121
|
logger.exception(e)
|
|
117
122
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
logger.error(payloadEnvelope.filt)
|
|
121
|
-
else:
|
|
122
|
-
logger.debug(
|
|
123
|
-
"Payload handler response for filt=%s: %s",
|
|
124
|
-
payloadEnvelope.filt,
|
|
125
|
-
failure.getErrorMessage(),
|
|
126
|
-
)
|
|
123
|
+
vortexLogFailure(failure, logger)
|
|
124
|
+
logger.error(payloadEnvelope.filt)
|
|
127
125
|
|
|
128
126
|
def callback(value, blocking=False):
|
|
129
127
|
# A blocking call taking more than 100ms is BAD
|
|
@@ -67,7 +67,7 @@ class PayloadResponse(Deferred):
|
|
|
67
67
|
destVortexUuid: Optional[str] = None,
|
|
68
68
|
timeout: Optional[float] = None,
|
|
69
69
|
resultCheck=True,
|
|
70
|
-
|
|
70
|
+
logTimeoutError=True,
|
|
71
71
|
) -> None:
|
|
72
72
|
"""Constructor
|
|
73
73
|
|
|
@@ -81,8 +81,6 @@ class PayloadResponse(Deferred):
|
|
|
81
81
|
:param timeout The timeout to wait for a response
|
|
82
82
|
:param resultCheck Should the response payload.result be checked, if it fails
|
|
83
83
|
it errback will be called.
|
|
84
|
-
:param logTimeoutException: When True, payload timeouts log at ERROR.
|
|
85
|
-
When False, timeouts log at DEBUG with neutral wording.
|
|
86
84
|
"""
|
|
87
85
|
Deferred.__init__(self)
|
|
88
86
|
|
|
@@ -90,7 +88,7 @@ class PayloadResponse(Deferred):
|
|
|
90
88
|
timeout = self.TIMEOUT
|
|
91
89
|
|
|
92
90
|
self._resultCheck = resultCheck
|
|
93
|
-
self.
|
|
91
|
+
self._logTimeoutError = logTimeoutError
|
|
94
92
|
|
|
95
93
|
# uuid4 can have collisions
|
|
96
94
|
self._messageId = str(uuid4()) + str(PayloadResponse.__SEQ)
|
|
@@ -144,10 +142,8 @@ class PayloadResponse(Deferred):
|
|
|
144
142
|
self._endpoint.shutdown()
|
|
145
143
|
self._endpoint = None
|
|
146
144
|
|
|
147
|
-
if self.
|
|
145
|
+
if self._logTimeoutError:
|
|
148
146
|
logger.error("Timed out for payload %s", self._filt)
|
|
149
|
-
else:
|
|
150
|
-
logger.debug("Payload response timed out for %s", self._filt)
|
|
151
147
|
self._status = self.TIMED_OUT
|
|
152
148
|
return failure
|
|
153
149
|
|
|
@@ -157,7 +153,6 @@ class PayloadResponse(Deferred):
|
|
|
157
153
|
vortexUuid: str,
|
|
158
154
|
vortexName: str,
|
|
159
155
|
sendResponse=None,
|
|
160
|
-
vortexSession=None,
|
|
161
156
|
):
|
|
162
157
|
if self._endpoint:
|
|
163
158
|
self._endpoint.shutdown()
|