various tool pipeline work for Emacs 29

This commit is contained in:
Eric 2023-07-31 18:48:30 -07:00
parent ba896185c1
commit 0a70c236af
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
13 changed files with 270 additions and 208 deletions

56
.efrocachemap generated
View File

@ -4068,26 +4068,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "2668b413da2d1dd597a6a6b8c6ae9ee8",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "5d38798c383cae78c227c427ae967281",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "0df69387ebe2fb149694a267a1df4c24",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "153abebe70483d17d933127e894908c4",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "fd6768fe1167b8e24db5eb9e33360456",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "8377309f0d570de541e9210752463bab",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "b4b774fef02d72f58f8083430cbc8334",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "9b100c7bf923a8f01de1b5984f62e7e5",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "ac5ecfa5b0e10bcc0d333875bfff9d29",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "241d315d379eb10ec7c2c7ccc8efa99e",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "9d57aaf4d56398e67695659eedce569c",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "d22fdee9f1355dd8965f56a97518ad85",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "b85955e00c3a076af273849fd436b18c",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "a044700e51b426cd333ab32308bfc033",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "e4bcb7821639ffb7e5b0616d509d3c3d",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "91a3fcefaf965260efb388f4477c8ce3",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "4a54dbbe24033a862a2dac3eb76f98b3",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "c82081e53a00d198137c934efae1ed72",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "d8ee381eafbca03eee21e1218935f499",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "f6e6fc30a1d2a3ccb2d5f43bf91c4402",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "884277e559d840df55f7e0dd1c186949",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "38240f93c1ae9065cf671be2e7620684",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "0480c97db92676754cf9552ee462dccb",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "052b4f4804e30da165744893e84d4a64",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "32d4c7a4bdac7a8cb12d4b42868a5979",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "42649b501212bea15f4b2f2741583339",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "03cbedec6c8f294d7fe57a6dc64803e8",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "37b2c536cd841b40319b0efae40471ce",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "85a86ab24f3a35bff85a9954d7be135a",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "5399d3f4924909ca1c0878f347e20a10",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "70784b57105accc067608e1ea50c2fbc",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "58559f7512a300586b8141591a21564e",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "851e1bcd5f12bcee1a2bb9d503ab90a3",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "8e98e2bb1d7d9fa34f873fd2b7d82138",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "9df874848d2f0cedc815f216f9ab2958",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "49107effdf5c1ee5a0533251a99f9f6a",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "dd131f742bc7780f30fe9bbcd547a662",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "b59086a58f9fd2148c186a4974ef59dd",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "03e1623b3a2826161a8a13b09d8ee9b6",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "56b977883c7374d3feb006a9d40c3e18",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "85ba4e81a1f7ae2cff4b1355eb49904f",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "498921f7eb2afd327d4b900cb70e31f9",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "85ba4e81a1f7ae2cff4b1355eb49904f",
@ -4104,14 +4104,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "0ab638b6602610bdaf432e3cc2464080",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "92394eb19387c363471ce134ac9e6a1b",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "0ab638b6602610bdaf432e3cc2464080",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "0016db9bd4fbf158d19f5a6e84aa2f74",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "40c9f4c7076ef9013dde9afd05d89b95",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "4e74f1959b833486aa1cee0affa1aaef",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "4e39a9a8222a683aa074a0698c26c498",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "9509a8782beb8fd0fc477d0afe3cc6c0",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "091fd49e9c75b202b4f481b65f91a100",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "87567923e411e713f82429f56abd9d84",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "5e6707e7b299474ae4a43a1df2919a55",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "d5b059c1be49152dcc400302e27406a7",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "606d781277bc8f8cd51b7fff37b405eb",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "0204082e71fe83d5e7e9688120a5c47d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "453de7f93862b35f208993f32a681fa1",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "e7f61245af268edad9ad09250e934a71",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e35706c767bba1f98c568ca1f1c54361",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "71de54551134cfb4e993d8897ba91dd3",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "88053eee3b28eb71e65eef0910d02a2d",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "f8cd3af311ac63147882590123b78318",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "eeddad968b176000e31c65be6206a2bc",

View File

