diff --git a/.efrocachemap b/.efrocachemap index 802a2ec7..95cc3ae3 100644 --- a/.efrocachemap +++ b/.efrocachemap @@ -3928,16 +3928,16 @@ "assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450", "assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e", "assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f", - "build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/47/8a/9ebc5daa1524ab2c28f110594713", - "build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/47/54/4afa32ce286c9fd1769d5974d806", - "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/a4/f6/70e8021e7eecd0ac2780c5290e20", - "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/5e/1c/1537e910399d1ff9f16597d9a687", - "build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/bb/6d/2d6e692c88f33c69bb2cf4346d41", - "build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/a4/e7/364c1ffda791abc63375d6fcbf24", - "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/8d/5f/425c115720b7f176a9968b064aec", - "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/9b/1e/14c166e8608beb01074606b58b6d", - "build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/9c/d1/91d2ba146c8c8cbb5a314321fe68", - "build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/f0/f7/1aa0a6b5a48bc91b48f8314f6091", - "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/ac/22/f41a02837800ffdcd1ab00b8c860", - "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/1d/4a/5c01f5243c5dcae456f8f2dbf63d" + "build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/53/c6/dfcaf3da1e374c6b6a8cca85299d", + "build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b2/40/1070559af08278c0b05d854c7e09", + "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/27/d1/36949ffb430b588fa40a12f7bcad", + "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/07/99/ce84901053a1515146805082f104", + "build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/59/3f/9c5e6a8435d46f4318034552870e", + "build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/89/b4/c88b4b1ed9e843f6f008c6988d20", + "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/67/f5/ce7f8ba6786caf2e5953d330be22", + "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ef/30/d06da2a6a373905a997d8b54062e", + "build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/68/31/b5c420f11b65a031649339df0015", + "build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/0d/e3/191eae14cf956088ed1bd635d744", + "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/bb/3c/6e2ca3917b4120d42fab3777c2ae", + "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/32/9f/586ee4ca6c6068483defbf95c86d" } \ No newline at end of file diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml index 39f956f8..b326b1a3 100644 --- a/.idea/dictionaries/ericf.xml +++ b/.idea/dictionaries/ericf.xml @@ -29,8 +29,8 @@ achname achs acinstance - ack ack'ed + ack acked acks acnt @@ -149,8 +149,8 @@ bacommon badguy bafoundation - ballistica ballistica's + ballistica ballisticacore ballisticacorecb bamaster @@ -780,8 +780,8 @@ gamedata gameinstance gamemap - gamepad gamepad's + gamepad gamepadadvanced gamepads gamepadselect @@ -1151,8 +1151,8 @@ lsqlite lssl lstart - lstr lstr's + lstr lstrs lsval ltex @@ -1773,8 +1773,8 @@ sessionname sessionplayer sessionplayers - sessionteam sessionteam's + sessionteam sessionteams sessiontype setactivity @@ -2100,8 +2100,8 @@ txtw typeargs typecheck - typechecker typechecker's + typechecker typedval typeshed typestr @@ -2177,6 +2177,7 @@ vcruntime vcxproj venv + verfilename verlines versioning versionpredicate diff --git a/assets/src/ba_data/python/ba/_map.py b/assets/src/ba_data/python/ba/_map.py index 0dfbbf65..8e47f11e 100644 --- a/assets/src/ba_data/python/ba/_map.py +++ b/assets/src/ba_data/python/ba/_map.py @@ -218,12 +218,12 @@ class Map(Actor): # (and instruct the user if we weren't preloaded properly). try: self.preloaddata = _ba.getactivity().preloads[type(self)] - except Exception: + except Exception as exc: from ba import _error raise _error.NotFoundError( 'Preload data not found for ' + str(type(self)) + '; make sure to call the type\'s preload()' - ' staticmethod in the activity constructor') + ' staticmethod in the activity constructor') from exc # Set various globals. gnode = _ba.getactivity().globalsnode diff --git a/assets/src/ba_data/python/ba/_session.py b/assets/src/ba_data/python/ba/_session.py index 65f9610c..60c3deba 100644 --- a/assets/src/ba_data/python/ba/_session.py +++ b/assets/src/ba_data/python/ba/_session.py @@ -143,7 +143,8 @@ class Session: else: missing_info = [(d.cls, d.config) for d in exc.deps] raise RuntimeError( - f'Missing non-asset dependencies: {missing_info}') + f'Missing non-asset dependencies: {missing_info}' + ) from exc # Throw a combined exception if we found anything missing. if missing_asset_packages: diff --git a/assets/src/server/ballisticacore_server.py b/assets/src/server/ballisticacore_server.py index ef24f90f..b2fd25c1 100755 --- a/assets/src/server/ballisticacore_server.py +++ b/assets/src/server/ballisticacore_server.py @@ -65,7 +65,7 @@ class ServerManagerApp: try: self._config = self._load_config() except Exception as exc: - raise CleanError(f'Error loading config: {exc}') + raise CleanError(f'Error loading config: {exc}') from exc self._done = False self._process_commands: List[Union[str, ServerCommand]] = [] self._process_commands_lock = Lock() diff --git a/docs/ba_module.md b/docs/ba_module.md index 800da8f6..3ab90371 100644 --- a/docs/ba_module.md +++ b/docs/ba_module.md @@ -1,5 +1,5 @@ -

