mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-27 01:13:13 +08:00
subsystem cleanup
This commit is contained in:
parent
f1ba22170d
commit
26cc24d345
@ -4072,50 +4072,50 @@
|
||||
"build/assets/workspace/ninjafightplug.py": "https://files.ballistica.net/cache/ba1/c5/09/4f10b8a21ba87aa5509cff7a164b",
|
||||
"build/assets/workspace/onslaughtplug.py": "https://files.ballistica.net/cache/ba1/ff/0a/a354984f9c074dab0676ac7e4877",
|
||||
"build/assets/workspace/runaroundplug.py": "https://files.ballistica.net/cache/ba1/2a/1c/9ee5db6d1bceca7fa6638fb8abde",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/d2/f1/c7ecb66769e793ea1ae2427ec540",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/89/4f/99fb1371ff083d135f3c8251ead1",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/4a/5c/076d47a516a1b9e5d3b7e7930a30",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/ab/63/caf01d35edabba0359e0444bf898",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/25/25/e0a9d955037c5375558b5bef7736",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/b8/6d/ef564300e7189964e133be1c6d7f",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/b4/50/9e1fcab11d5e329750ef64f38a94",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/a6/62/3ae503b2027dad675a8a4dae8d75",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/4c/8b/44c018a2bf5ff79951d28525d230",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/67/d9/1f49882d9f50051e5a77c8b37856",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/2f/26/01c0bb3750c49e8b27032e3506b4",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/c7/90/48bccd35318bbf7693417a50c96d",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/13/92/949362dd74ca933d11b8081c366b",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/20/a0/6f048f2a3b9d64851420de719d3a",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/3a/f8/bca8437e4ac8403d46efdd9b0173",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/d9/3d/5ac299f7f2e7acfdea2a297e1c57",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/82/ff/41b875d2048dee0d47ca5173f8e6",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/18/45/1b8328009e7e7aaf4d840170427a",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/f5/63/2b15e84c989a0f58c8ea6c78c379",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/1f/7f/ed15584c8a49e20a4f081622214f",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/de/fd/21a635bb0a73e252885acb7f6628",
|
||||
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/1b/d0/f94119594604e67652924b434416",
|
||||
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/13/18/48dc17a460c2ee0fa4a22b2d8005",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/c2/2d/bf75444af834501f9e443618786c",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/ec/88/ab5016ebb0ad9bdce10301267793",
|
||||
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/2c/1d/e26f457ba90fdd700dee7cc6252b",
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/04/f5/59af762745bef4e8660e95a07226",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/0f/32/d374d10065061ee0a6ca67b6a4af",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/94/30/c61c2114828f360d21bf81d2c39a",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/4c/2b/c6aa202a104e49c82461e6d084af",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/94/ff/ac435f0ade27ad8220c945e77c2b",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/21/b5/7f010c0be5f14b2b14a823afba57",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/12/75/79f8ec088e1c946e9d60db3e91cf",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/d9/e1/4791926365ecf2a19b9528163ae0",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/e0/99/a86cb331308904b24f1a48342d2d",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/94/7d/aa5e4fb93de4681bb4bf002e28cf",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/d1/cf/fa4136e93ded15dbab93fd57d1b8",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/b4/0e/1522c860e33f5001f71cfe12aa7a",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/a5/fb/cb9bb39ac98d0c5b0747094f54c2",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/63/60/cba991152f215d0e6ff1b0801a54",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/2a/29/e323dbaaa208c40a569d85a82527",
|
||||
"build/prefab/lib/linux_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/0f/d7/034299d84dde9b8a36933c3d6640",
|
||||
"build/prefab/lib/linux_arm64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/8c/0c/209d7fef648785021b2442b92a37",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/3e/d6/f3e8c02c82379d78d15bb1bb9d41",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/de/6b/14e766a2d2db860276553b7c3e9d",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/db/d6/42e603000c13737e60f693336d4e",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/dd/e3/c1b35888db082abde395c7197d79",
|
||||
"build/prefab/lib/linux_x86_64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/95/86/052441f8ccaa13006c9d38dbb79d",
|
||||
"build/prefab/lib/linux_x86_64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/64/40/f06fe4f0d7537e50b6e880c6590c",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/b2/fe/09cba839bcfdc19b29f6acf4c129",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/ed/bf/45c4771f7d77985b26f3612591e0",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/54/10/a2c3d3a1076eb1b9812b736ca34b",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/08/40/aaa523c2752e7128368dcbb9746c",
|
||||
"build/prefab/lib/mac_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/c3/2d/e1e05f01647e92c65cbcc3599705",
|
||||
"build/prefab/lib/mac_arm64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/89/cd/db7719b6851e28d7969d807be3d8",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/78/c0/3c8e4b03e3d92675a4c255242ccb",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/37/43/84a1fc8169db34054378f11fe4c1",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/5b/cb/4be9adf2aa44aae442bda6f39112",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/7d/4d/e6f90dbe842358db16b060fd3187",
|
||||
"build/prefab/lib/mac_x86_64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/3d/92/ea42decffa28fb7540d72248f79e",
|
||||
"build/prefab/lib/mac_x86_64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/8a/34/5d1b029d1a393139890f600ff91d",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/f6/a3/753d976d43b45062184414098306",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/98/e0/0772edc2ae173e7f8ab07d4e1230",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/ba/f0/c7dcdd6472a348663d104d490e77",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/94/a1/3eed726b9bf0dac2e44cca23c1ba",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/09/47/a0d5f2088c43798bc60f72204ba5",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/5f/9a/542f9cb3ddfb702f81756047e7dc",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/c9/57/641e99496162ed453e6a1a8aea2e",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/0c/8b/37e6fdd08cb1dc1df818d550f7a3",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/68/82/a261d09580d572c25982b15efaa2",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/b9/91/34ee2461cf291fd765e9ab1cb09e",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/8f/00/84bd3b34227305d59202195c2032",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/ef/f4/61c64323efa3fd0b1e6ef2042d2e",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/43/58/6797ab58417599aefa2719e9ed70",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/8d/9d/6e683b4a8ff61138041318470352",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/b6/1a/ad49bd349c7c0f59a6dcf2efd70e",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/df/7a/6bdd5096bb65a99d39d922b1743a",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/fb/15/19719ece74758579110612e93adb",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/80/fe/13417c54861d3bc076c173590175",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/2b/32/3d8e3e131fd27908742aac0df030",
|
||||
"src/assets/ba_data/python/babase/_mgen/__init__.py": "https://files.ballistica.net/cache/ba1/52/c6/c11130af7b10d6c0321add5518fa",
|
||||
"src/assets/ba_data/python/babase/_mgen/enums.py": "https://files.ballistica.net/cache/ba1/38/c3/1dedd5e74f2508efc5974c8815a1",
|
||||
"src/ballistica/base/mgen/pyembed/binding_base.inc": "https://files.ballistica.net/cache/ba1/d5/4a/0e480a855ce83709bd7f6761107d",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
### 1.7.20 (build 21045, api 8, 2023-06-03)
|
||||
### 1.7.20 (build 21046, api 8, 2023-06-04)
|
||||
|
||||
- This seems like a good time for a `refactoring` release in anticipation of
|
||||
changes coming in 1.8. Basically this means that a lot of things will be
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
"ba_data/python/babase/__pycache__/_appintent.cpython-311.opt-1.pyc",
|
||||
"ba_data/python/babase/__pycache__/_appmode.cpython-311.opt-1.pyc",
|
||||
"ba_data/python/babase/__pycache__/_appmodeselector.cpython-311.opt-1.pyc",
|
||||
"ba_data/python/babase/__pycache__/_appsubsystem.cpython-311.opt-1.pyc",
|
||||
"ba_data/python/babase/__pycache__/_apputils.cpython-311.opt-1.pyc",
|
||||
"ba_data/python/babase/__pycache__/_assetmanager.cpython-311.opt-1.pyc",
|
||||
"ba_data/python/babase/__pycache__/_asyncio.cpython-311.opt-1.pyc",
|
||||
@ -34,6 +35,7 @@
|
||||
"ba_data/python/babase/_appintent.py",
|
||||
"ba_data/python/babase/_appmode.py",
|
||||
"ba_data/python/babase/_appmodeselector.py",
|
||||
"ba_data/python/babase/_appsubsystem.py",
|
||||
"ba_data/python/babase/_apputils.py",
|
||||
"ba_data/python/babase/_assetmanager.py",
|
||||
"ba_data/python/babase/_asyncio.py",
|
||||
|
||||
@ -142,6 +142,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
|
||||
$(BUILD_DIR)/ba_data/python/babase/_appintent.py \
|
||||
$(BUILD_DIR)/ba_data/python/babase/_appmode.py \
|
||||
$(BUILD_DIR)/ba_data/python/babase/_appmodeselector.py \
|
||||
$(BUILD_DIR)/ba_data/python/babase/_appsubsystem.py \
|
||||
$(BUILD_DIR)/ba_data/python/babase/_apputils.py \
|
||||
$(BUILD_DIR)/ba_data/python/babase/_assetmanager.py \
|
||||
$(BUILD_DIR)/ba_data/python/babase/_asyncio.py \
|
||||
@ -413,6 +414,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
|
||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_appintent.cpython-311.opt-1.pyc \
|
||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_appmode.cpython-311.opt-1.pyc \
|
||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_appmodeselector.cpython-311.opt-1.pyc \
|
||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_appsubsystem.cpython-311.opt-1.pyc \
|
||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_apputils.cpython-311.opt-1.pyc \
|
||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_assetmanager.cpython-311.opt-1.pyc \
|
||||
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_asyncio.cpython-311.opt-1.pyc \
|
||||
|
||||
@ -35,6 +35,7 @@ from _babase import (
|
||||
|
||||
from babase._appintent import AppIntent, AppIntentDefault, AppIntentExec
|
||||
from babase._appmode import AppMode
|
||||
from babase._appsubsystem import AppSubsystem
|
||||
from babase._accountv2 import AccountV2Handle
|
||||
from babase._plugin import PotentialPlugin, Plugin, PluginSubsystem
|
||||
from babase._app import App
|
||||
@ -161,6 +162,7 @@ __all__ = [
|
||||
'AppIntentDefault',
|
||||
'AppIntentExec',
|
||||
'AppMode',
|
||||
'AppSubsystem',
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -27,11 +27,9 @@ if TYPE_CHECKING:
|
||||
|
||||
from efro.log import LogHandler
|
||||
import babase
|
||||
from babase._cloud import CloudSubsystem
|
||||
from babase import CloudSubsystem, AppIntent, AppMode, AppSubsystem
|
||||
from babase._accountv2 import AccountV2Subsystem
|
||||
from babase._apputils import AppHealthMonitor
|
||||
from babase._appintent import AppIntent
|
||||
from babase._appmode import AppMode
|
||||
|
||||
# __FEATURESET_APP_SUBSYSTEM_IMPORTS_BEGIN__
|
||||
# This section generated by batools.appmodule; do not edit.
|
||||
@ -58,6 +56,7 @@ class App:
|
||||
# Implementations for these will be filled in by internal libs.
|
||||
accounts: AccountV2Subsystem
|
||||
cloud: CloudSubsystem
|
||||
plugins: PluginSubsystem
|
||||
|
||||
# log_handler: LogHandler
|
||||
health_monitor: AppHealthMonitor
|
||||
@ -237,6 +236,8 @@ class App:
|
||||
|
||||
self.state = self.State.INITIAL
|
||||
|
||||
self._subsystems: list[AppSubsystem] = []
|
||||
|
||||
self._app_bootstrapping_complete = False
|
||||
self._called_on_app_launching = False
|
||||
self._launch_completed = False
|
||||
@ -279,7 +280,6 @@ class App:
|
||||
|
||||
self.components = AppComponentSubsystem()
|
||||
self.meta = MetadataSubsystem()
|
||||
self.plugins = PluginSubsystem()
|
||||
self.lang = LanguageSubsystem()
|
||||
self.net = NetworkSubsystem()
|
||||
self.workspaces = WorkspaceSubsystem()
|
||||
@ -299,9 +299,25 @@ class App:
|
||||
"""Called after we are inited and assigned to babase.app."""
|
||||
|
||||
# NOTE: the reason we need a postinit here is that
|
||||
# some of this stuff might try importing babase.app and that doesn't
|
||||
# some of this stuff accesses babase.app and that doesn't
|
||||
# exist yet as of our __init__() call.
|
||||
|
||||
self.plugins = PluginSubsystem()
|
||||
|
||||
def register_subsystem(self, subsystem: AppSubsystem) -> None:
|
||||
"""Called by the AppSubsystem class. Do not use directly."""
|
||||
|
||||
# We only allow registering new subsystems if we've not yet
|
||||
# reached the 'running' state. This ensures that all subsystems
|
||||
# receive a consistent set of callbacks starting with
|
||||
# on_app_running().
|
||||
if self._called_on_app_running:
|
||||
raise RuntimeError(
|
||||
'Subsystems cannot be registered after the'
|
||||
' app has reached the running state.'
|
||||
)
|
||||
self._subsystems.append(subsystem)
|
||||
|
||||
def _threadpool_no_wait_done(self, fut: Future) -> None:
|
||||
try:
|
||||
fut.result()
|
||||
@ -357,8 +373,8 @@ class App:
|
||||
|
||||
Intent defines what the app is trying to do at a given time.
|
||||
This call is asynchronous; the intent switch will happen in the
|
||||
logic thread in the near future. If set_intent is
|
||||
called repeatedly before the change takes place, the last intent
|
||||
logic thread in the near future. If set_intent is called
|
||||
repeatedly before the change takes place, the final intent to be
|
||||
set will be used.
|
||||
"""
|
||||
|
||||
@ -467,7 +483,11 @@ class App:
|
||||
self._update_state()
|
||||
|
||||
def on_app_launching(self) -> None:
|
||||
"""Called when the app is entering the launching state."""
|
||||
"""Called when the app enters the launching state.
|
||||
|
||||
Here we can put together subsystems and other pieces for the
|
||||
app, but most things should not be doing any work yet.
|
||||
"""
|
||||
# pylint: disable=cyclic-import
|
||||
from babase import _asyncio
|
||||
from babase import _appconfig
|
||||
@ -494,6 +514,9 @@ class App:
|
||||
# Get meta-system scanning built-in stuff in the bg.
|
||||
self.meta.start_scan(scan_complete_cb=self.on_meta_scan_complete)
|
||||
|
||||
if self.plus is not None:
|
||||
self.plus.on_app_launching()
|
||||
|
||||
self.accounts.on_app_launching()
|
||||
|
||||
# Make sure this runs after we init our accounts stuff, since
|
||||
@ -507,27 +530,47 @@ class App:
|
||||
self._launch_completed = True
|
||||
self._update_state()
|
||||
|
||||
def on_app_loading(self) -> None:
|
||||
"""Called when the app is entering the loading state."""
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
def on_meta_scan_complete(self) -> None:
|
||||
"""Called when meta-scan is done doing its thing."""
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
# Now that we know what's out there, build our final plugin set.
|
||||
self.plugins.on_meta_scan_complete()
|
||||
|
||||
def on_app_running(self) -> None:
|
||||
"""Called when the app is entering the running state."""
|
||||
def on_app_loading(self) -> None:
|
||||
"""Called when the app enters the loading state.
|
||||
|
||||
At this point, all built-in pieces of the app should be in place
|
||||
and can start doing 'work'. Though at a high level, the goal of
|
||||
the app at this point is only to sign in to initial accounts,
|
||||
download workspaces, and otherwise prepare itself to really
|
||||
'run'.
|
||||
"""
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
# Let the native layer know.
|
||||
def on_app_running(self) -> None:
|
||||
"""Called when the app enters the running state.
|
||||
|
||||
At this point, all workspaces, initial accounts, etc. are in place
|
||||
and we can actually get started doing whatever we're gonna do.
|
||||
"""
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
# Let our native layer know.
|
||||
_babase.on_app_running()
|
||||
|
||||
# Set a default app-mode-selector. Plugins can then override
|
||||
# this if they want.
|
||||
# this if they want in the on_app_running callback below.
|
||||
self.mode_selector = self.DefaultAppModeSelector()
|
||||
|
||||
self.plugins.on_app_running()
|
||||
# Inform all app subsystems in the same order they were inited.
|
||||
for subsystem in self._subsystems:
|
||||
try:
|
||||
subsystem.on_app_running()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_running for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
# If 'exec' code was provided to the app, always kick that off
|
||||
# here as an intent.
|
||||
@ -562,7 +605,7 @@ class App:
|
||||
# This section generated by batools.appmodule; do not edit.
|
||||
|
||||
# Hmm; need to think about how we auto-construct this; how
|
||||
# do we determine which app modes to check and in what
|
||||
# should we determine which app modes to check and in what
|
||||
# order?
|
||||
import bascenev1
|
||||
|
||||
@ -627,27 +670,43 @@ class App:
|
||||
|
||||
def on_app_pause(self) -> None:
|
||||
"""Called when the app goes to a paused state."""
|
||||
self.cloud.on_app_pause()
|
||||
self.plugins.on_app_pause()
|
||||
self.health_monitor.on_app_pause()
|
||||
if self.classic is not None:
|
||||
self.classic.on_app_pause()
|
||||
assert _babase.in_logic_thread()
|
||||
|
||||
# Pause all app subsystems in the opposite order they were inited.
|
||||
for subsystem in reversed(self._subsystems):
|
||||
try:
|
||||
subsystem.on_app_pause()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_pause for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
def on_app_resume(self) -> None:
|
||||
"""Called when resuming."""
|
||||
self.fg_state += 1
|
||||
self.cloud.on_app_resume()
|
||||
self.plugins.on_app_resume()
|
||||
self.health_monitor.on_app_resume()
|
||||
if self.classic is not None:
|
||||
self.classic.on_app_resume()
|
||||
|
||||
# Resume all app subsystems in the same order they were inited.
|
||||
for subsystem in self._subsystems:
|
||||
try:
|
||||
subsystem.on_app_resume()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_resume for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
def on_app_shutdown(self) -> None:
|
||||
"""(internal)"""
|
||||
self.state = self.State.SHUTTING_DOWN
|
||||
self.plugins.on_app_shutdown()
|
||||
if self.classic is not None:
|
||||
self.classic.on_app_shutdown()
|
||||
|
||||
# Shutdown all app subsystems in the opposite order they were
|
||||
# inited.
|
||||
for subsystem in reversed(self._subsystems):
|
||||
try:
|
||||
subsystem.on_app_shutdown()
|
||||
except Exception:
|
||||
logging.exception(
|
||||
'Error in on_app_shutdown for subsystem %s.', subsystem
|
||||
)
|
||||
|
||||
def read_config(self) -> None:
|
||||
"""(internal)"""
|
||||
|
||||
41
src/assets/ba_data/python/babase/_appsubsystem.py
Normal file
41
src/assets/ba_data/python/babase/_appsubsystem.py
Normal file
@ -0,0 +1,41 @@
|
||||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Provides the AppSubsystem base class."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _babase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from babase._app import App
|
||||
|
||||
|
||||
class AppSubsystem:
|
||||
"""Base class for an app subsystem.
|
||||
|
||||
Category: **App Classes**
|
||||
|
||||
An app 'subsystem' is a bit of a vague term, as pieces of the app
|
||||
can technically be any class and are not required to use this, but
|
||||
building one out of this base class provides some conveniences such
|
||||
as predefined callbacks during app state changes.
|
||||
|
||||
Subsystems must be registered with the app before it reaches the
|
||||
'running' state.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
_babase.app.register_subsystem(self)
|
||||
|
||||
def on_app_running(self) -> None:
|
||||
"""Called when the app reaches the running state."""
|
||||
|
||||
def on_app_pause(self) -> None:
|
||||
"""Called when the app enters the paused state."""
|
||||
|
||||
def on_app_resume(self) -> None:
|
||||
"""Called when the app exits the paused state."""
|
||||
|
||||
def on_app_shutdown(self) -> None:
|
||||
"""Called when the app is shutting down."""
|
||||
@ -14,6 +14,7 @@ from efro.call import tpartial
|
||||
from efro.log import LogLevel
|
||||
from efro.dataclassio import ioprepped, dataclass_to_json, dataclass_from_json
|
||||
import _babase
|
||||
from babase._appsubsystem import AppSubsystem
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, TextIO
|
||||
@ -78,8 +79,8 @@ def handle_v1_cloud_log() -> None:
|
||||
if app.classic is None or app.plus is None:
|
||||
if _babase.do_once():
|
||||
logging.warning(
|
||||
'handle_v1_cloud_log should not be used'
|
||||
' without classic or plus.'
|
||||
'handle_v1_cloud_log should not be called'
|
||||
' without classic and plus present.'
|
||||
)
|
||||
return
|
||||
|
||||
@ -350,11 +351,12 @@ def log_dumped_app_state() -> None:
|
||||
logging.exception('Error logging dumped app state.')
|
||||
|
||||
|
||||
class AppHealthMonitor:
|
||||
class AppHealthMonitor(AppSubsystem):
|
||||
"""Logs things like app-not-responding issues."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
assert _babase.in_logic_thread()
|
||||
super().__init__()
|
||||
self._running = True
|
||||
self._thread = Thread(target=self._app_monitor_thread_main, daemon=True)
|
||||
self._thread.start()
|
||||
@ -420,12 +422,10 @@ class AppHealthMonitor:
|
||||
self._first_check = False
|
||||
|
||||
def on_app_pause(self) -> None:
|
||||
"""Should be called when the app pauses."""
|
||||
assert _babase.in_logic_thread()
|
||||
self._running = False
|
||||
|
||||
def on_app_resume(self) -> None:
|
||||
"""Should be called when the app resumes."""
|
||||
assert _babase.in_logic_thread()
|
||||
self._running = True
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import logging
|
||||
from typing import TYPE_CHECKING, overload
|
||||
|
||||
import _babase
|
||||
from babase._appsubsystem import AppSubsystem
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable, Any
|
||||
@ -22,7 +23,7 @@ DEBUG_LOG = False
|
||||
# internal protocols.
|
||||
|
||||
|
||||
class CloudSubsystem:
|
||||
class CloudSubsystem(AppSubsystem):
|
||||
"""Manages communication with cloud components."""
|
||||
|
||||
def is_connected(self) -> bool:
|
||||
@ -33,12 +34,6 @@ class CloudSubsystem:
|
||||
"""
|
||||
return False # Needs to be overridden
|
||||
|
||||
def on_app_pause(self) -> None:
|
||||
"""Should be called when the app pauses."""
|
||||
|
||||
def on_app_resume(self) -> None:
|
||||
"""Should be called when the app resumes."""
|
||||
|
||||
def on_connectivity_changed(self, connected: bool) -> None:
|
||||
"""Called when cloud connectivity state changes."""
|
||||
if DEBUG_LOG:
|
||||
|
||||
@ -9,6 +9,7 @@ from typing import TYPE_CHECKING
|
||||
from dataclasses import dataclass
|
||||
|
||||
import _babase
|
||||
from babase._appsubsystem import AppSubsystem
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any
|
||||
@ -16,7 +17,7 @@ if TYPE_CHECKING:
|
||||
import babase
|
||||
|
||||
|
||||
class PluginSubsystem:
|
||||
class PluginSubsystem(AppSubsystem):
|
||||
"""Subsystem for plugin handling in the app.
|
||||
|
||||
Category: **App Classes**
|
||||
@ -28,6 +29,7 @@ class PluginSubsystem:
|
||||
AUTO_ENABLE_NEW_PLUGINS_DEFAULT = True
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.potential_plugins: list[babase.PotentialPlugin] = []
|
||||
self.active_plugins: dict[str, babase.Plugin] = {}
|
||||
|
||||
@ -46,6 +48,13 @@ class PluginSubsystem:
|
||||
results = _babase.app.meta.scanresults
|
||||
assert results is not None
|
||||
|
||||
auto_enable_new_plugins = (
|
||||
_babase.app.config.get(
|
||||
self.AUTO_ENABLE_NEW_PLUGINS_CONFIG_KEY,
|
||||
self.AUTO_ENABLE_NEW_PLUGINS_DEFAULT,
|
||||
)
|
||||
is True
|
||||
)
|
||||
# Create a potential-plugin for each class we found in the scan.
|
||||
for class_path in results.exports_of_class(Plugin):
|
||||
plugs.potential_plugins.append(
|
||||
@ -55,13 +64,7 @@ class PluginSubsystem:
|
||||
available=True,
|
||||
)
|
||||
)
|
||||
if (
|
||||
_babase.app.config.get(
|
||||
self.AUTO_ENABLE_NEW_PLUGINS_CONFIG_KEY,
|
||||
self.AUTO_ENABLE_NEW_PLUGINS_DEFAULT,
|
||||
)
|
||||
is True
|
||||
):
|
||||
if auto_enable_new_plugins:
|
||||
if class_path not in plugstates:
|
||||
# Go ahead and enable new plugins by default, but we'll
|
||||
# inform the user that they need to restart to pick them up.
|
||||
@ -72,12 +75,9 @@ class PluginSubsystem:
|
||||
|
||||
plugs.potential_plugins.sort(key=lambda p: p.class_path)
|
||||
|
||||
# Note: these days we complete meta-scan and immediately activate
|
||||
# plugins, so we don't need the message about 'restart to activate'
|
||||
# anymore.
|
||||
# FIXME: We actually now have an option to NOT activate new plugins
|
||||
# so we should selectively re-enable this.
|
||||
if found_new and bool(False):
|
||||
# If we're *not* auto-enabling new plugins, at least let the
|
||||
# user know we found something new.
|
||||
if found_new and not auto_enable_new_plugins:
|
||||
_babase.screenmessage(
|
||||
Lstr(resource='pluginsDetectedText'), color=(0, 1, 0)
|
||||
)
|
||||
@ -87,7 +87,6 @@ class PluginSubsystem:
|
||||
_babase.app.config.commit()
|
||||
|
||||
def on_app_running(self) -> None:
|
||||
"""Should be called when the app reaches the running state."""
|
||||
# Load up our plugins and go ahead and call their on_app_running calls.
|
||||
self.load_plugins()
|
||||
for plugin in self.active_plugins.values():
|
||||
@ -99,7 +98,6 @@ class PluginSubsystem:
|
||||
_error.print_exception('Error in plugin on_app_running()')
|
||||
|
||||
def on_app_pause(self) -> None:
|
||||
"""Called when the app goes to a suspended state."""
|
||||
for plugin in self.active_plugins.values():
|
||||
try:
|
||||
plugin.on_app_pause()
|
||||
@ -109,7 +107,6 @@ class PluginSubsystem:
|
||||
_error.print_exception('Error in plugin on_app_pause()')
|
||||
|
||||
def on_app_resume(self) -> None:
|
||||
"""Run when the app resumes from a suspended state."""
|
||||
for plugin in self.active_plugins.values():
|
||||
try:
|
||||
plugin.on_app_resume()
|
||||
@ -119,7 +116,6 @@ class PluginSubsystem:
|
||||
_error.print_exception('Error in plugin on_app_resume()')
|
||||
|
||||
def on_app_shutdown(self) -> None:
|
||||
"""Called when the app is being closed."""
|
||||
for plugin in self.active_plugins.values():
|
||||
try:
|
||||
plugin.on_app_shutdown()
|
||||
|
||||
@ -10,6 +10,7 @@ from typing import TYPE_CHECKING
|
||||
import _babase
|
||||
import _bauiv1
|
||||
import bascenev1
|
||||
from babase._appsubsystem import AppSubsystem
|
||||
from babase._general import AppTime
|
||||
import _baclassic
|
||||
from baclassic._music import MusicSubsystem
|
||||
@ -34,7 +35,7 @@ if TYPE_CHECKING:
|
||||
from baclassic._net import MasterServerCallback
|
||||
|
||||
|
||||
class ClassicSubsystem:
|
||||
class ClassicSubsystem(AppSubsystem):
|
||||
"""Subsystem for classic functionality in the app.
|
||||
|
||||
The single shared instance of this app can be accessed at
|
||||
@ -55,6 +56,7 @@ class ClassicSubsystem:
|
||||
from baclassic._music import MusicPlayMode # FIXME move 2 subsys
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._env = _babase.env()
|
||||
|
||||
self.accounts = AccountV1Subsystem()
|
||||
@ -252,16 +254,13 @@ class ClassicSubsystem:
|
||||
self.accounts.on_app_launching()
|
||||
|
||||
def on_app_pause(self) -> None:
|
||||
"""Called when the app is getting paused."""
|
||||
self.accounts.on_app_pause()
|
||||
|
||||
def on_app_resume(self) -> None:
|
||||
"""Called when the app is getting resumed."""
|
||||
self.accounts.on_app_resume()
|
||||
self.music.on_app_resume()
|
||||
|
||||
def on_app_shutdown(self) -> None:
|
||||
"""Called when the app is shutting down."""
|
||||
self.music.on_app_shutdown()
|
||||
|
||||
def pause(self) -> None:
|
||||
|
||||
@ -30,7 +30,7 @@ if TYPE_CHECKING:
|
||||
|
||||
# Build number and version of the ballistica binary we expect to be
|
||||
# using.
|
||||
TARGET_BALLISTICA_BUILD = 21045
|
||||
TARGET_BALLISTICA_BUILD = 21046
|
||||
TARGET_BALLISTICA_VERSION = '1.7.20'
|
||||
|
||||
_g_env_config: EnvConfig | None = None
|
||||
|
||||
@ -6,12 +6,15 @@ from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _baplus
|
||||
from babase._appsubsystem import AppSubsystem
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Callable, Any
|
||||
|
||||
from babase import App
|
||||
|
||||
class PlusSubsystem:
|
||||
|
||||
class PlusSubsystem(AppSubsystem):
|
||||
"""Subsystem for plus functionality in the app.
|
||||
|
||||
The single shared instance of this app can be accessed at
|
||||
@ -26,9 +29,6 @@ class PlusSubsystem:
|
||||
# type-checking purposes. Maybe there's some smart way we could skip
|
||||
# the overhead of this wrapper at runtime.
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def add_v1_account_transaction(
|
||||
transaction: dict, callback: Callable | None = None
|
||||
@ -157,7 +157,7 @@ class PlusSubsystem:
|
||||
@staticmethod
|
||||
def on_app_launching() -> None:
|
||||
"""(internal)"""
|
||||
return _baplus.on_app_launching()
|
||||
_baplus.on_app_launching()
|
||||
|
||||
@staticmethod
|
||||
def power_ranking_query(callback: Callable, season: Any = None) -> None:
|
||||
|
||||
@ -460,8 +460,14 @@ void BaseFeatureSet::ScreenMessage(const std::string& s,
|
||||
|
||||
void BaseFeatureSet::V1CloudLog(const std::string& msg) {
|
||||
// If we've got a fully running app environment, let the Python layer
|
||||
// handle logs. It will group log messages intelligently and ship them
|
||||
// handle this. It will group log messages intelligently and ship them
|
||||
// to the master server with various other context info included.
|
||||
|
||||
// We currently need both plus and classic for this system to function.
|
||||
if (!(HavePlus() && HaveClassic())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (app_running_) {
|
||||
python->objs().PushCall(BasePython::ObjID::kHandleV1CloudLogCall);
|
||||
} else {
|
||||
|
||||
@ -53,7 +53,7 @@ void BasePython::AddPythonClasses(PyObject* module) {
|
||||
// FIXME: should be able to do this in Python bootstrapping
|
||||
// code.
|
||||
auto register_call =
|
||||
PythonRef(PyImport_ImportModule("collections.abc"), PythonRef::kSteal)
|
||||
PythonRef::Stolen(PyImport_ImportModule("collections.abc"))
|
||||
.GetAttr("Sequence")
|
||||
.GetAttr("register");
|
||||
PythonRef args(Py_BuildValue("(O)", vec3), PythonRef::kSteal);
|
||||
@ -68,7 +68,7 @@ void BasePython::ImportPythonObjs() {
|
||||
|
||||
void BasePython::SoftImportPlus() {
|
||||
auto gil{Python::ScopedInterpreterLock()};
|
||||
auto result = PythonRef::Stolen(PyImport_ImportModule("_baplus"));
|
||||
auto result = PythonRef::StolenSoft(PyImport_ImportModule("_baplus"));
|
||||
if (!result.Exists()) {
|
||||
// Ignore any errors here for now. All that will matter is whether plus
|
||||
// gave us its interface.
|
||||
@ -78,7 +78,7 @@ void BasePython::SoftImportPlus() {
|
||||
|
||||
void BasePython::SoftImportClassic() {
|
||||
auto gil{Python::ScopedInterpreterLock()};
|
||||
auto result = PythonRef::Stolen(PyImport_ImportModule("_baclassic"));
|
||||
auto result = PythonRef::StolenSoft(PyImport_ImportModule("_baclassic"));
|
||||
if (!result.Exists()) {
|
||||
// Ignore any errors here for now. All that will matter is whether plus
|
||||
// gave us its interface.
|
||||
@ -88,7 +88,7 @@ void BasePython::SoftImportClassic() {
|
||||
|
||||
void BasePython::SoftImportUIV1() {
|
||||
auto gil{Python::ScopedInterpreterLock()};
|
||||
auto result = PythonRef::Stolen(PyImport_ImportModule("_bauiv1"));
|
||||
auto result = PythonRef::StolenSoft(PyImport_ImportModule("_bauiv1"));
|
||||
if (!result.Exists()) {
|
||||
// Ignore any errors here for now. All that will matter is whether plus
|
||||
// gave us its interface.
|
||||
|
||||
@ -181,7 +181,7 @@ void CorePython::ReleaseMainThreadGIL() {
|
||||
|
||||
void CorePython::SoftImportBase() {
|
||||
auto gil{Python::ScopedInterpreterLock()};
|
||||
auto result = PythonRef::Stolen(PyImport_ImportModule("_babase"));
|
||||
auto result = PythonRef::StolenSoft(PyImport_ImportModule("_babase"));
|
||||
if (!result.Exists()) {
|
||||
// Ignore any errors here for now. All that will matter is whether base
|
||||
// gave us its interface.
|
||||
|
||||
@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't modify them here.
|
||||
const int kEngineBuildNumber = 21045;
|
||||
const int kEngineBuildNumber = 21046;
|
||||
const char* kEngineVersion = "1.7.20";
|
||||
|
||||
auto MonolithicMain(const core::CoreConfig& core_config) -> int {
|
||||
|
||||
@ -19,56 +19,41 @@ using core::g_core;
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "RedundantCast"
|
||||
|
||||
PythonRef::PythonRef(PyObject* obj_in, ReferenceBehavior b) {
|
||||
assert(Python::HaveGIL());
|
||||
static void ClearPythonExceptionAndWarnIfUnset() {
|
||||
// We're assuming that a nullptr passed to us means a Python call has
|
||||
// failed and set an exception. So we're clearing that exception since
|
||||
// we'll be handling it by converting it to a C++ one. However let's warn
|
||||
// if we were passed nullptr but *no* Python exception is set. We want to
|
||||
// avoid that situation because it opens up the possibility of us clearing
|
||||
// exceptions that aren't related to our nullptr.
|
||||
if (!PyErr_Occurred()) {
|
||||
Log(LogLevel::kWarning,
|
||||
"A PythonRef acquire/steal call was passed nullptr but no Python "
|
||||
"exception is set. This situation should be avoided; only pass "
|
||||
"acquire/steal if it is directly due to a Python exception.");
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
PythonRef::PythonRef(PyObject* obj, ReferenceBehavior b) {
|
||||
switch (b) {
|
||||
case kSteal:
|
||||
Steal(obj_in);
|
||||
Steal(obj);
|
||||
break;
|
||||
case kStealSoft:
|
||||
if (obj_in) {
|
||||
Steal(obj_in);
|
||||
}
|
||||
StealSoft(obj);
|
||||
break;
|
||||
case kAcquire:
|
||||
Acquire(obj_in);
|
||||
Acquire(obj);
|
||||
break;
|
||||
case kAcquireSoft:
|
||||
if (obj_in) {
|
||||
Acquire(obj_in);
|
||||
break;
|
||||
}
|
||||
AcquireSoft(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PythonRef::Acquire(PyObject* obj_in) {
|
||||
BA_PRECONDITION(obj_in);
|
||||
assert(Python::HaveGIL());
|
||||
|
||||
// Assign and increment the new one before decrementing our old
|
||||
// (in case its the same one or prev gets deallocated and accesses us
|
||||
// somehow).
|
||||
PyObject* prev = obj_;
|
||||
Py_INCREF(obj_in);
|
||||
obj_ = obj_in;
|
||||
if (prev) {
|
||||
Py_DECREF(prev);
|
||||
}
|
||||
}
|
||||
|
||||
void PythonRef::AcquireSoft(PyObject* obj_in) {
|
||||
if (!obj_in) {
|
||||
Release();
|
||||
return;
|
||||
}
|
||||
Acquire(obj_in);
|
||||
}
|
||||
|
||||
void PythonRef::Steal(PyObject* obj_in) {
|
||||
BA_PRECONDITION(obj_in);
|
||||
assert(Python::HaveGIL());
|
||||
|
||||
void PythonRef::SetObj(PyObject* obj_in) {
|
||||
// Assign before decrementing the old
|
||||
// (in case prev gets deallocated and accesses us somehow).
|
||||
PyObject* prev = obj_;
|
||||
@ -78,12 +63,46 @@ void PythonRef::Steal(PyObject* obj_in) {
|
||||
}
|
||||
}
|
||||
|
||||
void PythonRef::StealSoft(PyObject* obj_in) {
|
||||
void PythonRef::Steal(PyObject* obj_in) {
|
||||
assert(Python::HaveGIL());
|
||||
if (!obj_in) {
|
||||
ClearPythonExceptionAndWarnIfUnset();
|
||||
throw Exception("nullptr passed to PythonRef::Steal.");
|
||||
}
|
||||
SetObj(obj_in);
|
||||
}
|
||||
|
||||
void PythonRef::StealSoft(PyObject* obj_in) {
|
||||
assert(Python::HaveGIL());
|
||||
if (!obj_in) {
|
||||
// 'Soft' versions don't assume nullptr is due to an exception,
|
||||
// so we don't touch Python exception state here.
|
||||
Release();
|
||||
return;
|
||||
}
|
||||
Steal(obj_in);
|
||||
SetObj(obj_in);
|
||||
}
|
||||
|
||||
void PythonRef::Acquire(PyObject* obj_in) {
|
||||
assert(Python::HaveGIL());
|
||||
if (!obj_in) {
|
||||
ClearPythonExceptionAndWarnIfUnset();
|
||||
throw Exception("nullptr passed to PythonRef::Acquire.");
|
||||
}
|
||||
Py_INCREF(obj_in);
|
||||
SetObj(obj_in);
|
||||
}
|
||||
|
||||
void PythonRef::AcquireSoft(PyObject* obj_in) {
|
||||
assert(Python::HaveGIL());
|
||||
if (!obj_in) {
|
||||
// 'Soft' versions don't assume nullptr is due to an exception,
|
||||
// so we don't touch Python exception state here.
|
||||
Release();
|
||||
return;
|
||||
}
|
||||
Py_INCREF(obj_in);
|
||||
SetObj(obj_in);
|
||||
}
|
||||
|
||||
void PythonRef::Release() {
|
||||
|
||||
@ -15,17 +15,24 @@ class PythonRef {
|
||||
public:
|
||||
/// Defines referencing behavior when creating new instances.
|
||||
enum ReferenceBehavior {
|
||||
/// Steal the provided object reference (and throw an Exception if it is
|
||||
/// nullptr).
|
||||
/// Steal the provided object reference. If nullptr is passed, it is
|
||||
/// assumed to be due to a Python exception occurring. The Python
|
||||
/// exception is then cleared, a C++ exception is raised, and a warning
|
||||
/// is logged if no Python exception was set.
|
||||
kSteal,
|
||||
/// Steal the provided object reference or set as unreferenced if it is
|
||||
/// nullptr.
|
||||
/// Steal the provided object reference. If nullptr is passed, set as
|
||||
/// unreferenced. Does not touch Python exception state, so be sure to
|
||||
/// clear that yourself if the nullptr case is due to an Exception.
|
||||
kStealSoft,
|
||||
/// Acquire a new reference to the provided object (and throw an Exception
|
||||
/// if it is nullptr).
|
||||
/// Acquire a new reference to the provided object. If nullptr is
|
||||
/// passed, it is assumed to be due to a Python exception occurring. The
|
||||
/// Python exception is then cleared, a C++ exception is raised, and a
|
||||
/// warning is logged if no Python exception was set.
|
||||
kAcquire,
|
||||
/// Acquire a new reference to the provided object or set as unreferenced if
|
||||
/// it is nullptr.
|
||||
/// Acquire a new reference to the provided object. If nullptr is
|
||||
/// passed, set as unreferenced. Does not touch Python exception state,
|
||||
/// so be sure to clear that yourself if the nullptr case is due to an
|
||||
/// exception.
|
||||
kAcquireSoft
|
||||
};
|
||||
|
||||
@ -35,22 +42,22 @@ class PythonRef {
|
||||
/// See ReferenceBehavior docs.
|
||||
PythonRef(PyObject* obj, ReferenceBehavior behavior);
|
||||
|
||||
/// Shortcut to create a new PythonRef using ReferenceBehavior::kSteal.
|
||||
/// Shortcut to create a new PythonRef using ReferenceBehavior::kSteal.
|
||||
static auto Stolen(PyObject* obj) -> PythonRef {
|
||||
return PythonRef(obj, ReferenceBehavior::kSteal);
|
||||
return {obj, ReferenceBehavior::kSteal};
|
||||
}
|
||||
|
||||
static auto StolenSoft(PyObject* obj) -> PythonRef {
|
||||
return PythonRef(obj, ReferenceBehavior::kStealSoft);
|
||||
return {obj, ReferenceBehavior::kStealSoft};
|
||||
}
|
||||
|
||||
/// Shortcut to create a new PythonRef using ReferenceBehavior::kAcquire.
|
||||
/// Shortcut to create a new PythonRef using ReferenceBehavior::kAcquire.
|
||||
static auto Acquired(PyObject* obj) -> PythonRef {
|
||||
return PythonRef(obj, ReferenceBehavior::kAcquire);
|
||||
return {obj, ReferenceBehavior::kAcquire};
|
||||
}
|
||||
|
||||
static auto AcquiredSoft(PyObject* obj) -> PythonRef {
|
||||
return PythonRef(obj, ReferenceBehavior::kAcquireSoft);
|
||||
return {obj, ReferenceBehavior::kAcquireSoft};
|
||||
}
|
||||
|
||||
/// Copy constructor acquires a new reference (or sets as unreferenced)
|
||||
@ -84,20 +91,28 @@ class PythonRef {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/// Acquire a new reference to the passed object. Throws an exception if
|
||||
/// nullptr is passed.
|
||||
void Acquire(PyObject* obj);
|
||||
|
||||
/// Acquire a new reference to the passed object. Sets to null reference
|
||||
/// if nullptr is passed.
|
||||
void AcquireSoft(PyObject* obj);
|
||||
|
||||
/// Steal the passed reference. Throws an Exception if nullptr is passed.
|
||||
/// Steal the provided object reference. If nullptr is passed, it is
|
||||
/// assumed to be due to a Python exception occurring. The Python
|
||||
/// exception is then cleared, a C++ exception is raised, and a warning is
|
||||
/// logged if no Python exception was set.
|
||||
void Steal(PyObject* obj);
|
||||
|
||||
/// Steal the passed reference. Sets to null reference if nullptr is passed.
|
||||
/// Steal the provided object reference. If nullptr is passed, set as
|
||||
/// unreferenced. Does not touch Python exception state, so be sure to
|
||||
/// clear that yourself if the nullptr case is due to an Exception.
|
||||
void StealSoft(PyObject* obj);
|
||||
|
||||
/// Acquire a new reference to the provided object. If nullptr is passed,
|
||||
/// it is assumed to be due to a Python exception occurring. The Python
|
||||
/// exception is then cleared, a C++ exception is raised, and a warning is
|
||||
/// logged if no Python exception was set.
|
||||
void Acquire(PyObject* obj);
|
||||
|
||||
/// Acquire a new reference to the provided object. If nullptr is passed,
|
||||
/// set as unreferenced. Does not touch Python exception state, so be sure
|
||||
/// to clear that yourself if the nullptr case is due to an exception.
|
||||
void AcquireSoft(PyObject* obj);
|
||||
|
||||
/// Release the held reference (if one is held).
|
||||
void Release();
|
||||
|
||||
@ -162,8 +177,8 @@ class PythonRef {
|
||||
/// Throws an exception if unset.
|
||||
auto UnicodeCheck() const -> bool;
|
||||
|
||||
/// Call the PyObject. On error, (optionally) prints errors and returns empty
|
||||
/// ref.
|
||||
/// Call the PyObject. On error, (optionally) prints errors and returns
|
||||
/// empty ref.
|
||||
auto Call(PyObject* args, PyObject* keywds = nullptr,
|
||||
bool print_errors = true) const -> PythonRef;
|
||||
auto Call(const PythonRef& args, const PythonRef& keywds = PythonRef(),
|
||||
@ -177,6 +192,7 @@ class PythonRef {
|
||||
|
||||
private:
|
||||
void ThrowIfUnset() const;
|
||||
void SetObj(PyObject* obj);
|
||||
PyObject* obj_{};
|
||||
};
|
||||
|
||||
|
||||
@ -118,7 +118,7 @@ def generate_app_module(
|
||||
# Set default app-mode-selection logic.
|
||||
contents = (
|
||||
'# Hmm; need to think about how we auto-construct this; how\n'
|
||||
'# do we determine which app modes to check and in what\n'
|
||||
'# should we determine which app modes to check and in what\n'
|
||||
'# order?\n'
|
||||
)
|
||||
if 'scene_v1' in fsets:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user