adding temp bastd featureset before migrating to ui_v1 and scene_v1

This commit is contained in:
Eric 2023-06-01 12:22:55 -07:00
parent 088db6928b
commit b5e0feeb0d
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
27 changed files with 396 additions and 277 deletions

View File

@ -4072,26 +4072,26 @@
"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/0e/83/a30a9b21d0256eb7252a3aea77cb",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/82/17/0ea5d85ff01573e2de91821dd8c9",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/46/12/88dfbcad582747150b6efe8fefe7",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/62/1f/78a78ed612d81a2708d9948c72ee",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/2c/2d/5c062b903d94b492d676e457ba81",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/f3/15/b168df3090bcc2f1f156029934eb",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/6b/51/a39e9cf765dc9ec4052df4a6b33d",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/82/09/f2d830e10ae0c9a77071ba4a7008",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/eb/80/ee6315adac4e758f1802683c24e9",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/48/be/fbfd2e4eee8993b06bcd6a1562fa",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/a9/7d/bad58995ca27599d4000c9507ea1",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/65/08/d274f08d7fb52896967cecc4af62",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/3b/fa/db2bc0b2d4324a969e91add25bd1",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/1b/42/fc1392fc5831d0e5717248608d04",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/cb/03/337ffd349762467008307c2afc99",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/37/62/81f812c8e28ea74ab8f9d0b1c7e4",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/fb/96/05c6846f69abf6c69ed3a756d66f",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/ff/79/6a67ceb295488a2659d57778cfd1",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/e1/e4/4e3dd2af6155d2f647a101551932",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/e9/32/78bec9589f2271a5d70c48048815",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/01/62/032e7f17e55eb4d1a46d00b7f8b3",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/d9/db/295a7e947eab3626dd09344f8773",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/4f/23/abf9b8a3d8382e132001a07ce659",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/8b/e6/969ff181328b319b0d0d7ba737b5",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/3f/71/ee0b615ae5737b07b14611fba521",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/ed/7b/f6b7d63868eff24231ddb4f08acc",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/b0/ed/b7c1d78cf2f4ca9501ae6ada5f2a",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/18/5b/eaea207321a10f13c932a3fd66d3",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/b6/f9/773f268c4ebd8cf0d663cc9466a5",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/a8/5c/40fb49f7a0e1a65496766c5767e6",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/e2/c8/59625490bbbb456617eebb9c4ef3",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/6e/79/66ccaa09094203be7f1bd96ba81b",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/f0/94/1fd51fa09da1fc2f67cfc530dccf",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/84/af/9a03f2688c69a9f704cb8c4c52df",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/d9/ac/6320a984d2b5d9c7c6dffdf596b8",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/b2/0f/acd0b9a413537b781d21e9d3d48f",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/08/3d/8b85009c5e8c8d628c4c65aa8f59",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/e9/95/7621c5397b87d504240bbb28bd05",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/89/fc/bf7301a9c8b6e0bb310fd9c84b36",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/7e/34/3664bb2e4760264eafa82a240b4c",
"build/prefab/lib/linux_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/d4/6a/dd303a200b98a56ba3b100277057",
"build/prefab/lib/linux_arm64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/fc/2c/2996c558fb408a548fdd37398c9a",
"build/prefab/lib/linux_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/ed/28/b7a72be7ae1bd2b58dda4b6902a0",
@ -4108,17 +4108,17 @@
"build/prefab/lib/mac_x86_64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/71/f6/691482915ad58ea1e953cc23d74c",
"build/prefab/lib/mac_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/b8/2b/6ec8c78980a62e3e0ee4b36ece04",
"build/prefab/lib/mac_x86_64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/4e/56/a95c987b2a371759896b037fea86",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/32/a0/8bf135cfa577c08c1e223fcf2031",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/33/a6/428f8a5f54aa10495da308af1e33",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/ae/0a/020e5df843adc6c48c5d1531eac4",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/59/83/ba94efb820dbca8ea42944c045ab",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/c6/de/4100a3f3b8d69fea601fe2810d18",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/ed/9f/c3ebb7d1e0032da37d8f0a0e88ad",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/d4/72/128d744f26cdb804c08f8241a89a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/1b/57/ba539fbf787b1cde81d12bcdfb37",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/46/b7/2b333df846670ad9b19c118dcd0f",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/3f/09/6d61b76e32baea0794483d3a8ad3",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/9e/0d/0407b97c24f4cf32e7c9aeba1842",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/12/ea/36c5d4aee512942eb9bb0866bf81",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/05/57/f9451c7bc39454a27afee023ce54",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/3c/38/7ab498b9f25e73062454c3b1d4af",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/56/8b/376666f0a064ebe26a0f5f61beb9",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/c9/f5/08f11ae1a959b9052c7fd799487e",
"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/b4/3d/e352190a0e5673d101c0f3ee3ad2",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "https://files.ballistica.net/cache/ba1/d5/4a/0e480a855ce83709bd7f6761107d",
"src/ballistica/classic/mgen/pyembed/binding_classic.inc": "https://files.ballistica.net/cache/ba1/b2/fd/f5c362e9093b2d0721fb59fc0056",
"src/ballistica/core/mgen/pyembed/binding_core.inc": "https://files.ballistica.net/cache/ba1/71/b8/c020cbb7f9a7ce3f347ccadd3df1",
"src/ballistica/core/mgen/pyembed/env.inc": "https://files.ballistica.net/cache/ba1/7c/74/9b014c32c937757bf3ed36a4f848",

View File

@ -1,4 +1,4 @@
### 1.7.20 (build 21030, api 8, 2023-05-31)
### 1.7.20 (build 21032, api 8, 2023-06-01)
- 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

View File

@ -20,13 +20,16 @@ with specific naming conventions:
- **Feature Set Definition**: To define feature set `foo_bar`, a file must exist
in this directory called `featureset_foo_bar.py`.
- **Python Package**: If feature set `foo_bar` provides a Python package, it
should be a directory named `bafoobar` ('ba' prefix, spaces removed)
should be a directory named `bafoobar` ('ba' prefix, name with spaces removed)
that lives under [Python source files](../../src/assets/ba_data/python).
- **Native Code**: If feature set `foo_bar` provides a native component (C++
code or otherwise) it should live in a directory named `foo_bar` (unmodified
feature set name) under [native source files](../../src/ballistica).
- **Meta Package**: If feature set `foo_bar` provides a meta package (that is,
code or data used to generate other source code), it should be a directory
named `bafoobarmeta` ('ba' prefix, 'meta' suffix, spaces removed)
named `bafoobarmeta` ('ba' prefix, name with spaces removed, 'meta' suffix)
that lives under [meta source files](../../src/meta).
- **Test Package**: If feature set `foo_bar` provides a set of tests, it should
be a directory named `test_bafoobar` ('test_ba' prefix, name with spaces
removed) under [tests](../../tests).

View File

@ -4,8 +4,8 @@
from __future__ import annotations
# This file is exec'ed by the spinoff system, allowing us to define
# values and behavior for this feature-set here in a way that can be
# type-checked alongside other project Python code.
# values and behavior for this feature-set here in a programmatic way
# that can also be type-checked alongside other project Python code.
from batools.featureset import FeatureSet

View File

@ -4,8 +4,8 @@
from __future__ import annotations
# This file is exec'ed by the spinoff system, allowing us to define
# values and behavior for this feature-set here in a way that can be
# type-checked alongside other project Python code.
# values and behavior for this feature-set here in a programmatic way
# that can also be type-checked alongside other project Python code.
from batools.featureset import FeatureSet

View File

@ -4,8 +4,8 @@
from __future__ import annotations
# This file is exec'ed by the spinoff system, allowing us to define
# values and behavior for this feature-set here in a way that can be
# type-checked alongside other project Python code.
# values and behavior for this feature-set here in a programmatic way
# that can also be type-checked alongside other project Python code.
from batools.featureset import FeatureSet

View File

@ -4,8 +4,8 @@
from __future__ import annotations
# This file is exec'ed by the spinoff system, allowing us to define
# values and behavior for this feature-set here in a way that can be
# type-checked alongside other project Python code.
# values and behavior for this feature-set here in a programmatic way
# that can also be type-checked alongside other project Python code.
from batools.featureset import FeatureSet

View File

@ -4,8 +4,8 @@
from __future__ import annotations
# This file is exec'ed by the spinoff system, allowing us to define
# values and behavior for this feature-set here in a way that can be
# type-checked alongside other project Python code.
# values and behavior for this feature-set here in a programmatic way
# that can also be type-checked alongside other project Python code.
from batools.featureset import FeatureSet

View File

@ -0,0 +1,17 @@
# Released under the MIT License. See LICENSE for details.
#
# pylint: disable=missing-docstring, invalid-name
from __future__ import annotations
# This file is exec'ed by the spinoff system, allowing us to define
# values and behavior for this feature-set here in a programmatic way
# that can also be type-checked alongside other project Python code.
from batools.featureset import FeatureSet
# Grab the FeatureSet we should apply to.
fset = FeatureSet.get_active()
fset.has_native_python_module = False
fset.requirements = {'core', 'base', 'scene_v1', 'ui_v1'}

