mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-05 06:53:18 +08:00
fixed cloud console crash error
This commit is contained in:
parent
86b931dfcc
commit
68ffe1f2bd
@ -3995,50 +3995,50 @@
|
|||||||
"assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e",
|
"assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e",
|
||||||
"assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34",
|
"assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34",
|
||||||
"ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a",
|
"ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a",
|
||||||
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/bc/d7/f65513a0b3d5fa8b5f4cfe342052",
|
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b3/94/954559711625a0bb6a29d41c35ff",
|
||||||
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/06/03/381b1b4470868245225dd4e4bb67",
|
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/44/1e/7eec4d37c0c2afb581927efbb2dc",
|
||||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/52/b0/36011f65de64a547009bef7fe6ec",
|
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/92/75/2d6b53a09ce1fe7cbe3b50d832de",
|
||||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e2/46/384efcdbfb324b63889d567e7f14",
|
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/cf/eb/2f2119b7c86ecbfb2a8b725b21f6",
|
||||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/8b/27/7bab35742af8c101f4aab3ebbd3d",
|
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/c2/95/be04f3219b078c92a787627b42b7",
|
||||||
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/3b/d0/c1ee5a02a09c1d676a22a20fe8a7",
|
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/53/f5/3bd3ba9c59b87ff7b8abc4233844",
|
||||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e9/2e/3ae4fb2983bb36167d1fe3044358",
|
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5e/21/a913309416dde18bc4c9104c3ec5",
|
||||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9e/93/12e8d5357db44c97549fe2fbd7ca",
|
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/28/25/54314d17a5a12be51a3b340359bd",
|
||||||
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/53/6d/06e5987cfcf47d740ead2e8c3b7f",
|
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/07/39/13923a2f10d8e2a8d1d12007cbed",
|
||||||
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/1b/5b/fd0fa7104c3e2d3a22c180db47cf",
|
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/a7/86/8cfb723071ad46355af9166ba59a",
|
||||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ca/98/0e12c6aa44fc9e64492b6da67b02",
|
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ad/73/6013ee6879fae3c3e06b15396fb0",
|
||||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e6/81/aacab39968075487c9f610e3036c",
|
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/da/8b/f33a546e2342591ab84ddcf4053e",
|
||||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/94/bc/7a2fb10033217cac2fc04ccd0309",
|
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/f8/b7/fffc4c52e906890b35c936441b60",
|
||||||
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/a4/da/b7095762fbdef22aff5d77c5d45d",
|
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/27/24/2ca5005df08ea5a7a78cd20b020a",
|
||||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8b/05/2051b310f7989aa9aa04339de2f3",
|
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/cd/8d/c59fcc270b637990d12cd8a758e0",
|
||||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2d/6e/3befc00833dc482ef55b70a915fe",
|
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/54/a9/78e4658fd4446898b11633191c01",
|
||||||
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/82/ce/77695599588b675fac1e10febeae",
|
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/53/30/cd915e748f31208239b90f5a7a2c",
|
||||||
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/3a/c3/d042e59d36f71c885036ed0e73d4",
|
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a9/4e/c367a7a66eb17df7757dc85d59b6",
|
||||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/87/48/b1551cd7b5cf44c06a3e3a1a66a4",
|
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/5d/13/38ab5bdd9fdb0abca878d0bbfbab",
|
||||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/6d/e2/3366be4f442e6ef48b5ef5babe87",
|
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/02/62/c3a8023aa43567204407325d6c4c",
|
||||||
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d6/9a/5e36fb51a797da74db8f366a8e6d",
|
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/23/17/f0d22a9a91a295ee4a9d94db2af9",
|
||||||
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/98/d7/e827cc644d4dde0c1bddb17121b0",
|
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d5/4f/bfbcdd18679b4ba0df1b040e8c15",
|
||||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/9b/e0/a1ae5fdadff116de78727e2a8d30",
|
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/96/e9/0f4aa3d10f2d50fe670bb6d89ba0",
|
||||||
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/49/76/fd27d293fd73d324ecc433b1e253",
|
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/26/ef/1b58d3c788441242ed9ca9352499",
|
||||||
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1e/93/b85c7585218b5c86d766a23373c6",
|
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/79/77/b35c5f93f62d92fe9cdb548f6e54",
|
||||||
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/34/0a/4547b5a8a00a35874cfbab25fc11",
|
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c6/53/8e678b75f456378e17e4f639fe35",
|
||||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/68/5a/a4a030424d8d5900433bdb70bd83",
|
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ab/1d/b514c16cfda2f5840676a4c75ca3",
|
||||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e1/4b/278433e2332245313d4fa3390aee",
|
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d7/c4/b797fd5365d34fcfb60d6275fb3c",
|
||||||
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/22/c1/fc9726d56ac62c757e7f7eeb56e2",
|
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b0/6c/b8f8c1d1d8e2f772208af12e085f",
|
||||||
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/23/4f/ee03bed8d42b8e12832efbd17968",
|
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c0/e1/f57102a8da2fe0ca7787c0a7924a",
|
||||||
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/dc/7a/f5bae1a284d2b51e149f12da9e18",
|
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8f/16/19494ad899b3f1990dd2b5cdfa99",
|
||||||
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2e/75/254680a01a85fcdc19db275cd2ff",
|
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a9/d5/59ba30f21d5583bdc92516c0916e",
|
||||||
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/79/fb/65e1f1851f2dc663eb5d9dd27ae9",
|
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e7/82/e29dbff494964b753a08eaa66b66",
|
||||||
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/24/5d/33ca757aa471e81ee2efe83b5c32",
|
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2f/06/ec124d5bfce4d3f268b1318755b8",
|
||||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/83/3e/35613478ab4887b7f77126c1d910",
|
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3f/47/3322caea5f9a92735076c1017839",
|
||||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ba/a7/b925b7eb7b2da10fdc9c88e59576",
|
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f5/9f/ce9a27aea9a4b7056800cf68afe9",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/0a/ae/daac4e04ef473d0da419ebe2ddf2",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/6c/56/6180e5d6db6868b7438751320faf",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/52/9d/d6c5366d82b56d1c79553ae3258b",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/71/24/e873efab9c315ec907427bd22327",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/35/db/9f6868dde4184cb3b33153981548",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/3d/d6/b1a3c97a66d3f5ad38d5f5dda476",
|
||||||
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/0c/e0/a869977d8ee1dcf4bcbb0853fe3c",
|
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/5a/e9/14593b84a3035a1bd7ce3980818d",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/31/c1/e51379d7cf51aec768855e6e7eb7",
|
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/87/5c/38b4d59ad04f6ba89dae6ca38fa5",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/0f/48/52683efe93f7311f2a81a280a87e",
|
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/3c/0a/6b151c9054294db58cf98957a515",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/7c/05/660a71d76685232d9bd91d979ef8",
|
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/e3/fb/7be0f96c82816af61849aaf4357a",
|
||||||
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/30/5a/b2e0ce3986936938c65e4bef2d0e",
|
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/23/dc/91a8e0f2123a75b4d72a0d26ab25",
|
||||||
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/c0/32/b7907e3859a5c5013a3d97b6b523",
|
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/c0/32/b7907e3859a5c5013a3d97b6b523",
|
||||||
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/2d/4f/f4fe67827f36cd59cd5193333a02",
|
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/2d/4f/f4fe67827f36cd59cd5193333a02",
|
||||||
"src/ballistica/generated/python_embedded/bootstrap_monolithic.inc": "https://files.ballistica.net/cache/ba1/ef/c1/aa5f1aa10af89f5c0b1e616355fd"
|
"src/ballistica/generated/python_embedded/bootstrap_monolithic.inc": "https://files.ballistica.net/cache/ba1/ef/c1/aa5f1aa10af89f5c0b1e616355fd"
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
### 1.7.7 (build 20862, api 7, 2022-09-17)
|
### 1.7.7 (build 20865, api 7, 2022-09-19)
|
||||||
- Added `ba.app.meta.load_exported_classes()` for loading classes discovered by the meta subsystem cleanly in a background thread.
|
- Added `ba.app.meta.load_exported_classes()` for loading classes discovered by the meta subsystem cleanly in a background thread.
|
||||||
- Improved logging of missing playlist game types.
|
- Improved logging of missing playlist game types.
|
||||||
- Some ba.Lstr functionality can now be used in background threads.
|
- Some ba.Lstr functionality can now be used in background threads.
|
||||||
@ -39,6 +39,8 @@
|
|||||||
- If you want to grab recent logs, you can now use `ba.app.log_handler.get_cached()`. This will give you everything that has gone through Python logging, Python stdout/stderr, and the C++ Log() call (up to the max cache size that is).
|
- If you want to grab recent logs, you can now use `ba.app.log_handler.get_cached()`. This will give you everything that has gone through Python logging, Python stdout/stderr, and the C++ Log() call (up to the max cache size that is).
|
||||||
- LogHandler output now ALWAYS goes to stderr. Previously it only would if an interactive terminal was detected. This should make the binary easier to debug if run from scripts/etc. We can add a `--quiet` option if needed or whatnot.
|
- LogHandler output now ALWAYS goes to stderr. Previously it only would if an interactive terminal was detected. This should make the binary easier to debug if run from scripts/etc. We can add a `--quiet` option if needed or whatnot.
|
||||||
- (build 20859) Fixed an error setting up asyncio loops under Windows related to the fact that Python is now inited in the main thread.
|
- (build 20859) Fixed an error setting up asyncio loops under Windows related to the fact that Python is now inited in the main thread.
|
||||||
|
- (build 20864) Fatal-error message/traceback now properly prints to stderr again (I think the reject logging rejiggering caused it to stop).
|
||||||
|
- (build 20864) Fixed an issue where the app could crash when connected to the cloud console while in a network game.
|
||||||
|
|
||||||
|
|
||||||
### 1.7.6 (build 20687, api 7, 2022-08-11)
|
### 1.7.6 (build 20687, api 7, 2022-08-11)
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
84155513838284412598729205538639495871
|
137071025041513581787580065580079045765
|
||||||
@ -44,7 +44,7 @@ def bootstrap() -> None:
|
|||||||
|
|
||||||
# Give a soft warning if we're being used with a different binary
|
# Give a soft warning if we're being used with a different binary
|
||||||
# version than we expect.
|
# version than we expect.
|
||||||
expected_build = 20862
|
expected_build = 20865
|
||||||
running_build: int = env['build_number']
|
running_build: int = env['build_number']
|
||||||
if running_build != expected_build:
|
if running_build != expected_build:
|
||||||
print(
|
print(
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
namespace ballistica {
|
namespace ballistica {
|
||||||
|
|
||||||
// These are set automatically via script; don't modify them here.
|
// These are set automatically via script; don't modify them here.
|
||||||
const int kAppBuildNumber = 20862;
|
const int kAppBuildNumber = 20865;
|
||||||
const char* kAppVersion = "1.7.7";
|
const char* kAppVersion = "1.7.7";
|
||||||
|
|
||||||
// Our standalone globals.
|
// Our standalone globals.
|
||||||
|
|||||||
@ -27,7 +27,7 @@ auto FatalError::ReportFatalError(const std::string& message,
|
|||||||
// error to the user and exiting the app cleanly (so we don't pollute our
|
// error to the user and exiting the app cleanly (so we don't pollute our
|
||||||
// crash records with results of user tinkering).
|
// crash records with results of user tinkering).
|
||||||
|
|
||||||
// Give the platform the opportunity to completely override our handling.
|
// Give the platform the opportunity to augment or override our handling.
|
||||||
if (g_platform) {
|
if (g_platform) {
|
||||||
auto handled =
|
auto handled =
|
||||||
g_platform->ReportFatalError(message, in_top_level_exception_handler);
|
g_platform->ReportFatalError(message, in_top_level_exception_handler);
|
||||||
@ -38,7 +38,8 @@ auto FatalError::ReportFatalError(const std::string& message,
|
|||||||
|
|
||||||
std::string dialog_msg = message;
|
std::string dialog_msg = message;
|
||||||
if (!dialog_msg.empty()) {
|
if (!dialog_msg.empty()) {
|
||||||
dialog_msg += "\n";
|
// Why was this here?
|
||||||
|
// dialog_msg += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto starttime = time(nullptr);
|
auto starttime = time(nullptr);
|
||||||
@ -75,9 +76,10 @@ auto FatalError::ReportFatalError(const std::string& message,
|
|||||||
g_early_v1_cloud_log_writes = 0;
|
g_early_v1_cloud_log_writes = 0;
|
||||||
|
|
||||||
// Add this to our V1CloudLog which we'll be attempting to send momentarily,
|
// Add this to our V1CloudLog which we'll be attempting to send momentarily,
|
||||||
// and also try to present it directly to the user.
|
// and also go to platform-specific logging and good ol' stderr.
|
||||||
Logging::V1CloudLog(logmsg);
|
Logging::V1CloudLog(logmsg);
|
||||||
Logging::DisplayLog("root", LogLevel::kCritical, logmsg);
|
Logging::DisplayLog("root", LogLevel::kCritical, logmsg);
|
||||||
|
fprintf(stderr, "%s\n", logmsg.c_str());
|
||||||
|
|
||||||
std::string prefix = "FATAL-ERROR-LOG:";
|
std::string prefix = "FATAL-ERROR-LOG:";
|
||||||
std::string suffix;
|
std::string suffix;
|
||||||
|
|||||||
@ -1050,15 +1050,10 @@ void Logic::PushPythonRawCallable(PyObject* callable, bool fg_context) {
|
|||||||
thread()->PushCall([this, callable, fg_context] {
|
thread()->PushCall([this, callable, fg_context] {
|
||||||
assert(InLogicThread());
|
assert(InLogicThread());
|
||||||
|
|
||||||
// Lets run this in the UI context.
|
// Run this in the UI context by default, or foreground if requested.
|
||||||
// (can add other options if we need later)
|
|
||||||
ScopedSetContext cp(fg_context ? GetForegroundContext() : GetUIContext());
|
ScopedSetContext cp(fg_context ? GetForegroundContext() : GetUIContext());
|
||||||
|
|
||||||
// This event contains a raw python obj with an incremented ref-count.
|
PythonRef(callable, PythonRef::kSteal).Call();
|
||||||
auto call(Object::New<PythonContextCall>(callable));
|
|
||||||
Py_DECREF(callable); // now just held by call
|
|
||||||
|
|
||||||
call->Run();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -83,8 +83,8 @@ class Logic {
|
|||||||
auto PushPythonWeakCallArgs(const Object::WeakRef<PythonContextCall>& call,
|
auto PushPythonWeakCallArgs(const Object::WeakRef<PythonContextCall>& call,
|
||||||
const PythonRef& args) -> void;
|
const PythonRef& args) -> void;
|
||||||
|
|
||||||
// Push a raw Python call, decrements its refcount after running.
|
// Push a raw Python call from any thread. Refcount should be incremented
|
||||||
// Can be pushed from any thread.
|
// beforehand and will be decremented after running.
|
||||||
auto PushPythonRawCallable(PyObject* callable, bool fg_context = false)
|
auto PushPythonRawCallable(PyObject* callable, bool fg_context = false)
|
||||||
-> void;
|
-> void;
|
||||||
auto PushScreenMessage(const std::string& message, const Vector3f& color)
|
auto PushScreenMessage(const std::string& message, const Vector3f& color)
|
||||||
|
|||||||
@ -102,7 +102,7 @@ auto PythonClassContextCall::tp_new(PyTypeObject* type, PyObject* args,
|
|||||||
if (!PyArg_ParseTuple(args, "O", &source_obj)) return nullptr;
|
if (!PyArg_ParseTuple(args, "O", &source_obj)) return nullptr;
|
||||||
if (!InLogicThread()) {
|
if (!InLogicThread()) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"ERROR: " + std::string(type_obj.tp_name)
|
std::string(type_obj.tp_name)
|
||||||
+ " objects must only be created in the logic thread (current is ("
|
+ " objects must only be created in the logic thread (current is ("
|
||||||
+ GetCurrentThreadName() + ").");
|
+ GetCurrentThreadName() + ").");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,17 +14,17 @@ PythonContextCall* PythonContextCall::current_call_ = nullptr;
|
|||||||
|
|
||||||
PythonContextCall::PythonContextCall(PyObject* obj_in) {
|
PythonContextCall::PythonContextCall(PyObject* obj_in) {
|
||||||
assert(InLogicThread());
|
assert(InLogicThread());
|
||||||
// as a sanity test, store the current context ptr just to make sure it
|
// As a sanity test, store the current context ptr just to make sure it
|
||||||
// hasn't changed when we run
|
// hasn't changed when we run.
|
||||||
#if BA_DEBUG_BUILD
|
#if BA_DEBUG_BUILD
|
||||||
context_target_sanity_test_ = context_.target.get();
|
context_target_sanity_test_ = context_.target.get();
|
||||||
#endif // BA_DEBUG_BUILD
|
#endif // BA_DEBUG_BUILD
|
||||||
BA_PRECONDITION(PyCallable_Check(obj_in));
|
BA_PRECONDITION(PyCallable_Check(obj_in));
|
||||||
object_.Acquire(obj_in);
|
object_.Acquire(obj_in);
|
||||||
GetTrace();
|
GetTrace();
|
||||||
// ok now we need to register this call with whatever the context is;
|
// Ok now we need to register this call with whatever the context is;
|
||||||
// it can be stored in a host-activity, a host-session, or the UI context.
|
// it can be stored in a host-activity, a host-session, or the UI context.
|
||||||
// whoever it is registered with will explicitly release its contents on
|
// Whoever it is registered with will explicitly release its contents on
|
||||||
// shutdown and ensure that nothing gets run after that point.
|
// shutdown and ensure that nothing gets run after that point.
|
||||||
if (HostActivity* ha = context_.GetHostActivity()) {
|
if (HostActivity* ha = context_.GetHostActivity()) {
|
||||||
ha->RegisterCall(this);
|
ha->RegisterCall(this);
|
||||||
|
|||||||
@ -18,7 +18,7 @@ from efro.dataclassio import ioprepped
|
|||||||
from efro.message import (Message, Response, MessageProtocol, MessageSender,
|
from efro.message import (Message, Response, MessageProtocol, MessageSender,
|
||||||
BoundMessageSender, MessageReceiver,
|
BoundMessageSender, MessageReceiver,
|
||||||
BoundMessageReceiver, UnregisteredMessageIDError,
|
BoundMessageReceiver, UnregisteredMessageIDError,
|
||||||
EmptyResponse)
|
EmptySysResponse)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Callable, Awaitable
|
from typing import Any, Callable, Awaitable
|
||||||
@ -424,8 +424,8 @@ TEST_PROTOCOL = MessageProtocol(
|
|||||||
0: _TResp1,
|
0: _TResp1,
|
||||||
1: _TResp2,
|
1: _TResp2,
|
||||||
},
|
},
|
||||||
receiver_returns_stack_traces=True,
|
forward_clean_errors=True,
|
||||||
receiver_logs_exceptions=False,
|
remote_errors_include_stack_traces=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Represents an 'evolved' TEST_PROTOCOL (one extra message type added).
|
# Represents an 'evolved' TEST_PROTOCOL (one extra message type added).
|
||||||
@ -441,8 +441,8 @@ TEST_PROTOCOL_B = MessageProtocol(
|
|||||||
0: _TResp1,
|
0: _TResp1,
|
||||||
1: _TResp2,
|
1: _TResp2,
|
||||||
},
|
},
|
||||||
receiver_returns_stack_traces=True,
|
forward_clean_errors=True,
|
||||||
receiver_logs_exceptions=False,
|
remote_errors_include_stack_traces=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
TEST_PROTOCOL_SINGLE = MessageProtocol(
|
TEST_PROTOCOL_SINGLE = MessageProtocol(
|
||||||
@ -452,8 +452,7 @@ TEST_PROTOCOL_SINGLE = MessageProtocol(
|
|||||||
response_types={
|
response_types={
|
||||||
0: _TResp1,
|
0: _TResp1,
|
||||||
},
|
},
|
||||||
receiver_returns_stack_traces=True,
|
remote_errors_include_stack_traces=True,
|
||||||
receiver_logs_exceptions=False,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -463,12 +462,16 @@ def test_protocol_creation() -> None:
|
|||||||
# This should fail because _TMsg1 can return _TResp1 which
|
# This should fail because _TMsg1 can return _TResp1 which
|
||||||
# is not given an id here.
|
# is not given an id here.
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
_protocol = MessageProtocol(message_types={0: _TMsg1},
|
_protocol = MessageProtocol(
|
||||||
response_types={0: _TResp2})
|
message_types={0: _TMsg1},
|
||||||
|
response_types={0: _TResp2},
|
||||||
|
)
|
||||||
|
|
||||||
# Now it should work.
|
# Now it should work.
|
||||||
_protocol = MessageProtocol(message_types={0: _TMsg1},
|
_protocol = MessageProtocol(
|
||||||
response_types={0: _TResp1})
|
message_types={0: _TMsg1},
|
||||||
|
response_types={0: _TResp1},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_sender_module_single_emb() -> None:
|
def test_sender_module_single_emb() -> None:
|
||||||
@ -777,7 +780,7 @@ def test_full_pipeline() -> None:
|
|||||||
# Emulate forwarding unregistered messages on to some
|
# Emulate forwarding unregistered messages on to some
|
||||||
# other handler...
|
# other handler...
|
||||||
response_dict = self.msg.protocol.response_to_dict(
|
response_dict = self.msg.protocol.response_to_dict(
|
||||||
EmptyResponse())
|
EmptySysResponse())
|
||||||
return self.msg.protocol.encode_dict(response_dict)
|
return self.msg.protocol.encode_dict(response_dict)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
@ -909,7 +912,8 @@ def test_full_pipeline() -> None:
|
|||||||
assert response3 is None
|
assert response3 is None
|
||||||
assert isinstance(response4, _TResp1)
|
assert isinstance(response4, _TResp1)
|
||||||
|
|
||||||
# Remote CleanErrors should come across locally as the same.
|
# Remote CleanErrors should come across locally as the same
|
||||||
|
# (provided our protocol has enabled support for them).
|
||||||
try:
|
try:
|
||||||
_response5 = obj.msg.send(_TMsg1(ival=1))
|
_response5 = obj.msg.send(_TMsg1(ival=1))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
|||||||
@ -11,15 +11,16 @@ from efro.message._protocol import MessageProtocol
|
|||||||
from efro.message._sender import (MessageSender, BoundMessageSender)
|
from efro.message._sender import (MessageSender, BoundMessageSender)
|
||||||
from efro.message._receiver import (MessageReceiver, BoundMessageReceiver)
|
from efro.message._receiver import (MessageReceiver, BoundMessageReceiver)
|
||||||
from efro.message._module import (create_sender_module, create_receiver_module)
|
from efro.message._module import (create_sender_module, create_receiver_module)
|
||||||
from efro.message._message import (Message, Response, EmptyResponse,
|
from efro.message._message import (Message, Response, EmptySysResponse,
|
||||||
ErrorResponse, StringResponse, BoolResponse,
|
ErrorSysResponse, StringResponse,
|
||||||
UnregisteredMessageIDError)
|
BoolResponse, UnregisteredMessageIDError)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'Message', 'Response', 'EmptyResponse', 'ErrorResponse', 'StringResponse',
|
'Message', 'Response', 'EmptySysResponse', 'ErrorSysResponse',
|
||||||
'BoolResponse', 'MessageProtocol', 'MessageSender', 'BoundMessageSender',
|
'StringResponse', 'BoolResponse', 'MessageProtocol', 'MessageSender',
|
||||||
'MessageReceiver', 'BoundMessageReceiver', 'create_sender_module',
|
'BoundMessageSender', 'MessageReceiver', 'BoundMessageReceiver',
|
||||||
'create_receiver_module', 'UnregisteredMessageIDError'
|
'create_sender_module', 'create_receiver_module',
|
||||||
|
'UnregisteredMessageIDError'
|
||||||
]
|
]
|
||||||
|
|
||||||
# Have these things present themselves cleanly as 'thismodule.SomeClass'
|
# Have these things present themselves cleanly as 'thismodule.SomeClass'
|
||||||
|
|||||||
@ -27,12 +27,12 @@ class Message:
|
|||||||
def get_response_types(cls) -> list[type[Response]]:
|
def get_response_types(cls) -> list[type[Response]]:
|
||||||
"""Return all message types this Message can result in when sent.
|
"""Return all message types this Message can result in when sent.
|
||||||
|
|
||||||
The default implementation specifies EmptyResponse, so messages with
|
The default implementation specifies EmptySysResponse, so messages with
|
||||||
no particular response needs can leave this untouched.
|
no particular response needs can leave this untouched.
|
||||||
Note that ErrorMessage is handled as a special case and does not
|
Note that ErrorMessage is handled as a special case and does not
|
||||||
need to be specified here.
|
need to be specified here.
|
||||||
"""
|
"""
|
||||||
return [EmptyResponse]
|
return [EmptySysResponse]
|
||||||
|
|
||||||
|
|
||||||
class Response:
|
class Response:
|
||||||
@ -44,7 +44,7 @@ class Response:
|
|||||||
|
|
||||||
@ioprepped
|
@ioprepped
|
||||||
@dataclass
|
@dataclass
|
||||||
class ErrorResponse(Response):
|
class ErrorSysResponse(Response):
|
||||||
"""Response saying some error has occurred for the send.
|
"""Response saying some error has occurred for the send.
|
||||||
|
|
||||||
This type is unique in that it is not returned to the user; it
|
This type is unique in that it is not returned to the user; it
|
||||||
@ -64,12 +64,12 @@ class ErrorResponse(Response):
|
|||||||
|
|
||||||
@ioprepped
|
@ioprepped
|
||||||
@dataclass
|
@dataclass
|
||||||
class EmptyResponse(Response):
|
class EmptySysResponse(Response):
|
||||||
"""The response equivalent of None."""
|
"""The response equivalent of None."""
|
||||||
|
|
||||||
|
|
||||||
# TODO: could allow handlers to deal in raw values for these
|
# TODO: could allow handlers to deal in raw values for these
|
||||||
# types similar to how we allow None in place of EmptyResponse.
|
# types similar to how we allow None in place of EmptySysResponse.
|
||||||
# Though not sure if they are widely used enough to warrant the
|
# Though not sure if they are widely used enough to warrant the
|
||||||
# extra code complexity.
|
# extra code complexity.
|
||||||
@ioprepped
|
@ioprepped
|
||||||
|
|||||||
@ -14,8 +14,9 @@ import json
|
|||||||
from efro.error import CleanError
|
from efro.error import CleanError
|
||||||
from efro.dataclassio import (is_ioprepped_dataclass, dataclass_to_dict,
|
from efro.dataclassio import (is_ioprepped_dataclass, dataclass_to_dict,
|
||||||
dataclass_from_dict)
|
dataclass_from_dict)
|
||||||
from efro.message._message import (Message, Response, ErrorResponse,
|
from efro.message._message import (Message, Response, ErrorSysResponse,
|
||||||
EmptyResponse, UnregisteredMessageIDError)
|
EmptySysResponse,
|
||||||
|
UnregisteredMessageIDError)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Literal
|
from typing import Any, Literal
|
||||||
@ -33,29 +34,20 @@ class MessageProtocol:
|
|||||||
def __init__(self,
|
def __init__(self,
|
||||||
message_types: dict[int, type[Message]],
|
message_types: dict[int, type[Message]],
|
||||||
response_types: dict[int, type[Response]],
|
response_types: dict[int, type[Response]],
|
||||||
preserve_clean_errors: bool = True,
|
forward_clean_errors: bool = False,
|
||||||
receiver_logs_exceptions: bool = True,
|
remote_errors_include_stack_traces: bool = False) -> None:
|
||||||
receiver_returns_stack_traces: bool = False) -> None:
|
|
||||||
"""Create a protocol with a given configuration.
|
"""Create a protocol with a given configuration.
|
||||||
|
|
||||||
Note that common response types are automatically registered
|
Note that common response types are automatically registered
|
||||||
with (unchanging negative ids) so they don't need to be passed
|
with (unchanging negative ids) so they don't need to be passed
|
||||||
explicitly (but can be if a different id is desired).
|
explicitly (but can be if a different id is desired).
|
||||||
|
|
||||||
If 'preserve_clean_errors' is True, efro.error.CleanError
|
If 'forward_clean_errors' is True, efro.error.CleanError
|
||||||
exceptions raised on the receiver end will result in a matching
|
exceptions raised on the receiver end will result in a matching
|
||||||
CleanError raised back on the sender. All other Exception types
|
CleanError raised back on the sender. All other Exception types
|
||||||
come across as efro.error.RemoteError.
|
come across as efro.error.RemoteError.
|
||||||
|
|
||||||
When 'receiver_logs_exceptions' is True, any uncaught Exceptions
|
If 'remote_errors_include_stack_traces' is True, stringified stack
|
||||||
on the receiver end will be logged there via logging.exception()
|
|
||||||
(in addition to the usual behavior of returning an ErrorResponse
|
|
||||||
to the sender). This is good to leave enabled if your
|
|
||||||
intention is to never return ErrorResponses. Looser setups
|
|
||||||
making routine use of CleanErrors or whatnot may want to
|
|
||||||
disable this, however.
|
|
||||||
|
|
||||||
If 'receiver_returns_stack_traces' is True, stringified stack
|
|
||||||
traces will be returned to the sender for exceptions occurring
|
traces will be returned to the sender for exceptions occurring
|
||||||
on the receiver end. This can make debugging easier but should
|
on the receiver end. This can make debugging easier but should
|
||||||
only be used when the client is trusted to see such info.
|
only be used when the client is trusted to see such info.
|
||||||
@ -88,15 +80,20 @@ class MessageProtocol:
|
|||||||
# Go ahead and auto-register a few common response types
|
# Go ahead and auto-register a few common response types
|
||||||
# if the user has not done so explicitly. Use unique negative
|
# if the user has not done so explicitly. Use unique negative
|
||||||
# IDs which will never change or overlap with user ids.
|
# IDs which will never change or overlap with user ids.
|
||||||
def _reg_if_not(reg_tp: type[Response], reg_id: int) -> None:
|
def _reg_sys(reg_tp: type[Response], reg_id: int) -> None:
|
||||||
|
|
||||||
|
# If we have a positive id registered already, we still point
|
||||||
|
# negative sys id at this type but not the opposite.
|
||||||
if reg_tp in self.response_ids_by_type:
|
if reg_tp in self.response_ids_by_type:
|
||||||
|
self.response_types_by_id[reg_id] = reg_tp
|
||||||
return
|
return
|
||||||
|
|
||||||
assert self.response_types_by_id.get(reg_id) is None
|
assert self.response_types_by_id.get(reg_id) is None
|
||||||
self.response_types_by_id[reg_id] = reg_tp
|
self.response_types_by_id[reg_id] = reg_tp
|
||||||
self.response_ids_by_type[reg_tp] = reg_id
|
self.response_ids_by_type[reg_tp] = reg_id
|
||||||
|
|
||||||
_reg_if_not(ErrorResponse, -1)
|
_reg_sys(ErrorSysResponse, -1)
|
||||||
_reg_if_not(EmptyResponse, -2)
|
_reg_sys(EmptySysResponse, -2)
|
||||||
|
|
||||||
# Some extra-thorough validation in debug mode.
|
# Some extra-thorough validation in debug mode.
|
||||||
if __debug__:
|
if __debug__:
|
||||||
@ -127,9 +124,9 @@ class MessageProtocol:
|
|||||||
'message_types contains duplicate __name__s;'
|
'message_types contains duplicate __name__s;'
|
||||||
' all types are required to have unique names.')
|
' all types are required to have unique names.')
|
||||||
|
|
||||||
self.preserve_clean_errors = preserve_clean_errors
|
self.forward_clean_errors = forward_clean_errors
|
||||||
self.receiver_logs_exceptions = receiver_logs_exceptions
|
self.remote_errors_include_stack_traces = (
|
||||||
self.receiver_returns_stack_traces = receiver_returns_stack_traces
|
remote_errors_include_stack_traces)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def encode_dict(obj: dict) -> str:
|
def encode_dict(obj: dict) -> str:
|
||||||
@ -147,21 +144,20 @@ class MessageProtocol:
|
|||||||
def error_to_response(self, exc: Exception) -> Response:
|
def error_to_response(self, exc: Exception) -> Response:
|
||||||
"""Translate an error to a response."""
|
"""Translate an error to a response."""
|
||||||
|
|
||||||
# Log any errors we got during handling if so desired.
|
# Log any errors we got during handling.
|
||||||
if self.receiver_logs_exceptions:
|
logging.exception('Error in efro.message handling.')
|
||||||
logging.exception('Error in efro.message handling.')
|
|
||||||
|
|
||||||
# If anything goes wrong, return a ErrorResponse instead.
|
# If anything goes wrong, return a ErrorSysResponse instead.
|
||||||
# (either CLEAN or generic REMOTE)
|
# (either CLEAN or generic REMOTE)
|
||||||
if isinstance(exc, CleanError) and self.preserve_clean_errors:
|
if isinstance(exc, CleanError) and self.forward_clean_errors:
|
||||||
return ErrorResponse(
|
return ErrorSysResponse(
|
||||||
error_message=str(exc),
|
error_message=str(exc),
|
||||||
error_type=ErrorResponse.ErrorType.REMOTE_CLEAN)
|
error_type=ErrorSysResponse.ErrorType.REMOTE_CLEAN)
|
||||||
return ErrorResponse(
|
return ErrorSysResponse(
|
||||||
error_message=(traceback.format_exc()
|
error_message=(traceback.format_exc()
|
||||||
if self.receiver_returns_stack_traces else
|
if self.remote_errors_include_stack_traces else
|
||||||
'An internal error has occurred.'),
|
'An internal error has occurred.'),
|
||||||
error_type=ErrorResponse.ErrorType.REMOTE)
|
error_type=ErrorSysResponse.ErrorType.REMOTE)
|
||||||
|
|
||||||
def _to_dict(self, message: Any, ids_by_type: dict[type, int],
|
def _to_dict(self, message: Any, ids_by_type: dict[type, int],
|
||||||
opname: str) -> dict:
|
opname: str) -> dict:
|
||||||
@ -236,7 +232,7 @@ class MessageProtocol:
|
|||||||
rsptypes.append(Response)
|
rsptypes.append(Response)
|
||||||
for rsp_tp in rsptypes:
|
for rsp_tp in rsptypes:
|
||||||
# Skip these as they don't actually show up in code.
|
# Skip these as they don't actually show up in code.
|
||||||
if rsp_tp is EmptyResponse or rsp_tp is ErrorResponse:
|
if rsp_tp is EmptySysResponse or rsp_tp is ErrorSysResponse:
|
||||||
continue
|
continue
|
||||||
if (single_message_type and part == 'sender'
|
if (single_message_type and part == 'sender'
|
||||||
and rsp_tp is not Response):
|
and rsp_tp is not Response):
|
||||||
@ -344,9 +340,9 @@ class MessageProtocol:
|
|||||||
f' """Protocol-specific bound sender."""\n')
|
f' """Protocol-specific bound sender."""\n')
|
||||||
|
|
||||||
def _filt_tp_name(rtype: type[Response]) -> str:
|
def _filt_tp_name(rtype: type[Response]) -> str:
|
||||||
# We accept None to equal EmptyResponse so reflect that
|
# We accept None to equal EmptySysResponse so reflect that
|
||||||
# in the type annotation.
|
# in the type annotation.
|
||||||
return 'None' if rtype is EmptyResponse else rtype.__name__
|
return 'None' if rtype is EmptySysResponse else rtype.__name__
|
||||||
|
|
||||||
# Define handler() overloads for all registered message types.
|
# Define handler() overloads for all registered message types.
|
||||||
if msgtypes:
|
if msgtypes:
|
||||||
@ -441,9 +437,9 @@ class MessageProtocol:
|
|||||||
# Define handler() overloads for all registered message types.
|
# Define handler() overloads for all registered message types.
|
||||||
|
|
||||||
def _filt_tp_name(rtype: type[Response]) -> str:
|
def _filt_tp_name(rtype: type[Response]) -> str:
|
||||||
# We accept None to equal EmptyResponse so reflect that
|
# We accept None to equal EmptySysResponse so reflect that
|
||||||
# in the type annotation.
|
# in the type annotation.
|
||||||
return 'None' if rtype is EmptyResponse else rtype.__name__
|
return 'None' if rtype is EmptySysResponse else rtype.__name__
|
||||||
|
|
||||||
if msgtypes:
|
if msgtypes:
|
||||||
cbgn = 'Awaitable[' if is_async else ''
|
cbgn = 'Awaitable[' if is_async else ''
|
||||||
|
|||||||
@ -11,8 +11,9 @@ import inspect
|
|||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from efro.message._message import (Message, Response, EmptyResponse,
|
from efro.message._message import (Message, Response, EmptySysResponse,
|
||||||
ErrorResponse, UnregisteredMessageIDError)
|
ErrorSysResponse,
|
||||||
|
UnregisteredMessageIDError)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Callable, Awaitable
|
from typing import Any, Callable, Awaitable
|
||||||
@ -123,8 +124,8 @@ class MessageReceiver:
|
|||||||
# types.UnionType above.
|
# types.UnionType above.
|
||||||
responsetypes = (ret, ) # type: ignore
|
responsetypes = (ret, ) # type: ignore
|
||||||
|
|
||||||
# Return type of None translates to EmptyResponse.
|
# Return type of None translates to EmptySysResponse.
|
||||||
responsetypes = tuple(EmptyResponse if r is type(None) else r
|
responsetypes = tuple(EmptySysResponse if r is type(None) else r
|
||||||
for r in responsetypes) # noqa
|
for r in responsetypes) # noqa
|
||||||
|
|
||||||
# Make sure our protocol has this message type registered and our
|
# Make sure our protocol has this message type registered and our
|
||||||
@ -236,13 +237,13 @@ class MessageReceiver:
|
|||||||
response: Response | None) -> str:
|
response: Response | None) -> str:
|
||||||
"""Encode a response provided by the user for sending."""
|
"""Encode a response provided by the user for sending."""
|
||||||
|
|
||||||
# A return value of None equals EmptyResponse.
|
# A return value of None equals EmptySysResponse.
|
||||||
if response is None:
|
if response is None:
|
||||||
response = EmptyResponse()
|
response = EmptySysResponse()
|
||||||
|
|
||||||
assert isinstance(response, Response)
|
assert isinstance(response, Response)
|
||||||
# (user should never explicitly return error-responses)
|
# (user should never explicitly return error-responses)
|
||||||
assert not isinstance(response, ErrorResponse)
|
assert not isinstance(response, ErrorSysResponse)
|
||||||
assert type(response) in message.get_response_types()
|
assert type(response) in message.get_response_types()
|
||||||
response_dict = self.protocol.response_to_dict(response)
|
response_dict = self.protocol.response_to_dict(response)
|
||||||
if self._encode_filter_call is not None:
|
if self._encode_filter_call is not None:
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import logging
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from efro.error import CleanError, RemoteError, CommunicationError
|
from efro.error import CleanError, RemoteError, CommunicationError
|
||||||
from efro.message._message import EmptyResponse, ErrorResponse
|
from efro.message._message import EmptySysResponse, ErrorSysResponse
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Any, Callable, Awaitable
|
from typing import Any, Callable, Awaitable
|
||||||
@ -139,12 +139,12 @@ class MessageSender:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
# Any error in the raw send call gets recorded as either
|
# Any error in the raw send call gets recorded as either
|
||||||
# a local or communication error.
|
# a local or communication error.
|
||||||
return ErrorResponse(
|
return ErrorSysResponse(
|
||||||
error_message=
|
error_message=
|
||||||
f'Error in MessageSender @send_method ({type(exc)}): {exc}',
|
f'Error in MessageSender @send_method ({type(exc)}): {exc}',
|
||||||
error_type=(ErrorResponse.ErrorType.COMMUNICATION
|
error_type=(ErrorSysResponse.ErrorType.COMMUNICATION
|
||||||
if isinstance(exc, CommunicationError) else
|
if isinstance(exc, CommunicationError) else
|
||||||
ErrorResponse.ErrorType.LOCAL))
|
ErrorSysResponse.ErrorType.LOCAL))
|
||||||
return self._decode_raw_response(bound_obj, message, response_encoded)
|
return self._decode_raw_response(bound_obj, message, response_encoded)
|
||||||
|
|
||||||
async def send_split_part_1_async(self, bound_obj: Any,
|
async def send_split_part_1_async(self, bound_obj: Any,
|
||||||
@ -166,13 +166,13 @@ class MessageSender:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
# Any error in the raw send call gets recorded as either
|
# Any error in the raw send call gets recorded as either
|
||||||
# a local or communication error.
|
# a local or communication error.
|
||||||
return ErrorResponse(
|
return ErrorSysResponse(
|
||||||
error_message=
|
error_message=
|
||||||
f'Error in MessageSender @send_async_method ({type(exc)}):'
|
f'Error in MessageSender @send_async_method ({type(exc)}):'
|
||||||
f' {exc}',
|
f' {exc}',
|
||||||
error_type=(ErrorResponse.ErrorType.COMMUNICATION
|
error_type=(ErrorSysResponse.ErrorType.COMMUNICATION
|
||||||
if isinstance(exc, CommunicationError) else
|
if isinstance(exc, CommunicationError) else
|
||||||
ErrorResponse.ErrorType.LOCAL))
|
ErrorSysResponse.ErrorType.LOCAL))
|
||||||
return self._decode_raw_response(bound_obj, message, response_encoded)
|
return self._decode_raw_response(bound_obj, message, response_encoded)
|
||||||
|
|
||||||
def send_split_part_2(self, message: Message,
|
def send_split_part_2(self, message: Message,
|
||||||
@ -214,13 +214,13 @@ class MessageSender:
|
|||||||
# If we got to this point, we successfully communicated
|
# If we got to this point, we successfully communicated
|
||||||
# with the other end so errors represent protocol mismatches
|
# with the other end so errors represent protocol mismatches
|
||||||
# or other invalid data. For now let's just log it but perhaps
|
# or other invalid data. For now let's just log it but perhaps
|
||||||
# we'd want to somehow embed it in the ErrorResponse to be
|
# we'd want to somehow embed it in the ErrorSysResponse to be
|
||||||
# available directly to the user later.
|
# available directly to the user later.
|
||||||
logging.exception('Error decoding raw response')
|
logging.exception('Error decoding raw response')
|
||||||
response = ErrorResponse(
|
response = ErrorSysResponse(
|
||||||
error_message=
|
error_message=
|
||||||
'Error decoding raw response; see log for details.',
|
'Error decoding raw response; see log for details.',
|
||||||
error_type=ErrorResponse.ErrorType.LOCAL)
|
error_type=ErrorSysResponse.ErrorType.LOCAL)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def _unpack_raw_response(self, raw_response: Response) -> Response | None:
|
def _unpack_raw_response(self, raw_response: Response) -> Response | None:
|
||||||
@ -232,25 +232,25 @@ class MessageSender:
|
|||||||
run such that any raised Exception is active when the callback
|
run such that any raised Exception is active when the callback
|
||||||
fires; not on the thread where the message was sent.
|
fires; not on the thread where the message was sent.
|
||||||
"""
|
"""
|
||||||
# EmptyResponse translates to None
|
# EmptySysResponse translates to None
|
||||||
if isinstance(raw_response, EmptyResponse):
|
if isinstance(raw_response, EmptySysResponse):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Some error occurred. Raise a local Exception for it.
|
# Some error occurred. Raise a local Exception for it.
|
||||||
if isinstance(raw_response, ErrorResponse):
|
if isinstance(raw_response, ErrorSysResponse):
|
||||||
|
|
||||||
if (raw_response.error_type is
|
if (raw_response.error_type is
|
||||||
ErrorResponse.ErrorType.COMMUNICATION):
|
ErrorSysResponse.ErrorType.COMMUNICATION):
|
||||||
raise CommunicationError(raw_response.error_message)
|
raise CommunicationError(raw_response.error_message)
|
||||||
|
|
||||||
# If something went wrong on *our* end of the connection,
|
# If something went wrong on *our* end of the connection,
|
||||||
# don't say it was a remote error.
|
# don't say it was a remote error.
|
||||||
if raw_response.error_type is ErrorResponse.ErrorType.LOCAL:
|
if raw_response.error_type is ErrorSysResponse.ErrorType.LOCAL:
|
||||||
raise RuntimeError(raw_response.error_message)
|
raise RuntimeError(raw_response.error_message)
|
||||||
|
|
||||||
# If they want to support clean errors, do those.
|
# If they want to support clean errors, do those.
|
||||||
if (self.protocol.preserve_clean_errors and raw_response.error_type
|
if (self.protocol.forward_clean_errors and raw_response.error_type
|
||||||
is ErrorResponse.ErrorType.REMOTE_CLEAN):
|
is ErrorSysResponse.ErrorType.REMOTE_CLEAN):
|
||||||
raise CleanError(raw_response.error_message)
|
raise CleanError(raw_response.error_message)
|
||||||
|
|
||||||
# Everything else gets lumped in as a remote error.
|
# Everything else gets lumped in as a remote error.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user