From 3fb10b7394466d9d760390e7d857e0d03489f16a Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 24 Apr 2024 18:16:38 -0700 Subject: [PATCH] pubsync --- .efrocachemap | 56 ++++++++-------- CHANGELOG.md | 9 ++- Makefile | 9 ++- config/requirements.txt | 3 +- config/toolconfigsrc/mypy.ini | 3 - src/assets/ba_data/python/babase/_app.py | 81 ++++++++++++++++++++++-- src/assets/ba_data/python/baenv.py | 2 +- src/ballistica/shared/ballistica.cc | 2 +- tools/batools/appmodule.py | 29 ++++++++- tools/efrotools/pcommand.py | 3 +- tools/efrotools/pybuild.py | 3 +- 11 files changed, 152 insertions(+), 48 deletions(-) diff --git a/.efrocachemap b/.efrocachemap index f1c2d656..7af0ba06 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -4056,26 +4056,26 @@ "build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1", "build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae", "build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599", - "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "7c8972ca3658d967ba43011362b087aa", - "build/prefab/full/linux_arm64_gui/release/ballisticakit": "27be65844fce312e8c8e13e9d187798d", - "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "e746d122dd08a3f92e4ec28cda6c1fdc", - "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "e0bdc0e743747562e7bcc2404343ded1", - "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "5d7250aeef4af4159e64c03e40607c92", - "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "106939b64bd0c1a7084e31d94e4482e8", - "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "08c321f9fbd4299b51710ef2cf332f14", - "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "5d8949348cb0f8fa18d756132cb24b21", - "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "815364e6a7f8b5e7f9531cc9bc7840b5", - "build/prefab/full/mac_arm64_gui/release/ballisticakit": "483f8f40534fde1ce6c76e446e1bd249", - "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "76f4a382be4ff02bd511349f185f9c94", - "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "8bf5d5375b20828572a7488d283ffebb", - "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "452ee2b082927abfc5e995e7d6d005e2", - "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "93260f68603774826cf48e4556d0fd36", - "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "89bef7d763799ca4a9b86f3819e9af7c", - "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "7775b58359a970118938b7629613ae28", - "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "af85416a3e610a12c54bf1a151a78750", - "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "86a5ecaa46411e8226d6b0a2b1311297", - "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "135935d46ebc78492f05cd23331685c1", - "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "5a3d820dbf01c0243c574b0594965994", + "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "6c7508f088e0b061b0d443a51e6a852b", + "build/prefab/full/linux_arm64_gui/release/ballisticakit": "f6598ab7468acdec2ccc730d21e56fb0", + "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "532877b098f19696d19b1997a09f826d", + "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "63c466b9d41dbb548473bb98c2091fd2", + "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "61b5b25750bb5ab345013cb985f86551", + "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "5d7052354d7d68337e1ee853f6b9a757", + "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "20f068094c73beaa8c231ed058f32a28", + "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "848c1e4376474504f0d03fbecb2bf933", + "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "a699fb523ed5b9959014ceab98fe1c2b", + "build/prefab/full/mac_arm64_gui/release/ballisticakit": "456f860358d90f3dfaddffc5bd5d5eaa", + "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "b53a1d296d46fd782210dc3fe41b3306", + "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "63689cb81be98b9731b47757ff1768ed", + "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "f7a100bdb8431973c969b9817ce3239a", + "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "db2eca1c74a8eaf6169ab638223a15ed", + "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "1a44aae131f2208742d7c04d905ea2ea", + "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "7c7c4c3a64a3c82d6e89b7846f6f4ad4", + "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "9ac60da735da0e07d82cabbb0a23e3d2", + "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "3756377852b3e9ad4bbf079dee7a9e73", + "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "89c9207961bc55ea4ccaf2a9c64d4e1d", + "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "517249ffc950c28968a94e97dd6a4205", "build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "d838781c9192c6d1db86bd540478aadf", "build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "b9f7438c554cdadedd0d71aabb3a1d86", "build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "d838781c9192c6d1db86bd540478aadf", @@ -4092,14 +4092,14 @@ "build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "5471a38a2f6cc967b6518b7976d48cae", "build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "807b53c6ca38c392a7477f250d3a85e5", "build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "5471a38a2f6cc967b6518b7976d48cae", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "08d57b27324c81c15b548378297d8bee", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "ddaa4e0263a93bf07ad0b32e88473b95", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "0655da25b5d61c49dc768c3bcf871a86", - "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "019338079c4c8e486bddb1fcde266d30", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "72c8127f2d20fb08381e9427da4277b0", - "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e020ac5ad52e12a74f562c4133d843ea", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "1142e87548995e74ea749eac87a8fc66", - "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "b687a3dcf04060a3c4635e5c5e883b5b", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "eda0b395775cdedf080e0d80aa7fbe7c", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "d8d746575d21eb26b56319f2d23b142d", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6b6078e47e9993a9b2d9e08dd24adf22", + "build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "ed7c7cd11e33fd5c9fa1bf7015cfc431", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "a69b5ba73dac421de34352f480dca39a", + "build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "48fc85dbf186820241733d2d447f299f", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "957d5f95c29d018025fc4517acb2216d", + "build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "d65f649dc8b6a1dbd0686ea95294605e", "src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c", "src/assets/ba_data/python/babase/_mgen/enums.py": "b611c090513a21e2fe90e56582724e9d", "src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f", diff --git a/CHANGELOG.md b/CHANGELOG.md index b45871be..1527604c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 1.7.34 (build 21810, api 8, 2024-04-23) +### 1.7.34 (build 21812, api 8, 2024-04-24) - Bumped Python version from 3.11 to 3.12 for all builds and project tools. One of the things this means is that we can use `typing.override` instead of the `typing_extensions` version so the annoying requirement of installing @@ -38,9 +38,12 @@ counts keep increasing in the future, the time expense of spinning up a new Python process per pcommand decreases, making pcommandbatch less of a win. Please holler if you have any thoughts on this. -- Renamed the `prereqs` Makefile target to `env`. This is easier to type and - feels more accurate now that the target sets up things like the Python virtual +- Renamed the `prereqs` Makefile target to `env`. This is more concise and feels + more accurate now that the target sets up things such as the Python virtual environment and generally gets the project environment ready to use. +- (build 21810) Fixed an issue where AppSubsystems could get inited multiple + times (due to functools.cached_property no longer being thread-safe in Python + 3.12). ### 1.7.33 (build 21795, api 8, 2024-03-24) - Stress test input-devices are now a bit smarter; they won't press any buttons diff --git a/Makefile b/Makefile index d9362b65..8f005688 100644 --- a/Makefile +++ b/Makefile @@ -1197,11 +1197,15 @@ DMAKE = $(MAKE) MAKEFLAGS= MKFLAGS= MAKELEVEL= # if using this on other platforms. CPUS = $(shell getconf _NPROCESSORS_ONLN || echo 8) PROJ_DIR = $(abspath $(CURDIR)) + +# IMPORTANT: Make sure anything using these values has built env first (so +# that pcommand exists). VERSION = $(shell $(PCOMMAND) version version) BUILD_NUMBER = $(shell $(PCOMMAND) version build) +STAGE_BUILD = $(PROJ_DIR)/$(PCOMMAND) stage_build + BUILD_DIR = $(PROJ_DIR)/build LAZYBUILDDIR = .cache/lazybuild -STAGE_BUILD = $(PROJ_DIR)/$(PCOMMAND) stage_build # Things to ignore when doing root level cleans. Note that we exclude build # and just blow that away manually; it might contain git repos or other things @@ -1288,8 +1292,9 @@ tools/efrotools/pyver.py $(PCOMMAND) checkenv && mkdir -p .cache && touch .cache/checkenv; \ fi -$(PCOMMANDBATCHBIN): src/tools/pcommandbatch/pcommandbatch.c \ +$(PCOMMANDBATCHBIN): src/tools/pcommandbatch/pcommandbatch.c \ src/tools/pcommandbatch/cJSON.c + @$(MAKE) tools/pcommand @$(PCOMMAND) build_pcommandbatch $^ $@ # CMake build-type lowercase diff --git a/config/requirements.txt b/config/requirements.txt index 401505ce..89ad203e 100644 --- a/config/requirements.txt +++ b/config/requirements.txt @@ -1,8 +1,9 @@ ansiwrap==0.8.4 cpplint==1.6.1 +dmgbuild==1.6.1 filelock==3.13.4 furo==2024.1.29 -mypy==1.9.0 +mypy==1.10.0 pbxproj==4.1.0 pdoc==14.4.0 pur==7.3.1 diff --git a/config/toolconfigsrc/mypy.ini b/config/toolconfigsrc/mypy.ini index 3811bb05..8d8d3ec0 100644 --- a/config/toolconfigsrc/mypy.ini +++ b/config/toolconfigsrc/mypy.ini @@ -12,9 +12,6 @@ ignore_missing_imports = True [mypy-pylint.*] ignore_missing_imports = True -[mypy-ansiwrap.*] -ignore_missing_imports = True - [mypy-xml.*] ignore_missing_imports = True diff --git a/src/assets/ba_data/python/babase/_app.py b/src/assets/ba_data/python/babase/_app.py index 8841076d..5cf3bc04 100644 --- a/src/assets/ba_data/python/babase/_app.py +++ b/src/assets/ba_data/python/babase/_app.py @@ -9,7 +9,8 @@ import logging from enum import Enum from typing import TYPE_CHECKING, TypeVar, override from concurrent.futures import ThreadPoolExecutor -from functools import cached_property +from threading import RLock + from efro.call import tpartial @@ -45,6 +46,8 @@ if TYPE_CHECKING: T = TypeVar('T') +Tsub = TypeVar('Tsub', bound='AppSubsystem') + class App: """A class for high level app functionality and state. @@ -219,6 +222,13 @@ class App: ] self._pool_thread_count = 0 + # We hold a lock while lazy-loading our subsystem properties so + # we don't spin up any subsystem more than once, but the lock is + # recursive so that the subsystems can instantiate other + # subsystems. + self._subsystem_property_lock = RLock() + self._subsystem_property_data: dict[str, AppSubsystem | bool] = {} + def postinit(self) -> None: """Called after we've been inited and assigned to babase.app. @@ -331,12 +341,63 @@ class App: def mode_selector(self, selector: babase.AppModeSelector) -> None: self._mode_selector = selector + def _get_subsystem_property( + self, ssname: str, create_call: Callable[[], AppSubsystem | None] + ) -> AppSubsystem | None: + + # Quick-out: if a subsystem object is present, just return it; + # no locking necessary. + val = self._subsystem_property_data.get(ssname) + if val is not None: + if val is False: + # False means subsystem is confirmed as not present. + return None + if val is not True: + # A subsystem has been set. Return it. + return val + + # Anything else (no val present or val True) requires locking. + with self._subsystem_property_lock: + val = self._subsystem_property_data.get(ssname) + if val is not None: + if val is False: + # False means confirmed as not present. + return None + if val is True: + # True means this property is already being loaded; + # not good. + raise RuntimeError( + f'Recursive subsystem load detected for {ssname}' + ) + # Must be an instantiated subsystem. Noice. + return val + + # Ok, there's nothing here for it. Instantiate and set it + # while we hold the lock. Set a placeholder value of True + # first so we know if something tries to recursively + # instantiate us while we're instantiating. + self._subsystem_property_data[ssname] = True + + # Do our one attempt to create the singleton. + val = create_call() + self._subsystem_property_data[ssname] = ( + False if val is None else val + ) + + return val + # __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__ # This section generated by batools.appmodule; do not edit. - @cached_property + @property def classic(self) -> ClassicSubsystem | None: """Our classic subsystem (if available).""" + return self._get_subsystem_property( + 'classic', self._create_classic_subsystem + ) # type: ignore + + @staticmethod + def _create_classic_subsystem() -> ClassicSubsystem | None: # pylint: disable=cyclic-import try: @@ -349,9 +410,15 @@ class App: logging.exception('Error importing baclassic.') return None - @cached_property + @property def plus(self) -> PlusSubsystem | None: """Our plus subsystem (if available).""" + return self._get_subsystem_property( + 'plus', self._create_plus_subsystem + ) # type: ignore + + @staticmethod + def _create_plus_subsystem() -> PlusSubsystem | None: # pylint: disable=cyclic-import try: @@ -364,9 +431,15 @@ class App: logging.exception('Error importing baplus.') return None - @cached_property + @property def ui_v1(self) -> UIV1Subsystem: """Our ui_v1 subsystem (always available).""" + return self._get_subsystem_property( + 'ui_v1', self._create_ui_v1_subsystem + ) # type: ignore + + @staticmethod + def _create_ui_v1_subsystem() -> UIV1Subsystem: # pylint: disable=cyclic-import from bauiv1 import UIV1Subsystem diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py index dabc783b..1aaae17c 100644 --- a/src/assets/ba_data/python/baenv.py +++ b/src/assets/ba_data/python/baenv.py @@ -52,7 +52,7 @@ if TYPE_CHECKING: # Build number and version of the ballistica binary we expect to be # using. -TARGET_BALLISTICA_BUILD = 21810 +TARGET_BALLISTICA_BUILD = 21812 TARGET_BALLISTICA_VERSION = '1.7.34' diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc index 67f45506..bc0d4449 100644 --- a/src/ballistica/shared/ballistica.cc +++ b/src/ballistica/shared/ballistica.cc @@ -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 = 21810; +const int kEngineBuildNumber = 21812; const char* kEngineVersion = "1.7.34"; const int kEngineApiVersion = 8; diff --git a/tools/batools/appmodule.py b/tools/batools/appmodule.py index f25b80aa..3b5a00c7 100755 --- a/tools/batools/appmodule.py +++ b/tools/batools/appmodule.py @@ -94,12 +94,28 @@ def generate_app_module( # so we need to be consistent. if fset.allow_as_soft_requirement: contents += ( + # f'\n' + # f'_{fset.name}_init_lock = Lock()\n' f'\n' - f'@cached_property\n' + # f'@cached_property\n' + f'@property\n' f'def {fset.name}(self) -> {classname} | None:\n' f' """Our {fset.name} subsystem (if available)."""\n' + f' return self._get_subsystem_property(\n' + f" '{fset.name}', " + f'self._create_{fset.name}_subsystem\n' + f' ) # type: ignore\n' + f'\n' + f'@staticmethod\n' + f'def _create_{fset.name}_subsystem()' + f' -> {classname} | None:\n' f' # pylint: disable=cyclic-import\n' f'\n' + # f' # cached_property is not thread safe as of' + # f' Python 3.12, so we\n' + # f' # need to wrangle that ourself' + # f' to avoid multiple instantiations.\n' + # f'\n' f' try:\n' f' from {modname} import {classname}\n' f'\n' @@ -114,10 +130,19 @@ def generate_app_module( else: contents += ( f'\n' - f'@cached_property\n' + # f'@cached_property\n' + '@property\n' f'def {fset.name}(self) -> {classname}:\n' f' """Our {fset.name} subsystem' ' (always available)."""\n' + f' return self._get_subsystem_property(\n' + f" '{fset.name}', " + f'self._create_{fset.name}_subsystem\n' + f' ) # type: ignore\n' + f'\n' + f'@staticmethod\n' + f'def _create_{fset.name}_subsystem()' + f' -> {classname}:\n' f' # pylint: disable=cyclic-import\n' f'\n' f' from {modname} import {classname}\n' diff --git a/tools/efrotools/pcommand.py b/tools/efrotools/pcommand.py index 594c54fe..86b06bb3 100644 --- a/tools/efrotools/pcommand.py +++ b/tools/efrotools/pcommand.py @@ -78,7 +78,8 @@ def pcommand_main(globs: dict[str, Any]) -> None: ): raise RuntimeError( 'Unexpected Python environment;' - ' we expect to be running using .venv/bin/pythonX.Y' + f' we expect to be running under something like' + f" .venv/bin/pythonX.Y; found '{abs_exe_path}'." ) cur_paths_str = os.environ.get('PATH') diff --git a/tools/efrotools/pybuild.py b/tools/efrotools/pybuild.py index 17dc2958..76b7f2cc 100644 --- a/tools/efrotools/pybuild.py +++ b/tools/efrotools/pybuild.py @@ -271,8 +271,7 @@ def build_apple(arch: str, debug: bool = False) -> None: '\t# Apply target Python patches\n' f'\tcd $$(PYTHON_SRCDIR-$({tword})) && ' 'patch -p1 < $(PROJECT_DIR)/patch/Python/Python.patch\n' - f'\t/opt/homebrew/opt/python@3.12/bin/python3.12' - ' ../../tools/pcommand python_apple_patch' + f'\t../../tools/pcommand python_apple_patch' f' $$(PYTHON_SRCDIR-$({tword}))\n' ), count=1,