View File

@ -4,8 +4,8 @@
from __future__ import annotations
# This file is exec'ed by the spinoff system, allowing us to define
# values and behavior for this feature-set here in a way that can be
# type-checked alongside other project Python code.
# values and behavior for this feature-set here in a programmatic way
# that can also be type-checked alongside other project Python code.
from batools.featureset import FeatureSet

View File

@ -4,8 +4,8 @@
from __future__ import annotations
# This file is exec'ed by the spinoff system, allowing us to define
# values and behavior for this feature-set here in a way that can be
# type-checked alongside other project Python code.
# values and behavior for this feature-set here in a programmatic way
# that can also be type-checked alongside other project Python code.
from batools.featureset import FeatureSet

View File

@ -52,6 +52,7 @@ ctx.src_omit_paths = {
'ballisticakit-android/build',
'tools/spinoff',
'.editorconfig',
'src/assets/workspace',
}
# Use this to 'carve out' directories or exact file paths which will be

View File

@ -13,6 +13,7 @@
"ba_data/python/babase/__pycache__/_assetmanager.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_asyncio.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_cloud.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_env.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_error.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_general.cpython-311.opt-1.pyc",
"ba_data/python/babase/__pycache__/_hooks.cpython-311.opt-1.pyc",
@ -37,6 +38,7 @@
"ba_data/python/babase/_assetmanager.py",
"ba_data/python/babase/_asyncio.py",
"ba_data/python/babase/_cloud.py",
"ba_data/python/babase/_env.py",
"ba_data/python/babase/_error.py",
"ba_data/python/babase/_general.py",
"ba_data/python/babase/_hooks.py",

View File

@ -146,6 +146,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
$(BUILD_DIR)/ba_data/python/babase/_assetmanager.py \
$(BUILD_DIR)/ba_data/python/babase/_asyncio.py \
$(BUILD_DIR)/ba_data/python/babase/_cloud.py \
$(BUILD_DIR)/ba_data/python/babase/_env.py \
$(BUILD_DIR)/ba_data/python/babase/_error.py \
$(BUILD_DIR)/ba_data/python/babase/_general.py \
$(BUILD_DIR)/ba_data/python/babase/_hooks.py \
@ -416,6 +417,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
$(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 \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_cloud.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_env.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_error.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_general.cpython-311.opt-1.pyc \
$(BUILD_DIR)/ba_data/python/babase/__pycache__/_hooks.cpython-311.opt-1.pyc \

View File

@ -0,0 +1,210 @@
# Released under the MIT License. See LICENSE for details.
#
"""Environment related functionality."""
from __future__ import annotations
import sys
import signal
import logging
from typing import TYPE_CHECKING
from efro.log import LogLevel
if TYPE_CHECKING:
from typing import Any
from efro.log import LogEntry, LogHandler
_g_babase_imported = False # pylint: disable=invalid-name
_g_babase_app_started = False # pylint: disable=invalid-name
def on_native_module_import() -> None:
"""Called by _babase when it is imported; does some sanity checking/etc."""
import _babase
import baenv
global _g_babase_imported # pylint: disable=global-statement
assert not _g_babase_imported
_g_babase_imported = True
# If we have a log_handler set up, wire it up to feed _babase its output.
envconfig = baenv.get_config()
if envconfig.log_handler is not None:
_feed_logs_to_babase(envconfig.log_handler)
env = _babase.pre_env()
# Give a soft warning if we're being used with a different binary
# version than we were built for.
running_build: int = env['build_number']
if running_build != baenv.TARGET_BALLISTICA_BUILD:
logging.warning(
'These scripts are meant to be used with'
' Ballistica build %d, but you are running build %d.'
" This might cause problems. Module path: '%s'.",
baenv.TARGET_BALLISTICA_BUILD,
running_build,
__file__,
)
debug_build = env['debug_build']
# We expect dev_mode on in debug builds and off otherwise;
# make noise if that's not the case.
if debug_build != sys.flags.dev_mode:
logging.warning(
'Mismatch in ballistica debug_build %s'
' and sys.flags.dev_mode %s; this may cause problems.',
debug_build,
sys.flags.dev_mode,
)
def setup_env_for_app_run() -> None:
"""Set stuff such as interrupt handlers for a run of the app."""
import gc
import _babase
import baenv
global _g_babase_app_started # pylint: disable=global-statement
_g_babase_app_started = True
assert _g_babase_imported
assert baenv.config_exists()
# If we were unable to set paths earlier, complain now.
if baenv.g_paths_set_failed:
logging.warning(
'Ballistica Python paths have not been set. This may cause'
' problems. To ensure paths are set, run baenv.configure()'
' before importing any ballistica modules.'
)
# Set up interrupt-signal handling.
# Note: I've found we need to set up our C signal handling AFTER
# we've told Python to disable its own; otherwise (on Mac at least)
# it wipes out our existing C handler.
signal.signal(signal.SIGINT, signal.SIG_DFL) # Do default handling.
_babase.setup_sigint()
# Turn off fancy-pants cyclic garbage-collection. We run it only at
# explicit times to avoid random hitches and keep things more
# deterministic. Non-reference-looped objects will still get cleaned
# up immediately, so we should try to structure things to avoid
# reference loops (just like Swift, ObjC, etc).
# FIXME - move this to Python bootstrapping code. or perhaps disable
# it completely since we've got more bg stuff happening now?...
# (but put safeguards in place to time/minimize gc pauses).
gc.disable()
# pylint: disable=c-extension-no-member
if not TYPE_CHECKING:
import __main__
# Clear out the standard quit/exit messages since they don't
# work in our embedded situation (should revisit this once we're
# usable from a standard interpreter). Note that these don't
# exist in the first place for our monolithic builds which don't
# use site.py.
for attr in ('quit', 'exit'):
if hasattr(__main__.__builtins__, attr):
delattr(__main__.__builtins__, attr)
# Also replace standard interactive help with our simplified
# non-blocking one which is more friendly to cloud/in-app console
# situations.
__main__.__builtins__.help = _CustomHelper()
# On Windows I'm seeing the following error creating asyncio loops
# in background threads with the default proactor setup:
# ValueError: set_wakeup_fd only works in main thread of the main
# interpreter.
# So let's explicitly request selector loops. Interestingly this
# error only started showing up once I moved Python init to the main
# thread; previously the various asyncio bg thread loops were
# working fine (maybe something caused them to default to selector
# in that case?..
if sys.platform == 'win32':
import asyncio
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
def _feed_logs_to_babase(log_handler: LogHandler) -> None:
"""Route log/print output to internal ballistica console/etc."""
import _babase
def _on_log(entry: LogEntry) -> None:
# Forward this along to the engine to display in the in-app
# console, in the Android log, etc.
_babase.display_log(
name=entry.name,
level=entry.level.name,
message=entry.message,
)
# We also want to feed some logs to the old v1-cloud-log system.
# Let's go with anything warning or higher as well as the
# stdout/stderr log messages that babase.app.log_handler creates
# for us. We should retire or upgrade this system at some point.
if entry.level.value >= LogLevel.WARNING.value or entry.name in (
'stdout',
'stderr',
):
_babase.v1_cloud_log(entry.message)
# Add our callback and also feed it all entries already in the
# cache. This will feed the engine any logs that happened between
# baenv.configure() and now.
# FIXME: while this works for now, the downside is that these
# callbacks fire in a bg thread so certain things like android
# logging will be delayed compared to code that uses native logging
# calls directly. Perhaps we should add some sort of 'immediate'
# callback option to better handle such cases (similar to the
# immediate echofile stderr print that already occurs).
log_handler.add_callback(_on_log, feed_existing_logs=True)
class _CustomHelper:
"""Replacement 'help' that behaves better for our setup."""
def __repr__(self) -> str:
return 'Type help(object) for help about object.'
def __call__(self, *args: Any, **kwds: Any) -> Any:
# We get an ugly error importing pydoc on our embedded platforms
# due to _sysconfigdata_xxx.py not being present (but then
# things mostly work). Let's get the ugly error out of the way
# explicitly.
# FIXME: we shouldn't be seeing this error anymore. Should
# revisit this.
import sysconfig
try:
# This errors once but seems to run cleanly after, so let's
# get the error out of the way.
sysconfig.get_path('stdlib')
except ModuleNotFoundError:
pass
import pydoc
# Disable pager and interactive help since neither works well
# with our funky multi-threaded setup or in-game/cloud consoles.
# Let's just do simple text dumps.
pydoc.pager = pydoc.plainpager
if not args and not kwds:
print(
'Interactive help is not available in this environment.\n'
'Type help(object) for help about object.'
)
return None
return pydoc.help(*args, **kwds)

View File

@ -16,7 +16,6 @@ from __future__ import annotations
import os
import sys
import signal
import logging
from pathlib import Path
from dataclasses import dataclass
@ -27,17 +26,15 @@ from efro.log import setup_logging, LogLevel
if TYPE_CHECKING:
from typing import Any
from efro.log import LogEntry, LogHandler
from efro.log import LogHandler
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21030
TARGET_BALLISTICA_BUILD = 21032
TARGET_BALLISTICA_VERSION = '1.7.20'
_g_env_config: EnvConfig | None = None
_g_babase_imported = False # pylint: disable=invalid-name
_g_babase_app_started = False # pylint: disable=invalid-name
_g_paths_set_failed = False # pylint: disable=invalid-name
g_paths_set_failed = False # pylint: disable=invalid-name
@dataclass
@ -134,15 +131,15 @@ def configure(
# If _babase has already been imported, there's not much we can do
# at this point aside from complain and inform for next time.
if _g_babase_imported:
if '_babase' in sys.modules:
app_python_dir = user_python_dir = site_python_dir = None
# We don't actually complain yet here; we simply take note
# that we weren't able to set paths. Then we complain if/when
# the app is started. This way, non-app uses of babase won't be
# filled with unnecessary warnings.
global _g_paths_set_failed # pylint: disable=global-statement
_g_paths_set_failed = True
global g_paths_set_failed # pylint: disable=global-statement
g_paths_set_failed = True
else:
# Ok; _babase hasn't been imported yet so we can muck with
@ -231,189 +228,7 @@ def on_babase_import() -> None:
on_babase_start_app(). This allows bits of _babase to be used under
existing environments without messing things up too badly.
"""
import _babase
global _g_babase_imported # pylint: disable=global-statement
assert not _g_babase_imported
_g_babase_imported = True
# If we have a log_handler set up, wire it up to feed _babase its output.
envconfig = get_config()
if envconfig.log_handler is not None:
_feed_logs_to_babase(envconfig.log_handler)
env = _babase.pre_env()
# Give a soft warning if we're being used with a different binary
# version than we were built for.
running_build: int = env['build_number']
if running_build != TARGET_BALLISTICA_BUILD:
logging.warning(
'These scripts are meant to be used with'
' Ballistica build %d, but you are running build %d.'
" This might cause problems. Module path: '%s'.",
TARGET_BALLISTICA_BUILD,
running_build,
__file__,
)
debug_build = env['debug_build']
# We expect dev_mode on in debug builds and off otherwise;
# make noise if that's not the case.
if debug_build != sys.flags.dev_mode:
logging.warning(
'Mismatch in ballistica debug_build %s'
' and sys.flags.dev_mode %s; this may cause problems.',
debug_build,
sys.flags.dev_mode,
)
def on_babase_start_app() -> None:
"""Called when ballistica's babase module is spinning up an app."""
import gc
import _babase
global _g_babase_app_started # pylint: disable=global-statement
_g_babase_app_started = True
assert _g_babase_imported
assert config_exists()
# If we were unable to set paths earlier, complain now.
if _g_paths_set_failed:
logging.warning(
'Ballistica Python paths have not been set. This may cause'
' problems. To ensure paths are set, run baenv.configure()'
' before importing any ballistica modules.'
)
# Set up interrupt-signal handling.
# Note: I've found we need to set up our C signal handling AFTER
# we've told Python to disable its own; otherwise (on Mac at least)
# it wipes out our existing C handler.
signal.signal(signal.SIGINT, signal.SIG_DFL) # Do default handling.
_babase.setup_sigint()
# Turn off fancy-pants cyclic garbage-collection. We run it only at
# explicit times to avoid random hitches and keep things more
# deterministic. Non-reference-looped objects will still get cleaned
# up immediately, so we should try to structure things to avoid
# reference loops (just like Swift, ObjC, etc).
# FIXME - move this to Python bootstrapping code. or perhaps disable
# it completely since we've got more bg stuff happening now?...
# (but put safeguards in place to time/minimize gc pauses).
gc.disable()
# pylint: disable=c-extension-no-member
if not TYPE_CHECKING:
import __main__
# Clear out the standard quit/exit messages since they don't
# work in our embedded situation (should revisit this once we're
# usable from a standard interpreter). Note that these don't
# exist in the first place for our monolithic builds which don't
# use site.py.
for attr in ('quit', 'exit'):
if hasattr(__main__.__builtins__, attr):
delattr(__main__.__builtins__, attr)
# Also replace standard interactive help with our simplified
# non-blocking one which is more friendly to cloud/in-app console
# situations.
__main__.__builtins__.help = _CustomHelper()
# On Windows I'm seeing the following error creating asyncio loops
# in background threads with the default proactor setup:
# ValueError: set_wakeup_fd only works in main thread of the main
# interpreter.
# So let's explicitly request selector loops. Interestingly this
# error only started showing up once I moved Python init to the main
# thread; previously the various asyncio bg thread loops were
# working fine (maybe something caused them to default to selector
# in that case?..
if sys.platform == 'win32':
import asyncio
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
class _CustomHelper:
"""Replacement 'help' that behaves better for our setup."""
def __repr__(self) -> str:
return 'Type help(object) for help about object.'
def __call__(self, *args: Any, **kwds: Any) -> Any:
# We get an ugly error importing pydoc on our embedded platforms
# due to _sysconfigdata_xxx.py not being present (but then
# things mostly work). Let's get the ugly error out of the way
# explicitly.
# FIXME: we shouldn't be seeing this error anymore. Should
# revisit this.
import sysconfig
try:
# This errors once but seems to run cleanly after, so let's
# get the error out of the way.
sysconfig.get_path('stdlib')
except ModuleNotFoundError:
pass
import pydoc
# Disable pager and interactive help since neither works well
# with our funky multi-threaded setup or in-game/cloud consoles.
# Let's just do simple text dumps.
pydoc.pager = pydoc.plainpager
if not args and not kwds:
print(
'Interactive help is not available in this environment.\n'
'Type help(object) for help about object.'
)
return None
return pydoc.help(*args, **kwds)
def _feed_logs_to_babase(log_handler: LogHandler) -> None:
"""Route log/print output to internal ballistica console/etc."""
import _babase
def _on_log(entry: LogEntry) -> None:
# Forward this along to the engine to display in the in-app
# console, in the Android log, etc.
_babase.display_log(
name=entry.name,
level=entry.level.name,
message=entry.message,
)
# We also want to feed some logs to the old v1-cloud-log system.
# Let's go with anything warning or higher as well as the
# stdout/stderr log messages that babase.app.log_handler creates
# for us. We should retire or upgrade this system at some point.
if entry.level.value >= LogLevel.WARNING.value or entry.name in (
'stdout',
'stderr',
):
_babase.v1_cloud_log(entry.message)
# Add our callback and also feed it all entries already in the
# cache. This will feed the engine any logs that happened between
# baenv.configure() and now.
# FIXME: while this works for now, the downside is that these
# callbacks fire in a bg thread so certain things like android
# logging will be delayed compared to code that uses native logging
# calls directly. Perhaps we should add some sort of 'immediate'
# callback option to better handle such cases (similar to the
# immediate echofile stderr print that already occurs).
log_handler.add_callback(_on_log, feed_existing_logs=True)

View File

@ -113,6 +113,14 @@ void BaseFeatureSet::OnModuleExec(PyObject* module) {
// let baenv know it can now feed us logs and run some checks.
g_core->python->RunBaEnvOnBaBaseImport();
// Run some sanity checks/etc.
auto result = g_base->python->objs()
.Get(BasePython::ObjID::kOnNativeModuleImportCall)
.Call();
if (!result.Exists()) {
FatalError("babase._env.on_native_module_import() call failed.");
}
// ..and because baenv is now feeding us logs, we can push any logs through
// that we've been holding on to.
g_core->python->EnablePythonLoggingCalls();

View File

@ -123,6 +123,14 @@ void BasePython::OnMainThreadStartApp() {
if (!result.Exists()) {
FatalError("baenv.on_babase_start_app() failed.");
}
// Set up some env stuff (interrupt handlers, etc.)
result = g_base->python->objs()
.Get(BasePython::ObjID::kSetupEnvForAppRunCall)
.Call();
if (!result.Exists()) {
FatalError("babase._env.setup_env_for_app_run() failed.");
}
}
void BasePython::OnAppStart() {

View File

@ -101,6 +101,8 @@ class BasePython {
kOnTooManyFileDescriptorsCall,
kPreEnv,
kOpenURLWithWebBrowserModuleCall,
kOnNativeModuleImportCall,
kSetupEnvForAppRunCall,
kLast // Sentinel; must be at end.
};

View File

@ -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 = 21030;
const int kEngineBuildNumber = 21032;
const char* kEngineVersion = "1.7.20";
auto MonolithicMain(const core::CoreConfig& core_config) -> int {

View File

@ -33,7 +33,7 @@ sources: \
$(PROJ_SRC_DIR)/ballistica/template_fs/mgen/pyembed/binding_template_fs.inc \
$(PROJ_SRC_DIR)/ballistica/ui_v1/mgen/pyembed/binding_ui_v1.inc
$(PROJ_SRC_DIR)/ballistica/core/mgen/python_modules_monolithic.h : $(PROJ_DIR)/config/featuresets/featureset_base.py $(PROJ_DIR)/config/featuresets/featureset_classic.py $(PROJ_DIR)/config/featuresets/featureset_core.py $(PROJ_DIR)/config/featuresets/featureset_plus.py $(PROJ_DIR)/config/featuresets/featureset_scene_v1.py $(PROJ_DIR)/config/featuresets/featureset_template_fs.py $(PROJ_DIR)/config/featuresets/featureset_ui_v1.py
$(PROJ_SRC_DIR)/ballistica/core/mgen/python_modules_monolithic.h : $(PROJ_DIR)/config/featuresets/featureset_base.py $(PROJ_DIR)/config/featuresets/featureset_classic.py $(PROJ_DIR)/config/featuresets/featureset_core.py $(PROJ_DIR)/config/featuresets/featureset_plus.py $(PROJ_DIR)/config/featuresets/featureset_scene_v1.py $(PROJ_DIR)/config/featuresets/featureset_std.py $(PROJ_DIR)/config/featuresets/featureset_template_fs.py $(PROJ_DIR)/config/featuresets/featureset_ui_v1.py
@$(PCOMMAND) gen_monolithic_register_modules $@
$(PROJ_SRC_DIR)/ballistica/base/mgen/pyembed/binding_base.inc : babasemeta/pyembed/binding_base.py

View File

@ -10,6 +10,7 @@ from babase import _language
from babase import _apputils
from babase._mgen import enums
from babase import _hooks
from babase import _env
# The C++ layer looks for this variable:
values = [
@ -85,4 +86,6 @@ values = [
_hooks.login_adapter_get_sign_in_token_response, # kLoginAdapterGetSignInTokenResponseCall
_hooks.open_url_with_webbrowser_module, # kOpenURLWithWebBrowserModuleCall
_apputils.on_too_many_file_descriptors, # kOnTooManyFileDescriptorsCall
_env.on_native_module_import, # kOnNativeModuleImportCall
_env.setup_env_for_app_run, # kSetupEnvForAppRunCall
]

View File

@ -953,7 +953,6 @@ def generate(projroot: str) -> None:
f'import sys\n'
f'sys.path.append("build/assets/ba_data/python")\n'
f'sys.path.append("{toolsdir}")\n'
f'import _babase\n'
f'from batools import dummymodule\n'
)
@ -972,7 +971,6 @@ def generate(projroot: str) -> None:
f'dummymodule.Generator(modulename="{mname}",'
f' outfilename="{outfilename}").run()\n'
)
assert gencount
# Launch ballisticakit and exec ourself from within it.
print(

View File

@ -140,9 +140,14 @@ class FeatureSet:
@property
def name_python_package_meta(self) -> str:
"""The name of our meta python package."""
"""The name of our meta Python package."""
return f'ba{self.name_compact}meta'
@property
def name_python_package_tests(self) -> str:
"""The name of our Python tests package."""
return f'test_ba{self.name_compact}'
@property
def name_python_binary_module(self) -> str:
"""Python binary module name (foo_bar -> _bafoobar)."""

View File

@ -333,7 +333,9 @@ def spinoff_test() -> None:
'--featuresets',
'none',
]
print(Clr.MAG + ' '.join(cmd) + Clr.RST)
# Show the spinoff command we'd use here.
print(Clr.MAG + ' '.join(cmd) + Clr.RST, flush=True)
# Avoid the 'what to do next' help.
subprocess.run(
cmd + ['--noninteractive'],
check=True,
@ -341,6 +343,37 @@ def spinoff_test() -> None:
os.makedirs(path, exist_ok=True)
print(f'{Clr.MAG}tools/spinoff update{Clr.RST}', flush=True)
subprocess.run(['tools/spinoff', 'update'], cwd=path, check=True)
subprocess.run(['make', 'cmake-server-binary'], cwd=path, check=True)
# subprocess.run(['make', 'cmake-server-binary'], cwd=path, check=True)
# Now let's simply run the mypy target. This will compile a
# binary, use that binary to generate dummy Python modules, and
# then check the assembled set of Python scripts. If all that
# goes through it tells us that this spinoff project is at least
# basically functional.
subprocess.run(
['make', 'mypy'],
cwd=path,
env=dict(os.environ, BA_ENABLE_DUMMY_MODULE_BINARY_BUILDS='1'),
check=True,
)
# Run the binary with a --help arg and make sure it spits
# out what we expect it to.
# DISABLING: the dummy-module generation part of the mypy target
# covers this.
if bool(False):
help_output = subprocess.run(
[
'build/cmake/server-debug/dist/spinofftest_headless',
'--help',
],
cwd=path,
check=True,
capture_output=True,
).stdout.decode()
if '-h, --help ' not in help_output:
raise RuntimeError(
'Unexpected output when running test command.'
)
else:
raise CleanError(f"Invalid test type '{testtype}'.")

View File

@ -332,6 +332,10 @@ class SpinoffContext:
fsmetapackagename = featureset.name_python_package_meta
paths.add(f'src/meta/{fsmetapackagename}')
# Omit its tests package.
fstestspackagename = featureset.name_python_package_tests
paths.add(f'tests/{fstestspackagename}')
@classmethod
def get_active(cls) -> SpinoffContext:
"""Return the context currently running."""
@ -1757,8 +1761,9 @@ class SpinoffContext:
# pylint: disable=too-many-locals
# Ok, *something* differs from our cache. Need to take a closer look.
# With no dst we have to do the copy of course.
if not dst_exists:
# With no dst gotta do a copy of course.
self._src_copy_entities.add(src_path)
return
@ -1801,46 +1806,53 @@ class SpinoffContext:
)
return
# Let's filter the src file and if it matches dst we can just
# re-grab our cache info and call it a day.
if self._should_filter_src_file(src_path):
encoding = self._encoding_for_file(src_path_full)
with open(src_path_full, 'rb') as infile:
try:
src_data = self._filter_file(
src_path, infile.read().decode(encoding)
)
except Exception:
print(f"Error decoding/filtering file: '{src_path}'.")
raise
with open(dst_path_full, 'rb') as infile:
try:
dst_data = infile.read().decode(encoding)
except Exception:
print(f"Error decoding file: '{dst_path}'.")
raise
results_are_same = src_data == dst_data
is_project_file = self._is_project_file(src_path)
# Bytes versions are only used very rarely by 'backport'
# command so let's lazy compute them here.
src_datab = dst_datab = None
if is_project_file:
# Project files apply arbitrary logic on top of our
# copying/filtering (which we cannot check here) so we can
# never assume results are unchanging.
results_are_same = False
else:
# Ok our src isn't filtered; can be a bit more streamlined.
with open(src_path_full, 'rb') as infile:
src_datab = infile.read()
with open(dst_path_full, 'rb') as infile:
dst_datab = infile.read()
results_are_same = src_datab == dst_datab
# Let's filter the src file and if it matches dst we can just
# re-grab our cache info and call it a day.
if self._should_filter_src_file(src_path):
encoding = self._encoding_for_file(src_path_full)
with open(src_path_full, 'rb') as infile:
try:
src_data = self._filter_file(
src_path, infile.read().decode(encoding)
)
except Exception:
print(f"Error decoding/filtering file: '{src_path}'.")
raise
with open(dst_path_full, 'rb') as infile:
try:
dst_data = infile.read().decode(encoding)
except Exception:
print(f"Error decoding file: '{dst_path}'.")
raise
results_are_same = src_data == dst_data
# No string versions needed in this case.
src_data = dst_data = None
# Bytes versions are only used very rarely by 'backport'
# command so let's lazy compute them here.
src_datab = dst_datab = None
else:
# Ok our src isn't filtered; can be a bit more streamlined.
with open(src_path_full, 'rb') as infile:
src_datab = infile.read()
with open(dst_path_full, 'rb') as infile:
dst_datab = infile.read()
results_are_same = src_datab == dst_datab
# No string versions needed in this case.
src_data = dst_data = None
if results_are_same:
# Things match; just update the times we've got recorded
# for these fellas.
self._src_recache_entities.add(src_path)
else:
# Ok, something legit changed.
if (os.path.getsize(dst_path_full) == dst_entity.dst_size) and (
os.path.getmtime(dst_path_full) == dst_entity.dst_mtime
):

View File

@ -215,7 +215,7 @@ def _do_create(src_root: str | None, dst_root: str) -> None:
doneclr = Clr.BLU if noninteractive else Clr.GRN
print(
f'{doneclr}{Clr.BLD}Spinoff dst project created at'
f' {Clr.RST}{Clr.BLD}{path}{Clr.RST}{doneclr}.{Clr.RST}'
f' {Clr.RST}{Clr.BLD}{path}{Clr.RST}{doneclr}.{Clr.RST}',
)
if not noninteractive:
print(