last updated on 2020-08-09 for Ballistica version 1.5.25 build 20166

+

last updated on 2020-08-21 for Ballistica version 1.5.25 build 20171

This page documents the Python classes and functions in the 'ba' module, which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please let me know. Happy modding!


diff --git a/tools/bacloud b/tools/bacloud index cb08dcff..2765688f 100755 --- a/tools/bacloud +++ b/tools/bacloud @@ -208,9 +208,10 @@ class App: subprocess.run(['make', '--quiet', 'prereqs'], check=True, cwd=self._project_root) - except subprocess.CalledProcessError: - raise CleanError('"make prereqs" check failed. ' - 'Install missing requirements and try again.') + except subprocess.CalledProcessError as exc: + raise CleanError( + '"make prereqs" check failed. ' + 'Install missing requirements and try again.') from exc self._load_state() @@ -439,6 +440,6 @@ if __name__ == '__main__': # Let's do a clean fail on keyboard interrupt. # Can make this optional if a backtrace is ever useful.. sys.exit(1) - except CleanError as exc: - exc.pretty_print() + except CleanError as clean_exc: + clean_exc.pretty_print() sys.exit(1) diff --git a/tools/batools/build.py b/tools/batools/build.py index 01fea940..5f181bf3 100644 --- a/tools/batools/build.py +++ b/tools/batools/build.py @@ -30,6 +30,7 @@ import subprocess from pathlib import Path from typing import TYPE_CHECKING +from efro.error import CleanError from efro.terminal import Clr if TYPE_CHECKING: @@ -46,10 +47,10 @@ class PipRequirement: PIP_REQUIREMENTS = [ - PipRequirement(modulename='pylint', minversion=[2, 5, 3]), + PipRequirement(modulename='pylint', minversion=[2, 6, 0]), PipRequirement(modulename='mypy', minversion=[0, 782]), PipRequirement(modulename='yapf', minversion=[0, 30, 0]), - PipRequirement(modulename='cpplint', minversion=[1, 5, 3]), + PipRequirement(modulename='cpplint', minversion=[1, 5, 4]), PipRequirement(modulename='typing_extensions'), PipRequirement(modulename='pytz'), PipRequirement(modulename='yaml', pipname='PyYAML'), @@ -489,19 +490,19 @@ def checkenv() -> None: # Make sure they've got curl. if subprocess.run(['which', 'curl'], check=False, capture_output=True).returncode != 0: - raise RuntimeError('curl is required; please install it.') + raise CleanError('curl is required; please install it.') # Make sure they've got our target python version. if subprocess.run(['which', PYTHON_BIN], check=False, capture_output=True).returncode != 0: - raise RuntimeError(f'{PYTHON_BIN} is required; please install it.') + raise CleanError(f'{PYTHON_BIN} is required; please install it.') # Make sure they've got pip for that python version. if subprocess.run(f'{PYTHON_BIN} -m pip --version', shell=True, check=False, capture_output=True).returncode != 0: - raise RuntimeError( + raise CleanError( f'pip (for {PYTHON_BIN}) is required; please install it.') # Check for some required python modules. @@ -522,12 +523,11 @@ def checkenv() -> None: check=False, capture_output=True) if results.returncode != 0: - raise RuntimeError( - f'{packagename} (for {PYTHON_BIN}) is required.\n' - f'To install it, try: "{PYTHON_BIN}' - f' -m pip install {packagename}"\n' - f'Alternately, "tools/pcommand install_pip_reqs"' - f' will update all pip requirements.') + raise CleanError(f'{packagename} (for {PYTHON_BIN}) is required.\n' + f'To install it, try: "{PYTHON_BIN}' + f' -m pip install {packagename}"\n' + f'Alternately, "tools/pcommand install_pip_reqs"' + f' will update all pip requirements.') if minver is not None: verlines = results.stdout.decode().splitlines() if verlines[0].startswith('Cpplint fork'): @@ -537,7 +537,7 @@ def checkenv() -> None: vnums = [int(x) for x in ver_line.split()[-1].split('.')] assert len(vnums) == len(minver) if vnums < minver: - raise RuntimeError( + raise CleanError( f'{packagename} ver. {_vstr(minver)} or newer is required;' f' found {_vstr(vnums)}.\n' f'To upgrade it, try: "{PYTHON_BIN}' diff --git a/tools/batools/pcommand.py b/tools/batools/pcommand.py index ee0b23f1..f2b94f37 100644 --- a/tools/batools/pcommand.py +++ b/tools/batools/pcommand.py @@ -551,11 +551,7 @@ def install_pip_reqs() -> None: def checkenv() -> None: """Check for tools necessary to build and run the app.""" import batools.build - from efro.error import CleanError - try: - batools.build.checkenv() - except RuntimeError as exc: - raise CleanError(exc) + batools.build.checkenv() def ensure_prefab_platform() -> None: @@ -620,13 +616,13 @@ def lazybuild() -> None: try: category = batools.build.SourceCategory(sys.argv[2]) except ValueError as exc: - raise CleanError(exc) + raise CleanError(exc) from exc target = sys.argv[3] command = ' '.join(sys.argv[4:]) try: batools.build.lazybuild(target, category, command) except subprocess.CalledProcessError as exc: - raise CleanError(exc) + raise CleanError(exc) from exc def android_archive_unstripped_libs() -> None: @@ -730,3 +726,43 @@ def update_project() -> None: fix = '--fix' in sys.argv Updater(check=check, fix=fix).run() + + +def cmake_prep_dir() -> None: + """Create a dir, recreating it when cmake version changes. + + Useful to prevent builds from breaking when cmake is updated. + """ + import os + import subprocess + from efro.error import CleanError + from efro.terminal import Clr + + if len(sys.argv) != 3: + raise CleanError('Expected 1 arg (dir name)') + dirname = sys.argv[2] + + # Look for cmake version associated with the dir. + verfilename = os.path.join(dirname, '.ba_cmake_version') + ver: Optional[str] + if os.path.isfile(verfilename): + with open(verfilename) as infile: + ver = infile.read() + else: + ver = None + + # Get version of installed cmake. + cmake_ver_output = subprocess.run(['cmake', '--version'], + check=True, + capture_output=True).stdout.decode() + cmake_ver = cmake_ver_output.splitlines()[0].split('cmake version ')[1] + + # If they don't match, blow away the dir and write the current version. + if ver != cmake_ver: + if ver is not None: + print(f'{Clr.BLU}CMake version changed from {ver} to {cmake_ver};' + f' clearing existing build at "{dirname}".{Clr.RST}') + subprocess.run(['rm', '-rf', dirname], check=True) + os.makedirs(dirname, exist_ok=True) + with open(verfilename, 'w') as outfile: + outfile.write(cmake_ver) diff --git a/tools/efrotools/code.py b/tools/efrotools/code.py index 11c999b1..35f47d78 100644 --- a/tools/efrotools/code.py +++ b/tools/efrotools/code.py @@ -121,8 +121,8 @@ def cpplint(projroot: Path, full: bool) -> None: # We want to do a few custom modifications to the cpplint module... try: import cpplint as cpplintmodule - except Exception: - raise CleanError('Unable to import cpplint') + except Exception as exc: + raise CleanError('Unable to import cpplint.') from exc with open(cpplintmodule.__file__) as infile: codelines = infile.read().splitlines() cheadersline = codelines.index('_C_HEADERS = frozenset([') @@ -598,8 +598,8 @@ def mypy(projroot: Path, full: bool) -> None: starttime = time.time() try: runmypy(projroot, filenames, full) - except Exception: - raise CleanError('Mypy failed.') + except Exception as exc: + raise CleanError('Mypy failed.') from exc duration = time.time() - starttime print(f'{Clr.GRN}Mypy passed in {duration:.1f} seconds.{Clr.RST}', flush=True) @@ -625,8 +625,8 @@ def dmypy(projroot: Path) -> None: '.mypy.ini', '--follow-imports=error', '--pretty' ] + filenames subprocess.run(args, check=True) - except Exception: - raise CleanError('Mypy daemon: fail.') + except Exception as exc: + raise CleanError('Mypy daemon: fail.') from exc duration = time.time() - starttime print(f'{Clr.GRN}Mypy daemon passed in {duration:.1f} seconds.{Clr.RST}', flush=True) diff --git a/tools/efrotools/jsontools.py b/tools/efrotools/jsontools.py index e608cd44..d01ae53b 100644 --- a/tools/efrotools/jsontools.py +++ b/tools/efrotools/jsontools.py @@ -43,7 +43,7 @@ class NoIndentEncoder(json.JSONEncoder): """Our custom encoder implementing selective indentation.""" def __init__(self, *args: Any, **kwargs: Any): - super(NoIndentEncoder, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.kwargs = dict(kwargs) del self.kwargs['indent'] self._replacement_map: Dict = {} @@ -55,10 +55,10 @@ class NoIndentEncoder(json.JSONEncoder): key = uuid.uuid4().hex self._replacement_map[key] = json.dumps(o.value, **self.kwargs) return '@@%s@@' % (key, ) - return super(NoIndentEncoder, self).default(o) + return super().default(o) def encode(self, o: Any) -> Any: - result = super(NoIndentEncoder, self).encode(o) + result = super().encode(o) for k, v in self._replacement_map.items(): result = result.replace('"@@%s@@"' % (k, ), v) return result diff --git a/tools/efrotools/pcommand.py b/tools/efrotools/pcommand.py index b7c22ff4..a75a656b 100644 --- a/tools/efrotools/pcommand.py +++ b/tools/efrotools/pcommand.py @@ -297,8 +297,8 @@ def runmypy() -> None: try: efrotools.code.runmypy(PROJROOT, filenames) print(f'{Clr.GRN}Mypy Passed.{Clr.RST}') - except Exception: - raise CleanError('Mypy Failed.') + except Exception as exc: + raise CleanError('Mypy Failed.') from exc def dmypy() -> None: diff --git a/tools/pcommand b/tools/pcommand index bd1d6665..4a9c5cc2 100755 --- a/tools/pcommand +++ b/tools/pcommand @@ -55,7 +55,7 @@ from batools.pcommand import ( list_pip_reqs, install_pip_reqs, checkenv, ensure_prefab_platform, prefab_run_var, make_prefab, update_makebob, lazybuild, android_archive_unstripped_libs, efro_gradle, stage_assets, - update_assets_makefile, update_project) + update_assets_makefile, update_project, cmake_prep_dir) # pylint: enable=unused-import if TYPE_CHECKING: