mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-01 12:25:53 +08:00
tidying
This commit is contained in:
parent
9169eb6f21
commit
368b39044c
@ -4080,18 +4080,18 @@
|
||||
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/fb/46/34eada1e570cce2107cb55a033e8",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/1d/3e/be779b3740cda2a7d98418d4007a",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/18/b7/4389f6000decbcde1044180b134a",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/4a/91/2c3bf6cca0baecc16138db7fe7ff",
|
||||
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/a0/35/48a61b9ea9369bbe8e6bbb7a2d81",
|
||||
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/01/b4/31635bc46cbda94cc73fc019d28c",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/13/3d/50286e4d2fe1fc7507ba20b45ca2",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/8a/d9/0364942cd8fc9cebbb8b2e355455",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/d7/17/7f186bd856ea7bd18b2fc8d64639",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/b9/63/640aa2e767450800ff481c51b665",
|
||||
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/fe/b8/9865abef73b150348a113fd2bcf0",
|
||||
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/19/ca/ae8153fb5fd0ea1045d386c31134",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/70/e8/796d18c51690f54efcb3df22c048",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/cb/54/ff08149cf2d0c2430e964ad0b9f3",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/e2/8a/0ae529b92bcf4afe5d1c9c797e96",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/a3/d7/f415b115cd0e348be8aa75e28101",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/58/77/7244f67e35fcb0ab4047d5cc6f5e",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/91/de/bef5f0a5b9a0c6d50f4e2922a959",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/75/a5/42ad0f7c2944b1033e5b12395743",
|
||||
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/15/c2/f85086c32e40be84f46f26d90790",
|
||||
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/70/e5/266a0a37f2c7566624fdbc08f1bd",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/29/b2/723a9c0ac8c501cf0d313c7c98b0",
|
||||
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/ed/9a/a2611b9814196d2def42e363df94",
|
||||
"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,14 +4108,14 @@
|
||||
"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/60/31/7c82d61f768515a6f5f8f20a967b",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/ba/38/d98a316972f47a5509be6ab28a96",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/a5/8d/8120340f79d9f9244013ef24c9da",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/84/47/90ccac6eb182c16a973855a160ee",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/5f/7b/ea3d74c27c2272084b459814986f",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/f6/a9/a780cd9b23e680a9f5cc87e5ac21",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/8c/9e/3902170e5e8662ec1fccc720ed48",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/c9/d4/5fa5dc68d04b906ef22a10eae5ae",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/a7/b0/aae9f0f77bc4cf5b7367554e024f",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/81/6e/1cec831611669051695029bd1eeb",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/43/4e/0050d1d6d47cf785a498d9060d30",
|
||||
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/82/fb/c202aa3d4857dfa846afe049ed79",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/cd/27/e34e5ddcf8f5198adf6d896492c8",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/8e/e9/e4af2706ec10fb842743e9227b6a",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/37/b3/75a6d096d1b0801badc116e6b122",
|
||||
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/3b/c1/32817f574106264dfd67563d9ce1",
|
||||
"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",
|
||||
|
||||
140
tools/batools/appmodule.py
Executable file
140
tools/batools/appmodule.py
Executable file
@ -0,0 +1,140 @@
|
||||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Generates parts of babase._app.py.
|
||||
|
||||
This includes things like subsystem attributes for all feature-sets that
|
||||
define them.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from efro.error import CleanError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from batools.featureset import FeatureSet
|
||||
|
||||
|
||||
def generate_app_module(
|
||||
feature_sets: dict[str, FeatureSet], existing_data: str
|
||||
) -> str:
|
||||
"""Generate babase._app.py based on its existing version."""
|
||||
|
||||
# pylint: disable=too-many-locals
|
||||
import textwrap
|
||||
|
||||
from efrotools import replace_section
|
||||
|
||||
out = ''
|
||||
|
||||
fsets = feature_sets
|
||||
|
||||
out = existing_data
|
||||
|
||||
info = '# This section autogenerated by project-update.'
|
||||
indent = ' '
|
||||
|
||||
# Import modules we need for feature-set subsystems.
|
||||
contents = ''
|
||||
for _fsname, fset in sorted(fsets.items()):
|
||||
if fset.has_python_app_subsystem:
|
||||
modname = fset.name_python_package
|
||||
classname = f'{fset.name_camel}Subsystem'
|
||||
contents += f'from {modname} import {classname}\n'
|
||||
out = replace_section(
|
||||
out,
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_IMPORTS_BEGIN__\n',
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_IMPORTS_END__\n',
|
||||
textwrap.indent(
|
||||
f'{info}\n\n{contents}\n' if contents else f'{info}\n', indent
|
||||
),
|
||||
keep_markers=True,
|
||||
)
|
||||
|
||||
# Calc which feature-sets are soft-required by any of the ones here
|
||||
# but not included here. For those we'll expose app-subsystems that
|
||||
# always return None.
|
||||
missing_soft_fset_names = set[str]()
|
||||
|
||||
for fset in fsets.values():
|
||||
for softreq in fset.soft_requirements:
|
||||
if softreq not in fsets:
|
||||
missing_soft_fset_names.add(softreq)
|
||||
|
||||
all_fset_names = missing_soft_fset_names | fsets.keys()
|
||||
|
||||
# Add properties to instantiate feature-set subsystems.
|
||||
contents = ''
|
||||
|
||||
for fsetname in sorted(all_fset_names):
|
||||
# for _fsname, fset in sorted(fsets.items()):
|
||||
if fsetname in missing_soft_fset_names:
|
||||
contents += (
|
||||
f'\n'
|
||||
f'@cached_property\n'
|
||||
f'def {fsetname}(self) -> Any | None:\n'
|
||||
f' """Our {fsetname} subsystem (not available'
|
||||
f' in this project)."""\n'
|
||||
f'\n'
|
||||
f' return None\n'
|
||||
)
|
||||
else:
|
||||
fset = fsets[fsetname]
|
||||
if fset.has_python_app_subsystem:
|
||||
if not fset.allow_as_soft_requirement:
|
||||
raise CleanError(
|
||||
f'allow_as_soft_requirement is False for'
|
||||
f' feature-set {fset.name};'
|
||||
f' this is not yet supported.'
|
||||
)
|
||||
modname = fset.name_python_package
|
||||
classname = f'{fset.name_camel}Subsystem'
|
||||
contents += (
|
||||
f'\n'
|
||||
f'@cached_property\n'
|
||||
f'def {fset.name}(self) -> {classname} | None:\n'
|
||||
f' """Our {fset.name} subsystem (if available)."""\n'
|
||||
f'\n'
|
||||
f' try:\n'
|
||||
f' from {modname} import {classname}\n'
|
||||
f'\n'
|
||||
f' return {classname}()\n'
|
||||
f' except ImportError:\n'
|
||||
f' return None\n'
|
||||
f' except Exception:\n'
|
||||
f" logging.exception('Error importing"
|
||||
f" {modname}.')\n"
|
||||
f' return None\n'
|
||||
)
|
||||
out = replace_section(
|
||||
out,
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__\n',
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_END__\n',
|
||||
textwrap.indent(f'{info}\n{contents}\n', indent),
|
||||
keep_markers=True,
|
||||
)
|
||||
|
||||
# Set default app-mode-selection logic.
|
||||
|
||||
# TEMP - fill this out with proper logic/options.
|
||||
if 'scene_v1' in fsets:
|
||||
contents = 'import bascenev1\n\nreturn bascenev1.SceneV1AppMode\n'
|
||||
else:
|
||||
contents = "raise RuntimeError('FIXME: unimplemented.')\n"
|
||||
|
||||
indent = ' '
|
||||
out = replace_section(
|
||||
out,
|
||||
f'{indent}# __DEFAULT_APP_MODE_SELECTION_BEGIN__\n',
|
||||
f'{indent}# __DEFAULT_APP_MODE_SELECTION_END__\n',
|
||||
textwrap.indent(f'{info}\n\n{contents}\n', indent),
|
||||
keep_markers=True,
|
||||
)
|
||||
|
||||
# Note: we *should* format this string, but because this code
|
||||
# runs with every project update I'm just gonna try to keep the
|
||||
# formatting correct manually for now to save a bit of time.
|
||||
# (project update time jumps from 0.3 to 0.5 seconds if I format
|
||||
# thie one file).
|
||||
return out
|
||||
@ -51,8 +51,8 @@ class FeatureSet:
|
||||
|
||||
# Whether this featureset defines a native Python module within
|
||||
# its C++ code. The build process will try to create dummy
|
||||
# modules for all native modules you must tell it if you don't
|
||||
# have one.
|
||||
# modules for all native modules, so to avoid errors you must
|
||||
# tell it if you don't have one.
|
||||
self.has_native_python_module = True
|
||||
|
||||
# If True, for feature-set 'foo_bar', the build system will
|
||||
|
||||
@ -306,109 +306,9 @@ def android_archive_unstripped_libs() -> None:
|
||||
|
||||
def spinoff_test() -> None:
|
||||
"""Test spinoff functionality."""
|
||||
import os
|
||||
import subprocess
|
||||
import batools.spinoff
|
||||
|
||||
from efrotools import extract_flag
|
||||
from efro.terminal import Clr
|
||||
from efro.error import CleanError
|
||||
|
||||
args = sys.argv[2:]
|
||||
|
||||
submodule_parent = extract_flag(args, '--submodule-parent')
|
||||
|
||||
# A spinoff symlink means we're a spun-off project.
|
||||
if os.path.islink('tools/spinoff'):
|
||||
raise CleanError(
|
||||
'This must be run in a src project; this appears to be a dst.'
|
||||
)
|
||||
if len(args) != 1:
|
||||
raise CleanError('Expected 1 arg.')
|
||||
testtype = args[0]
|
||||
if testtype in {'empty', 'base'}:
|
||||
path = f'build/spinofftest/{testtype}'
|
||||
print(
|
||||
f'{Clr.SBLU}{Clr.BLD}Running spinoff test'
|
||||
f" {Clr.RST}{Clr.BLD}'{testtype}'{Clr.RST}{Clr.SBLU}{Clr.BLD}"
|
||||
f'...{Clr.RST}',
|
||||
flush=True,
|
||||
)
|
||||
|
||||
if os.path.exists(path):
|
||||
if bool(False):
|
||||
subprocess.run(['rm', '-rf', path], check=True)
|
||||
submpath = os.path.join(path, 'submodules/ballistica')
|
||||
if os.path.exists(submpath):
|
||||
print(
|
||||
f'{Clr.BLU}Pulling latest parent submodule'
|
||||
f' for existing test setup...{Clr.RST}',
|
||||
flush=True,
|
||||
)
|
||||
subprocess.run(
|
||||
f'cd "{submpath}" && git checkout master && git pull',
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
|
||||
else:
|
||||
cmd = [
|
||||
'./tools/spinoff',
|
||||
'create',
|
||||
'SpinoffTest',
|
||||
path,
|
||||
'--featuresets',
|
||||
'none' if testtype == 'empty' else testtype,
|
||||
] + (['--submodule-parent'] if submodule_parent else [])
|
||||
|
||||
# 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,
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
# 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',
|
||||
BA_DUMMY_MODULE_BINARY_BUILDS_USE_HEADLESS='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}'.")
|
||||
batools.spinoff.spinoff_test(sys.argv[2:])
|
||||
|
||||
|
||||
def spinoff_check_submodule_parent() -> None:
|
||||
|
||||
@ -696,119 +696,12 @@ class ProjectUpdater:
|
||||
)
|
||||
|
||||
def _generate_app_module(self, path: str, existing_data: str) -> None:
|
||||
# pylint: disable=too-many-locals
|
||||
import textwrap
|
||||
from batools.appmodule import generate_app_module
|
||||
|
||||
from efrotools import replace_section
|
||||
|
||||
fsets = self.feature_sets
|
||||
|
||||
out = existing_data
|
||||
|
||||
info = '# This section autogenerated by project-update.'
|
||||
indent = ' '
|
||||
|
||||
# Import modules we need for feature-set subsystems.
|
||||
contents = ''
|
||||
for _fsname, fset in sorted(fsets.items()):
|
||||
if fset.has_python_app_subsystem:
|
||||
modname = fset.name_python_package
|
||||
classname = f'{fset.name_camel}Subsystem'
|
||||
contents += f'from {modname} import {classname}\n'
|
||||
out = replace_section(
|
||||
out,
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_IMPORTS_BEGIN__\n',
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_IMPORTS_END__\n',
|
||||
textwrap.indent(f'{info}\n\n{contents}\n', indent),
|
||||
keep_markers=True,
|
||||
self._generated_files[path] = generate_app_module(
|
||||
self.feature_sets, existing_data
|
||||
)
|
||||
|
||||
# Calc which feature-sets are soft-required by any of the ones here
|
||||
# but not included here. For those we'll expose app-subsystems that
|
||||
# always return None.
|
||||
missing_soft_fset_names = set[str]()
|
||||
|
||||
for fset in fsets.values():
|
||||
for softreq in fset.soft_requirements:
|
||||
if softreq not in fsets:
|
||||
missing_soft_fset_names.add(softreq)
|
||||
|
||||
all_fset_names = missing_soft_fset_names | fsets.keys()
|
||||
|
||||
# Add properties to instantiate feature-set subsystems.
|
||||
contents = ''
|
||||
|
||||
for fsetname in sorted(all_fset_names):
|
||||
# for _fsname, fset in sorted(fsets.items()):
|
||||
if fsetname in missing_soft_fset_names:
|
||||
contents += (
|
||||
f'\n'
|
||||
f'@cached_property\n'
|
||||
f'def {fsetname}(self) -> Any | None:\n'
|
||||
f' """Our {fsetname} subsystem (not available)."""\n'
|
||||
f'\n'
|
||||
f' return None\n'
|
||||
)
|
||||
else:
|
||||
fset = fsets[fsetname]
|
||||
if fset.has_python_app_subsystem:
|
||||
if not fset.allow_as_soft_requirement:
|
||||
raise CleanError(
|
||||
f'allow_as_soft_requirement is False for'
|
||||
f' feature-set {fset.name};'
|
||||
f' this is not yet supported.'
|
||||
)
|
||||
modname = fset.name_python_package
|
||||
classname = f'{fset.name_camel}Subsystem'
|
||||
contents += (
|
||||
f'\n'
|
||||
f'@cached_property\n'
|
||||
f'def {fset.name}(self) -> {classname} | None:\n'
|
||||
f' """Our {fset.name} subsystem (if available)."""\n'
|
||||
f'\n'
|
||||
f' try:\n'
|
||||
f' from {modname} import {classname}\n'
|
||||
f'\n'
|
||||
f' return {classname}()\n'
|
||||
f' except ImportError:\n'
|
||||
f' return None\n'
|
||||
f' except Exception:\n'
|
||||
f" logging.exception('Error importing"
|
||||
f" {modname}.')\n"
|
||||
f' return None\n'
|
||||
)
|
||||
out = replace_section(
|
||||
out,
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_BEGIN__\n',
|
||||
f'{indent}# __FEATURESET_APP_SUBSYSTEM_PROPERTIES_END__\n',
|
||||
textwrap.indent(f'{info}\n{contents}\n', indent),
|
||||
keep_markers=True,
|
||||
)
|
||||
|
||||
# Set default app-mode-selection logic.
|
||||
|
||||
# TEMP - fill this out with proper logic/options.
|
||||
if 'scene_v1' in fsets:
|
||||
contents = 'import bascenev1\n\nreturn bascenev1.SceneV1AppMode\n'
|
||||
else:
|
||||
contents = "raise RuntimeError('FIXME: unimplemented.')\n"
|
||||
|
||||
indent = ' '
|
||||
out = replace_section(
|
||||
out,
|
||||
f'{indent}# __DEFAULT_APP_MODE_SELECTION_BEGIN__\n',
|
||||
f'{indent}# __DEFAULT_APP_MODE_SELECTION_END__\n',
|
||||
textwrap.indent(f'{info}\n\n{contents}\n', indent),
|
||||
keep_markers=True,
|
||||
)
|
||||
|
||||
# Note: we *should* format this string, but because this code
|
||||
# runs with every project update I'm just gonna try to keep the
|
||||
# formatting correct manually for now to save a bit of time.
|
||||
# (project update time jumps from 0.3 to 0.5 seconds if I format
|
||||
# thie one file).
|
||||
self._generated_files[path] = out
|
||||
|
||||
def _update_meta_makefile(self) -> None:
|
||||
self.enqueue_update('src/meta/Makefile')
|
||||
|
||||
|
||||
@ -16,8 +16,10 @@ submodule and remove the 'spinoff' section in .gitignore.
|
||||
|
||||
from batools.spinoff._context import SpinoffContext
|
||||
from batools.spinoff._main import spinoff_main
|
||||
from batools.spinoff._test import spinoff_test
|
||||
|
||||
__all__ = [
|
||||
'SpinoffContext',
|
||||
'spinoff_main',
|
||||
'spinoff_test',
|
||||
]
|
||||
|
||||
@ -341,12 +341,32 @@ class SpinoffContext:
|
||||
|
||||
self._read_state()
|
||||
|
||||
# First, ask git if there are any untracked files in src. we use
|
||||
# git's managed file list so these wouldn't get synced which
|
||||
# would be confusing. So we'd rather just error in this case.
|
||||
try:
|
||||
output = subprocess.check_output(
|
||||
['git', 'status', '--porcelain=v2'],
|
||||
cwd=self._src_root,
|
||||
).decode()
|
||||
if any(line.startswith('?') for line in output.splitlines()):
|
||||
raise CleanError(
|
||||
'There appear to be files in the src project'
|
||||
' untracked by git. Everything must be added to'
|
||||
' git for spinoff to function.'
|
||||
)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
raise CleanError(
|
||||
"'git status' command failed in src dir."
|
||||
' Spinoff requires the src project to be git managed.'
|
||||
) from exc
|
||||
|
||||
# Get the list of src files managed by git.
|
||||
self._src_git_files = set[str](
|
||||
subprocess.run(
|
||||
['git', 'ls-files'],
|
||||
check=True,
|
||||
cwd=os.path.join(self._src_root),
|
||||
cwd=self._src_root,
|
||||
capture_output=True,
|
||||
)
|
||||
.stdout.decode()
|
||||
|
||||
118
tools/batools/spinoff/_test.py
Normal file
118
tools/batools/spinoff/_test.py
Normal file
@ -0,0 +1,118 @@
|
||||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Tests for spinoff."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
|
||||
def spinoff_test(args: list[str]) -> None:
|
||||
"""High level test run command; accepts args and raises CleanErrors."""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from efrotools import extract_flag
|
||||
from efro.terminal import Clr
|
||||
from efro.error import CleanError
|
||||
|
||||
submodule_parent = extract_flag(args, '--submodule-parent')
|
||||
|
||||
# A spinoff symlink means we're a spun-off project.
|
||||
if os.path.islink('tools/spinoff'):
|
||||
raise CleanError(
|
||||
'This must be run in a src project; this appears to be a dst.'
|
||||
)
|
||||
if len(args) != 1:
|
||||
raise CleanError('Expected 1 arg.')
|
||||
testtype = args[0]
|
||||
if testtype in {'empty', 'base'}:
|
||||
path = f'build/spinofftest/{testtype}'
|
||||
print(
|
||||
f'{Clr.BLD}Running spinoff test{Clr.RST}'
|
||||
f" {Clr.SBLU}{Clr.BLD}'{testtype}'{Clr.RST}"
|
||||
f' {Clr.BLD}in{Clr.RST}'
|
||||
f" {Clr.BLU}'{path}'{Clr.RST}"
|
||||
f'{Clr.BLD}...{Clr.RST}',
|
||||
flush=True,
|
||||
)
|
||||
|
||||
if os.path.exists(path):
|
||||
if bool(False):
|
||||
subprocess.run(['rm', '-rf', path], check=True)
|
||||
submpath = os.path.join(path, 'submodules/ballistica')
|
||||
if os.path.exists(submpath):
|
||||
print(
|
||||
f'{Clr.BLU}Pulling latest parent submodule'
|
||||
f' for existing test setup...{Clr.RST}',
|
||||
flush=True,
|
||||
)
|
||||
subprocess.run(
|
||||
f'cd "{submpath}" && git checkout master && git pull',
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
|
||||
else:
|
||||
cmd = [
|
||||
'./tools/spinoff',
|
||||
'create',
|
||||
'SpinoffTest',
|
||||
path,
|
||||
'--featuresets',
|
||||
'none' if testtype == 'empty' else testtype,
|
||||
] + (['--submodule-parent'] if submodule_parent else [])
|
||||
|
||||
# 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,
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
# 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',
|
||||
BA_DUMMY_MODULE_BINARY_BUILDS_USE_HEADLESS='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}'.")
|
||||
@ -130,7 +130,6 @@ def extract_arg(
|
||||
return val
|
||||
|
||||
|
||||
# FIXME: this has not been tested yet.
|
||||
def replace_section(
|
||||
text: str,
|
||||
begin_marker: str,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user