@ -1,4 +1,4 @@
### 1.7.25 (build 21206, api 8, 2023-07-29)
### 1.7.25 (build 21208, api 8, 2023-07-31)
- `getconfig` and `setconfig` in `efrotools` are now `getprojectconfig` and
`setprojectconfig` (to reflect the file name changes that happened in 1.7.20).
@ -31,6 +31,12 @@
dirs and only moved into their final locations once that completes
successfully. Its extra important to be safe now that its possible to share
local efrocache dirs between projects or otherwise keep them around longer.
- Experimenting a bit with adding support for
[Pyright](https://github.com/microsoft/pyright) type-checking. This could
theoretically allow for a really great interactive Python environment in
Visual Studio Code (and potentially other editors), so am seeing if it is
worth officially supporting in addition to or as a replacement for Mypy. See
`tools/pcommand pyright`
### 1.7.24 (build 21199, api 8, 2023-07-27)

View File

@ -1,34 +1,9 @@
;;; Directory Local Variables for emacs clang flycheck
;;; For more information see (info "(emacs) Directory Variables")
;; -*- lexical-binding: t; -*-
;;; Turn flycheck mode on for our c++ stuff and tell jedi where to look for our python stuff.
(
;; (c++-mode (eval . (flycheck-mode)))
(python-ts-mode (jedi:server-args . ("--sys-path" "__EFRO_PROJECT_ROOT__/tools"
"--sys-path" "__EFRO_PROJECT_ROOT__/src/assets/ba_data/python"
"--sys-path" "__EFRO_PROJECT_ROOT__/build/dummymodules"
;; "--log-level" "DEBUG" "--log" "/Users/ericf/Desktop/jedilog"
))
(python-black-extra-args . __PYTHON_BLACK_EXTRA_ARGS__))
;; Shorter name in projectile status bar to save valuable space.
(nil . ((projectile-project-name . "__EFRO_PROJECT_SHORTNAME__")))
;; Projectile indexing and search will ignore the following
;; (in addition to git-ignored stuff which it ignores by default)
;; NOTE TO SELF: this means searches in spinoff projects will mostly fail
;; because everything is gitignored; should search in parent repo instead.
(nil . ((projectile-globally-ignored-directories . ("docs"
"submodules"
"src/external"
"src/assets/ba_data/python-site-packages"
"src/assets/pylib-android"
"src/assets/pylib-apple"
"src/assets/windows"))))
;; Trying to get project.el to work the same as projectile since its built in.
;; Specify some extra paths that project.el searches and whatnot should ignore.
;; Note that gitignored stuff is ignored implicitly.
(nil . ((project-vc-ignores . ("docs"
"submodules"
"src/external"
@ -37,4 +12,32 @@
"src/assets/pylib-apple"
"src/assets/windows"))))
;; Set up clangd as our C++ language server.
(c++-ts-mode . ((eglot-server-programs . ((c++-ts-mode . ("clangd" "--compile-commands-dir=.cache/compile_commands_db"))))))
;; Set up python-lsp-server as our Python language server.
(python-ts-mode . (
(eglot-server-programs . (
(python-ts-mode . ("__EFRO_PY_BIN__" "-m" "pylsp"))))
(python-shell-interpreter . "__EFRO_PY_BIN__")
(eglot-workspace-configuration . (
(:pylsp . (:plugins (
:pylint (:enabled t)
:flake8 (:enabled :json-false)
:pycodestyle (:enabled :json-false)
:mccabe (:enabled :json-false)
:autopep8 (:enabled :json-false)
:pyflakes (:enabled :json-false)
:rope_autoimport (:enabled :json-false)
:rope_completion (:enabled :json-false)
:rope_rename (:enabled :json-false)
:yapf (:enabled :json-false)
:black (:enabled t
:skip_string_normalization t
:line_length 80
:cache_config t)
:jedi (:extra_paths [__EFRO_PYTHON_PATHS_Q_REL_STR__])
:pylsp_mypy (:enabled t
:live_mode nil
:dmypy t))))))))
)

View File

@ -17,6 +17,7 @@ a more focused way.
from efro.util import set_canonical_module_names
import _babase
from _babase import (
add_clean_frame_callback,

View File

@ -24,6 +24,7 @@ from dataclasses import dataclass
from typing import TYPE_CHECKING
import __main__
if TYPE_CHECKING:
from efro.log import LogHandler
@ -50,7 +51,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21206
TARGET_BALLISTICA_BUILD = 21208
TARGET_BALLISTICA_VERSION = '1.7.25'

View File

@ -18,8 +18,8 @@ if TYPE_CHECKING:
from typing import Any
import bascenev1
PlayerT = TypeVar('PlayerT', bound=Player)
TeamT = TypeVar('TeamT', bound=Team)
PlayerT = TypeVar("PlayerT", bound=Player)
TeamT = TypeVar("TeamT", bound=Team)
class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
@ -300,7 +300,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
self._expire()
else:
raise RuntimeError(
f'destroy() called when' f' already expired for {self}'
f"destroy() called when" f" already expired for {self}"
)
def retain_actor(self, actor: bascenev1.Actor) -> None:
@ -410,7 +410,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
# Set up the globals node based on our settings.
with self.context:
glb = self._globalsnode = _bascenev1.newnode('globals')
glb = self._globalsnode = _bascenev1.newnode("globals")
# Now that it's going to be front and center,
# set some global values based on what the activity wants.
@ -452,7 +452,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
self.on_transition_in()
except Exception:
logging.exception('Error in on_transition_in for %s.', self)
logging.exception("Error in on_transition_in for %s.", self)
# Tell the C++ layer that this activity is the main one, so it uses
# settings from our globals, directs various events to us, etc.
@ -466,7 +466,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
self.on_transition_out()
except Exception:
logging.exception('Error in on_transition_out for %s.', self)
logging.exception("Error in on_transition_out for %s.", self)
def begin(self, session: bascenev1.Session) -> None:
"""Begin the activity.
@ -562,7 +562,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
self.on_player_join(player)
except Exception:
logging.exception('Error in on_player_join for %s.', self)
logging.exception("Error in on_player_join for %s.", self)
def remove_player(self, sessionplayer: bascenev1.SessionPlayer) -> None:
"""Remove a player from the Activity while it is running.
@ -592,11 +592,11 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
self.on_player_leave(player)
except Exception:
logging.exception('Error in on_player_leave for %s.', self)
logging.exception("Error in on_player_leave for %s.", self)
try:
player.leave()
except Exception:
logging.exception('Error on leave for %s in %s.', player, self)
logging.exception("Error on leave for %s in %s.", player, self)
self._reset_session_player_for_no_activity(sessionplayer)
@ -621,7 +621,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
self.on_team_join(team)
except Exception:
logging.exception('Error in on_team_join for %s.', self)
logging.exception("Error in on_team_join for %s.", self)
def remove_team(self, sessionteam: bascenev1.SessionTeam) -> None:
"""Remove a team from a Running Activity
@ -643,11 +643,11 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
self.on_team_leave(team)
except Exception:
logging.exception('Error in on_team_leave for %s.', self)
logging.exception("Error in on_team_leave for %s.", self)
try:
team.leave()
except Exception:
logging.exception('Error on leave for %s in %s.', team, self)
logging.exception("Error on leave for %s in %s.", team, self)
sessionteam.activityteam = None
@ -668,7 +668,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
sessionplayer.setnode(None)
except Exception:
logging.exception(
'Error resetting SessionPlayer node on %s for %s.',
"Error resetting SessionPlayer node on %s for %s.",
sessionplayer,
self,
)
@ -676,7 +676,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
sessionplayer.resetinput()
except Exception:
logging.exception(
'Error resetting SessionPlayer input on %s for %s.',
"Error resetting SessionPlayer input on %s for %s.",
sessionplayer,
self,
)
@ -701,17 +701,17 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
if not isinstance(self._playertype, type):
self._playertype = Player
print(
f'ERROR: {type(self)} was not passed a Player'
f' type argument; please explicitly pass bascenev1.Player'
f' if you do not want to override it.'
f"ERROR: {type(self)} was not passed a Player"
f" type argument; please explicitly pass bascenev1.Player"
f" if you do not want to override it."
)
self._teamtype = type(self).__orig_bases__[-1].__args__[1]
if not isinstance(self._teamtype, type):
self._teamtype = Team
print(
f'ERROR: {type(self)} was not passed a Team'
f' type argument; please explicitly pass bascenev1.Team'
f' if you do not want to override it.'
f"ERROR: {type(self)} was not passed a Team"
f" type argument; please explicitly pass bascenev1.Team"
f" if you do not want to override it."
)
assert issubclass(self._playertype, Player)
assert issubclass(self._teamtype, Team)
@ -729,24 +729,24 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
activity = activity_ref()
print(
'ERROR: Activity is not dying when expected:',
"ERROR: Activity is not dying when expected:",
activity,
'(warning ' + str(counter[0] + 1) + ')',
"(warning " + str(counter[0] + 1) + ")",
)
print(
'This means something is still strong-referencing it.\n'
'Check out methods such as efro.debug.printrefs() to'
' help debug this sort of thing.'
"This means something is still strong-referencing it.\n"
"Check out methods such as efro.debug.printrefs() to"
" help debug this sort of thing."
)
# Note: no longer calling gc.get_referrers() here because it's
# usage can bork stuff. (see notes at top of efro.debug)
counter[0] += 1
if counter[0] == 4:
print('Killing app due to stuck activity... :-(')
print("Killing app due to stuck activity... :-(")
babase.quit()
except Exception:
logging.exception('Error on _check_activity_death.')
logging.exception("Error on _check_activity_death.")
def _expire(self) -> None:
"""Put the activity in a state where it can be garbage-collected.
@ -760,12 +760,12 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
self.on_expire()
except Exception:
logging.exception('Error in Activity on_expire() for %s.', self)
logging.exception("Error in Activity on_expire() for %s.", self)
try:
self._customdata = None
except Exception:
logging.exception('Error clearing customdata for %s.', self)
logging.exception("Error clearing customdata for %s.", self)
# Don't want to be holding any delay-delete refs at this point.
self._prune_delay_deletes()
@ -780,7 +780,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
self._activity_data.expire()
except Exception:
logging.exception('Error expiring _activity_data for %s.', self)
logging.exception("Error expiring _activity_data for %s.", self)
def _expire_actors(self) -> None:
# Expire all Actors.
@ -792,7 +792,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
actor.on_expire()
except Exception:
logging.exception(
'Error in Actor.on_expire() for %s.', actor_ref()
"Error in Actor.on_expire() for %s.", actor_ref()
)
def _expire_players(self) -> None:
@ -810,7 +810,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
player.expire()
except Exception:
logging.exception('Error expiring %s.', player)
logging.exception("Error expiring %s.", player)
# Reset the SessionPlayer to a not-in-an-activity state.
try:
@ -821,7 +821,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
# until now whos underlying SessionPlayer left long ago...
pass
except Exception:
logging.exception('Error expiring %s.', player)
logging.exception("Error expiring %s.", player)
def _expire_teams(self) -> None:
# Issue warnings for any teams that left the game but don't
@ -838,7 +838,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
try:
team.expire()
except Exception:
logging.exception('Error expiring %s.', team)
logging.exception("Error expiring %s.", team)
try:
sessionteam = team.sessionteam
@ -850,7 +850,7 @@ class Activity(DependencyComponent, Generic[PlayerT, TeamT]):
# player/team has left the game)
pass
except Exception:
logging.exception('Error expiring Team %s.', team)
logging.exception("Error expiring Team %s.", team)
def _prune_delay_deletes(self) -> None:
self._delay_delete_players.clear()

View File

@ -15,6 +15,7 @@ from bascenev1._player import EmptyPlayer # pylint: disable=W0611
from bascenev1._team import EmptyTeam # pylint: disable=W0611
from bascenev1._music import MusicType, setmusic
if TYPE_CHECKING:
import bascenev1
from bascenev1._lobby import JoinInfo

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 = 21206;
const int kEngineBuildNumber = 21208;
const char* kEngineVersion = "1.7.25";
#if BA_MONOLITHIC_BUILD

View File

@ -22,7 +22,6 @@ from efrotools.filecache import FileCache
# pylint: enable=useless-suppression, wrong-import-order
if TYPE_CHECKING:
from typing import Any

View File

@ -566,7 +566,11 @@ def _check_warm_start_entries(entries: list[tuple[str, str]]) -> None:
def warm_start_cache() -> None:
"""Run a pre-pass on the efrocache to improve efficiency."""
"""Run a pre-pass on the efrocache to improve efficiency.
This may fetch an initial cache archive, batch update mod times
to reflect new cache maps, etc.
"""
import tempfile
base_url = get_repository_base_url()

View File

@ -449,125 +449,16 @@ def androidstudiocode() -> None:
def tool_config_install() -> None:
"""Install a tool config file (with some filtering)."""
from efro.terminal import Clr
from efro.error import CleanError
import efrotools.toolconfig
if len(sys.argv) != 4:
raise CleanError('expected 2 args')
src = Path(sys.argv[2])
dst = Path(sys.argv[3])
print(f'Creating tool config: {Clr.BLD}{dst}{Clr.RST}')
with src.open(encoding='utf-8') as infile:
cfg = infile.read()
# Some substitutions, etc.
cfg = _filter_tool_config(cfg)
# Add an auto-generated notice.
comment = None
if dst.name in ['.dir-locals.el']:
comment = ';;'
elif dst.name in [
'.mypy.ini',
'.pycheckers',
'.pylintrc',
'.style.yapf',
'.clang-format',
'.editorconfig',
]:
comment = '#'
if comment is not None:
cfg = (
f'{comment} THIS FILE WAS AUTOGENERATED; DO NOT EDIT.\n'
f'{comment} Source: {src}.\n\n' + cfg
)
with dst.open('w', encoding='utf-8') as outfile:
outfile.write(cfg)
def _filter_tool_config(cfg: str) -> str:
import textwrap
from efrotools import getprojectconfig
# Stick project-root wherever they want.
cfg = cfg.replace('__EFRO_PROJECT_ROOT__', str(PROJROOT))
# Stick a colon-separated list of project Python paths wherever they want.
name = '__EFRO_PYTHON_PATHS__'
if name in cfg:
pypaths = getprojectconfig(PROJROOT).get('python_paths')
if pypaths is None:
raise RuntimeError('python_paths not set in project config')
assert not any(' ' in p for p in pypaths)
cfg = cfg.replace(name, ':'.join(f'{PROJROOT}/{p}' for p in pypaths))
# Short project name.
short_names = {
'ballistica-internal': 'ba-i',
'ballistica': 'ba',
'ballistica-master-server': 'bmas',
'ballistica-master-server-legacy': 'bmasl',
'ballistica-server-node': 'basn',
}
shortname = short_names.get(PROJROOT.name, PROJROOT.name)
cfg = cfg.replace('__EFRO_PROJECT_SHORTNAME__', shortname)
mypy_standard_settings = textwrap.dedent(
"""
# We don't want all of our plain scripts complaining
# about __main__ being redefined.
scripts_are_modules = True
# Try to be as strict as we can about using types everywhere.
no_implicit_optional = True
warn_unused_ignores = True
warn_no_return = True
warn_return_any = True
warn_redundant_casts = True
warn_unreachable = True
warn_unused_configs = True
disallow_incomplete_defs = True
disallow_untyped_defs = True
disallow_untyped_decorators = True
disallow_untyped_calls = True
disallow_any_unimported = True
disallow_subclassing_any = True
strict_equality = True
local_partial_types = True
no_implicit_reexport = True
enable_error_code = redundant-expr, truthy-bool, \
truthy-function, unused-awaitable
"""
).strip()
cfg = cfg.replace('__EFRO_MYPY_STANDARD_SETTINGS__', mypy_standard_settings)
name = '__PYTHON_BLACK_EXTRA_ARGS__'
if name in cfg:
from efrotools.code import black_base_args
bargs = black_base_args()
assert bargs[2] == 'black'
cfg = cfg.replace(
name, '(' + ' '.join(f'"{b}"' for b in bargs[3:]) + ')'
)
# Gen a pylint init hook which sets up our python paths.
pylint_init_tag = '__EFRO_PYLINT_INIT__'
if pylint_init_tag in cfg:
pypaths = getprojectconfig(PROJROOT).get('python_paths')
if pypaths is None:
raise RuntimeError('python_paths not set in project config')
cstr = 'init-hook=import sys;'
for path in pypaths:
cstr += f" sys.path.append('{PROJROOT}/{path}');"
cfg = cfg.replace(pylint_init_tag, cstr)
return cfg
efrotools.toolconfig.install_tool_config(PROJROOT, src, dst)
def sync_all() -> None:

View File

@ -0,0 +1,155 @@
# Released under the MIT License. See LICENSE for details.
#
"""Functionality for wrangling tool config files.
This lets us auto-populate values such as python-paths or versions
into tool config files automatically instead of having to update
everything everywhere manually. It also provides a centralized location
for some tool defaults across all my projects.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from efro.terminal import Clr
if TYPE_CHECKING:
from pathlib import Path
def install_tool_config(projroot: Path, src: Path, dst: Path) -> None:
"""Install a config."""
print(f'Creating tool config: {Clr.BLD}{dst}{Clr.RST}')
with src.open(encoding='utf-8') as infile:
cfg = infile.read()
# Some substitutions, etc.
cfg = _filter_tool_config(projroot, cfg)
# Add an auto-generated notice.
comment = None
if dst.name in ['.dir-locals.el']:
comment = ';;'
elif dst.name in [
'.mypy.ini',
'.pycheckers',
'.pylintrc',
'.style.yapf',
'.clang-format',
'.editorconfig',
]:
comment = '#'
if comment is not None:
cfg = (
f'{comment} THIS FILE WAS AUTOGENERATED; DO NOT EDIT.\n'
f'{comment} Source: {src}.\n\n' + cfg
)
with dst.open('w', encoding='utf-8') as outfile:
outfile.write(cfg)
def _filter_tool_config(projroot: Path, cfg: str) -> str:
# pylint: disable=too-many-locals
import textwrap
from efrotools import getprojectconfig, PYVER
# Stick project-root wherever they want.
cfg = cfg.replace('__EFRO_PROJECT_ROOT__', str(projroot))
# Project Python version; '3.11', etc.
name = '__EFRO_PY_VER__'
if name in cfg:
cfg = cfg.replace(name, PYVER)
# Project Python version as a binary name; 'python3.11', etc.
name = '__EFRO_PY_BIN__'
if name in cfg:
cfg = cfg.replace(name, f'python{PYVER}')
# Colon-separated list of project Python paths.
name = '__EFRO_PYTHON_PATHS__'
if name in cfg:
pypaths = getprojectconfig(projroot).get('python_paths')
if pypaths is None:
raise RuntimeError('python_paths not set in project config')
assert not any(' ' in p for p in pypaths)
cfg = cfg.replace(name, ':'.join(f'{projroot}/{p}' for p in pypaths))
# Quoted relative space-separated list of project Python paths.
name = '__EFRO_PYTHON_PATHS_Q_REL_STR__'
if name in cfg:
pypaths = getprojectconfig(projroot).get('python_paths')
if pypaths is None:
raise RuntimeError('python_paths not set in project config')
assert not any(' ' in p for p in pypaths)
cfg = cfg.replace(name, ' '.join(f'"{p}"' for p in pypaths))
# Short project name.
short_names = {
'ballistica-internal': 'ba-i',
'ballistica': 'ba',
'ballistica-master-server': 'bmas',
'ballistica-master-server-legacy': 'bmasl',
'ballistica-server-node': 'basn',
}
shortname = short_names.get(projroot.name, projroot.name)
cfg = cfg.replace('__EFRO_PROJECT_SHORTNAME__', shortname)
mypy_standard_settings = textwrap.dedent(
"""
# We don't want all of our plain scripts complaining
# about __main__ being redefined.
scripts_are_modules = True
# Try to be as strict as we can about using types everywhere.
no_implicit_optional = True
warn_unused_ignores = True
warn_no_return = True
warn_return_any = True
warn_redundant_casts = True
warn_unreachable = True
warn_unused_configs = True
disallow_incomplete_defs = True
disallow_untyped_defs = True
disallow_untyped_decorators = True
disallow_untyped_calls = True
disallow_any_unimported = True
disallow_subclassing_any = True
strict_equality = True
local_partial_types = True
no_implicit_reexport = True
enable_error_code = redundant-expr, truthy-bool, \
truthy-function, unused-awaitable
"""
).strip()
cfg = cfg.replace('__EFRO_MYPY_STANDARD_SETTINGS__', mypy_standard_settings)
name = '__PYTHON_BLACK_EXTRA_ARGS__'
if name in cfg:
from efrotools.code import black_base_args
bargs = black_base_args()
assert bargs[2] == 'black'
cfg = cfg.replace(
name, '(' + ' '.join(f'"{b}"' for b in bargs[3:]) + ')'
)
# Gen a pylint init hook that sets up our Python paths.
pylint_init_tag = '__EFRO_PYLINT_INIT__'
if pylint_init_tag in cfg:
pypaths = getprojectconfig(projroot).get('python_paths')
if pypaths is None:
raise RuntimeError('python_paths not set in project config')
cstr = 'init-hook=import sys;'
# Stuff our paths in at the beginning in the order they appear
# in our projectconfig.
for i, path in enumerate(pypaths):
cstr += f" sys.path.insert({i}, '{projroot}/{path}');"
cfg = cfg.replace(pylint_init_tag, cstr)
return cfg

View File

@ -15,6 +15,7 @@ from __future__ import annotations
from typing import TYPE_CHECKING
# Pull in commands we want to expose. Its more efficient to define them in
# modules rather than inline here because we'll be able to load them via pyc.
# pylint: disable=unused-import