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: