diff --git a/.efrocachemap b/.efrocachemap
index 6308dead..9f3857dd 100644
--- a/.efrocachemap
+++ b/.efrocachemap
@@ -2565,7 +2565,7 @@
"assets/build/pylib-android/_compression.py": "https://files.ballistica.net/cache/ba1/93/7f/56c3fd789058399b898c5c527b92",
"assets/build/pylib-android/_dummy_thread.py": "https://files.ballistica.net/cache/ba1/5b/a5/82c6ed2ef16974f8cfd5ee2e11f6",
"assets/build/pylib-android/_markupbase.py": "https://files.ballistica.net/cache/ba1/a5/5e/6ad43bfbcd054529b852fa9d9919",
- "assets/build/pylib-android/_osx_support.py": "https://files.ballistica.net/cache/ba1/61/30/ac3f83f7567392218242dc1bd371",
+ "assets/build/pylib-android/_osx_support.py": "https://files.ballistica.net/cache/ba1/1a/dd/18c02bae9dd4e2b651071dd0e606",
"assets/build/pylib-android/_py_abc.py": "https://files.ballistica.net/cache/ba1/63/57/80933fee0979574b2d3b1172cdc8",
"assets/build/pylib-android/_pydecimal.py": "https://files.ballistica.net/cache/ba1/78/1c/999595e074c71574c01ff521a6e0",
"assets/build/pylib-android/_pyio.py": "https://files.ballistica.net/cache/ba1/e6/8e/da9cef09b9375b297ccc45cbedf7",
@@ -2577,7 +2577,7 @@
"assets/build/pylib-android/aifc.py": "https://files.ballistica.net/cache/ba1/8a/d6/25bd39b0581236a85b096ba3fe9d",
"assets/build/pylib-android/antigravity.py": "https://files.ballistica.net/cache/ba1/83/cf/9d1698d68e0e260e6bbefec5a516",
"assets/build/pylib-android/argparse.py": "https://files.ballistica.net/cache/ba1/7d/a3/3c4997b2a8c0c3486ee6a88a1d11",
- "assets/build/pylib-android/ast.py": "https://files.ballistica.net/cache/ba1/4d/98/0c14a8fb30313b4f4d9650772599",
+ "assets/build/pylib-android/ast.py": "https://files.ballistica.net/cache/ba1/b7/42/718de3a57faaca60e6107da1791d",
"assets/build/pylib-android/asynchat.py": "https://files.ballistica.net/cache/ba1/5e/b1/f69db224de08b5e119f5c0f425a8",
"assets/build/pylib-android/asyncio/__init__.py": "https://files.ballistica.net/cache/ba1/6d/27/61dd597138eea19aaf7d724ee691",
"assets/build/pylib-android/asyncio/base_events.py": "https://files.ballistica.net/cache/ba1/93/62/5ee3d4885bf7d85654964fb065e3",
@@ -2601,7 +2601,7 @@
"assets/build/pylib-android/asyncio/subprocess.py": "https://files.ballistica.net/cache/ba1/c8/c4/e58d4c6d467aff6b79cda30f9b52",
"assets/build/pylib-android/asyncio/tasks.py": "https://files.ballistica.net/cache/ba1/92/c3/5a2f6c0fe03583f3f1255456959e",
"assets/build/pylib-android/asyncio/transports.py": "https://files.ballistica.net/cache/ba1/55/a3/0f5d3365b3235c75b2ea80bd5563",
- "assets/build/pylib-android/asyncio/unix_events.py": "https://files.ballistica.net/cache/ba1/58/44/5520e46a45d5630e95dad27b66d7",
+ "assets/build/pylib-android/asyncio/unix_events.py": "https://files.ballistica.net/cache/ba1/eb/86/58dff20a80672a8e4406668de361",
"assets/build/pylib-android/asyncio/windows_events.py": "https://files.ballistica.net/cache/ba1/3d/20/87bd62ba23f5d9f81421eb287041",
"assets/build/pylib-android/asyncio/windows_utils.py": "https://files.ballistica.net/cache/ba1/2e/f9/7642257a860d664f7242efecb3f7",
"assets/build/pylib-android/asyncore.py": "https://files.ballistica.net/cache/ba1/25/1f/ccae9e6cdd0885f9d989a3902e9b",
@@ -2612,13 +2612,13 @@
"assets/build/pylib-android/bz2.py": "https://files.ballistica.net/cache/ba1/84/cb/27cdd0e9186f848fe949c2a3bee7",
"assets/build/pylib-android/cProfile.py": "https://files.ballistica.net/cache/ba1/6e/44/33dbc763d5d1bf76678bdbe772f4",
"assets/build/pylib-android/calendar.py": "https://files.ballistica.net/cache/ba1/74/31/64ce1c94d173a6226df81fbe2baf",
- "assets/build/pylib-android/cgi.py": "https://files.ballistica.net/cache/ba1/ba/63/856b253fbd572d7b925b552354b8",
+ "assets/build/pylib-android/cgi.py": "https://files.ballistica.net/cache/ba1/84/f5/4581cafa1723aab9252016a9128d",
"assets/build/pylib-android/cgitb.py": "https://files.ballistica.net/cache/ba1/45/67/f3f215ae81b670ba05d94706a2ab",
"assets/build/pylib-android/chunk.py": "https://files.ballistica.net/cache/ba1/f6/fe/3c43d1dc84ee74b8a170c61271a3",
"assets/build/pylib-android/cmd.py": "https://files.ballistica.net/cache/ba1/f0/d9/8cec4bcbbfd195d46c3ad637df71",
"assets/build/pylib-android/code.py": "https://files.ballistica.net/cache/ba1/7a/a4/ee660f11ad995354a3b21efbfb1c",
"assets/build/pylib-android/codecs.py": "https://files.ballistica.net/cache/ba1/ed/16/584061843712bbb77342ee17c423",
- "assets/build/pylib-android/codeop.py": "https://files.ballistica.net/cache/ba1/19/1a/47fd0ef5269e708ad2faf50db559",
+ "assets/build/pylib-android/codeop.py": "https://files.ballistica.net/cache/ba1/9b/f7/a7fac5b57aa2aa74739f16d62515",
"assets/build/pylib-android/collections/__init__.py": "https://files.ballistica.net/cache/ba1/96/31/74bf91d70ac53f56c651ea0b1c6f",
"assets/build/pylib-android/collections/abc.py": "https://files.ballistica.net/cache/ba1/29/45/a03469c0f5eb61d823b277d547ce",
"assets/build/pylib-android/colorsys.py": "https://files.ballistica.net/cache/ba1/d6/3b/b932055a535b017694e91296168c",
@@ -2654,11 +2654,11 @@
"assets/build/pylib-android/decimal.py": "https://files.ballistica.net/cache/ba1/92/94/b8be378718b3ede8f05f07aa257b",
"assets/build/pylib-android/difflib.py": "https://files.ballistica.net/cache/ba1/6c/c2/0e781f8333593d5cb5890f702476",
"assets/build/pylib-android/dis.py": "https://files.ballistica.net/cache/ba1/a1/d1/7ccecfaa71f7cd43ce504eb53194",
- "assets/build/pylib-android/doctest.py": "https://files.ballistica.net/cache/ba1/5b/27/a20fbc6e0c46230b9d02d0e016a5",
+ "assets/build/pylib-android/doctest.py": "https://files.ballistica.net/cache/ba1/88/94/4e162825868d974768473472df54",
"assets/build/pylib-android/dummy_threading.py": "https://files.ballistica.net/cache/ba1/20/2f/ec8e68634908312148b53a5dfd4c",
"assets/build/pylib-android/email/__init__.py": "https://files.ballistica.net/cache/ba1/2b/f0/8c85ab15e7cdbdaa0e1705223012",
"assets/build/pylib-android/email/_encoded_words.py": "https://files.ballistica.net/cache/ba1/08/fa/de22bc96e1e332bbe1cf76162a1c",
- "assets/build/pylib-android/email/_header_value_parser.py": "https://files.ballistica.net/cache/ba1/d8/a5/2c5574aedbde0de48d72b06770ef",
+ "assets/build/pylib-android/email/_header_value_parser.py": "https://files.ballistica.net/cache/ba1/9f/f5/17085d073d928ec6c0b8e37fcb95",
"assets/build/pylib-android/email/_parseaddr.py": "https://files.ballistica.net/cache/ba1/e0/b3/b0167200b852c46e60116ba12740",
"assets/build/pylib-android/email/_policybase.py": "https://files.ballistica.net/cache/ba1/19/f9/844a8a848bc5670a810d06f0a6de",
"assets/build/pylib-android/email/base64mime.py": "https://files.ballistica.net/cache/ba1/6b/52/907171fcf7e3baf097a4d503d79c",
@@ -2669,7 +2669,7 @@
"assets/build/pylib-android/email/feedparser.py": "https://files.ballistica.net/cache/ba1/98/6d/61c614d442ca8451320ca7fe4e86",
"assets/build/pylib-android/email/generator.py": "https://files.ballistica.net/cache/ba1/c1/23/173f2e5fd02455bd2db0970c9ca0",
"assets/build/pylib-android/email/header.py": "https://files.ballistica.net/cache/ba1/bb/cb/194570894c14063cd85ea2d8ab6a",
- "assets/build/pylib-android/email/headerregistry.py": "https://files.ballistica.net/cache/ba1/a7/c9/e8d4ab6d0b0a13c4c0330a9201e1",
+ "assets/build/pylib-android/email/headerregistry.py": "https://files.ballistica.net/cache/ba1/4b/d3/0240bedc7e23ba3e3022f6d2b87c",
"assets/build/pylib-android/email/iterators.py": "https://files.ballistica.net/cache/ba1/a5/02/2f56787a3fb91547c61284d7facd",
"assets/build/pylib-android/email/message.py": "https://files.ballistica.net/cache/ba1/9e/50/f42dc086f8eedac768907140cf75",
"assets/build/pylib-android/email/mime/__init__.py": "https://files.ballistica.net/cache/ba1/42/fb/835abe12a4e1e72a5d1711d12cde",
@@ -2810,7 +2810,7 @@
"assets/build/pylib-android/encodings/utf_8_sig.py": "https://files.ballistica.net/cache/ba1/c5/56/c3d98c0cb4cf569fb833ed919cc1",
"assets/build/pylib-android/encodings/uu_codec.py": "https://files.ballistica.net/cache/ba1/f9/64/0107520eca9130ca870cec675bf0",
"assets/build/pylib-android/encodings/zlib_codec.py": "https://files.ballistica.net/cache/ba1/b4/3f/7369ee7aa1aa36b098c3b33ea31b",
- "assets/build/pylib-android/enum.py": "https://files.ballistica.net/cache/ba1/b1/ee/e7435d4112cdaef0192c57f12531",
+ "assets/build/pylib-android/enum.py": "https://files.ballistica.net/cache/ba1/de/8f/09627b04f762c56e00c24cdd5c3f",
"assets/build/pylib-android/filecmp.py": "https://files.ballistica.net/cache/ba1/54/d4/3d6d66bd7d4ee85407851fe986a0",
"assets/build/pylib-android/fileinput.py": "https://files.ballistica.net/cache/ba1/00/79/91b5218d122a5ede37fb0c821b22",
"assets/build/pylib-android/fnmatch.py": "https://files.ballistica.net/cache/ba1/d5/44/0a58d9161ae9d2409ae2477b5948",
@@ -2831,7 +2831,7 @@
"assets/build/pylib-android/html/entities.py": "https://files.ballistica.net/cache/ba1/02/4d/e42a17593176e35ff5da8d720cf9",
"assets/build/pylib-android/html/parser.py": "https://files.ballistica.net/cache/ba1/c7/87/628a5a87855afbac3ebbd858e9a1",
"assets/build/pylib-android/http/__init__.py": "https://files.ballistica.net/cache/ba1/93/8e/37eb6e0c8e0e85fbc817d9b7a7ac",
- "assets/build/pylib-android/http/client.py": "https://files.ballistica.net/cache/ba1/cb/64/465b1cf482df244287406c2d04d9",
+ "assets/build/pylib-android/http/client.py": "https://files.ballistica.net/cache/ba1/91/76/10a31e7d6260da3f5cc290b14441",
"assets/build/pylib-android/http/cookiejar.py": "https://files.ballistica.net/cache/ba1/79/72/6cb2162180eaec43445a53f3ee97",
"assets/build/pylib-android/http/cookies.py": "https://files.ballistica.net/cache/ba1/31/12/7d40c2be1ef8456a4abeb613d633",
"assets/build/pylib-android/http/server.py": "https://files.ballistica.net/cache/ba1/9e/b7/7c94874f5f3684a110923c113b65",
@@ -2851,9 +2851,9 @@
"assets/build/pylib-android/json/decoder.py": "https://files.ballistica.net/cache/ba1/3f/bf/6fd2a01d31cd85e4c21cf2c0a5c8",
"assets/build/pylib-android/json/encoder.py": "https://files.ballistica.net/cache/ba1/5f/36/b17803f0c2b18467b7d10e87e46d",
"assets/build/pylib-android/json/scanner.py": "https://files.ballistica.net/cache/ba1/c8/4b/bcc458a5047e9ac8064a607ee231",
- "assets/build/pylib-android/json/tool.py": "https://files.ballistica.net/cache/ba1/59/1f/a5883f250a5a8584a786531159eb",
+ "assets/build/pylib-android/json/tool.py": "https://files.ballistica.net/cache/ba1/20/ac/edbfd1cabc47b3f3d57b37c95116",
"assets/build/pylib-android/keyword.py": "https://files.ballistica.net/cache/ba1/1d/8a/1cdb5840e8f561ec69407f898752",
- "assets/build/pylib-android/linecache.py": "https://files.ballistica.net/cache/ba1/60/c9/68f020023d9b6d0e7f1f7d6d6b50",
+ "assets/build/pylib-android/linecache.py": "https://files.ballistica.net/cache/ba1/01/91/9aecf23d41972edd3bcb7927b1fe",
"assets/build/pylib-android/locale.py": "https://files.ballistica.net/cache/ba1/ab/cf/da9a211a39662f631b6869e1c28b",
"assets/build/pylib-android/logging/__init__.py": "https://files.ballistica.net/cache/ba1/0d/d3/3460e7bd9309e2e09cbbac2c2f66",
"assets/build/pylib-android/logging/config.py": "https://files.ballistica.net/cache/ba1/14/a0/a315016fa0d6d748d204acde0c8d",
@@ -2873,13 +2873,13 @@
"assets/build/pylib-android/operator.py": "https://files.ballistica.net/cache/ba1/03/ac/fc74fa2a3146b00f9ee1921996c5",
"assets/build/pylib-android/optparse.py": "https://files.ballistica.net/cache/ba1/56/b4/9ae8b02341d9b2b5c1a75d5f8729",
"assets/build/pylib-android/os.py": "https://files.ballistica.net/cache/ba1/d0/78/d8693c3a2c5c4684faadf46ebed5",
- "assets/build/pylib-android/pathlib.py": "https://files.ballistica.net/cache/ba1/f6/90/a68b8e0dffc669ae7aec2c95010c",
+ "assets/build/pylib-android/pathlib.py": "https://files.ballistica.net/cache/ba1/ee/4c/ae4cf6fa2e0b54aa42e26cbc6295",
"assets/build/pylib-android/pdb.py": "https://files.ballistica.net/cache/ba1/84/4f/9fc933776560b7e45cb7ef3bcfa9",
"assets/build/pylib-android/pickle.py": "https://files.ballistica.net/cache/ba1/81/cf/a94f6e8a45671c34c1d9d4efdc13",
"assets/build/pylib-android/pickletools.py": "https://files.ballistica.net/cache/ba1/c7/0a/1f89f5d71ccf1f9269cc5f8d3d72",
"assets/build/pylib-android/pipes.py": "https://files.ballistica.net/cache/ba1/ed/d3/9e08e7ece839c58d885223c57adb",
"assets/build/pylib-android/pkgutil.py": "https://files.ballistica.net/cache/ba1/3f/27/1c376bf997f3ee3a09c9ffdb58d6",
- "assets/build/pylib-android/platform.py": "https://files.ballistica.net/cache/ba1/23/0a/090ebfcb1943ca88f9a524f05b6a",
+ "assets/build/pylib-android/platform.py": "https://files.ballistica.net/cache/ba1/99/72/0d5d720f5936836937633e4cc54e",
"assets/build/pylib-android/plistlib.py": "https://files.ballistica.net/cache/ba1/ff/ca/c37a29df76785ad0bb6975627639",
"assets/build/pylib-android/poplib.py": "https://files.ballistica.net/cache/ba1/62/c4/c9a5a81583fcd7e7767ea6392ef4",
"assets/build/pylib-android/posixpath.py": "https://files.ballistica.net/cache/ba1/8c/52/9a1a9b00a9a4c12c8fd0bb840865",
@@ -2893,7 +2893,7 @@
"assets/build/pylib-android/queue.py": "https://files.ballistica.net/cache/ba1/8c/f8/37f30b7f7500462869580f7eb14c",
"assets/build/pylib-android/quopri.py": "https://files.ballistica.net/cache/ba1/f3/08/1d7b3e0f7ce1ad649b1abf08f8ac",
"assets/build/pylib-android/random.py": "https://files.ballistica.net/cache/ba1/f3/8e/b752b23583b23a38bb15cb176522",
- "assets/build/pylib-android/re.py": "https://files.ballistica.net/cache/ba1/31/52/f31201e7ade98dab88d2f36faee8",
+ "assets/build/pylib-android/re.py": "https://files.ballistica.net/cache/ba1/d2/41/e4c70d2365338a2c378f55920849",
"assets/build/pylib-android/reprlib.py": "https://files.ballistica.net/cache/ba1/81/66/44ee9dceee6943006c4500ee3303",
"assets/build/pylib-android/rlcompleter.py": "https://files.ballistica.net/cache/ba1/fe/06/6f06102f9f6c8c0e73a33714c25a",
"assets/build/pylib-android/runpy.py": "https://files.ballistica.net/cache/ba1/6b/e1/0453f97c2fcc323bf89989a74974",
@@ -2925,28 +2925,28 @@
"assets/build/pylib-android/subprocess.py": "https://files.ballistica.net/cache/ba1/f6/bf/640ac9ceb0e3d7cfbe02bef64557",
"assets/build/pylib-android/sunau.py": "https://files.ballistica.net/cache/ba1/ff/0e/1a6c5fd41803511cad28595dc248",
"assets/build/pylib-android/symbol.py": "https://files.ballistica.net/cache/ba1/a5/26/eea6d483c82e7b4048937832889d",
- "assets/build/pylib-android/symtable.py": "https://files.ballistica.net/cache/ba1/46/92/4be884871052300c5e7b9a11164b",
+ "assets/build/pylib-android/symtable.py": "https://files.ballistica.net/cache/ba1/e0/43/5390cbe7195d9edcddbbd2aa1cfa",
"assets/build/pylib-android/sysconfig.py": "https://files.ballistica.net/cache/ba1/9b/d7/6b01292e81749e4d3fd2bf762f7f",
"assets/build/pylib-android/tabnanny.py": "https://files.ballistica.net/cache/ba1/f3/7e/b463d5f4ead23d34a36d0e559447",
"assets/build/pylib-android/tarfile.py": "https://files.ballistica.net/cache/ba1/46/a6/9d1a46c06d7b5e787efbfeadec05",
"assets/build/pylib-android/telnetlib.py": "https://files.ballistica.net/cache/ba1/60/28/4aab22dece4896a4d32694bbe282",
- "assets/build/pylib-android/tempfile.py": "https://files.ballistica.net/cache/ba1/69/88/1a506e6ee4ff144b2aecd4e98ad2",
+ "assets/build/pylib-android/tempfile.py": "https://files.ballistica.net/cache/ba1/03/07/434e753d91b18bbbd9b1c7640ce8",
"assets/build/pylib-android/textwrap.py": "https://files.ballistica.net/cache/ba1/4c/4b/c743c5e7427b00f428c318a9673b",
"assets/build/pylib-android/this.py": "https://files.ballistica.net/cache/ba1/a8/fa/4d1152b689d75bc1a997ff34b799",
- "assets/build/pylib-android/threading.py": "https://files.ballistica.net/cache/ba1/95/c1/7562cfde69149c713cd881cb4d56",
- "assets/build/pylib-android/timeit.py": "https://files.ballistica.net/cache/ba1/b3/b7/a2c93ac110fde00eebcb74a7ced1",
+ "assets/build/pylib-android/threading.py": "https://files.ballistica.net/cache/ba1/11/3a/cdb3194846494446ed43bf6d0050",
+ "assets/build/pylib-android/timeit.py": "https://files.ballistica.net/cache/ba1/55/7b/f7ef83f08ac5cb36ddaff03ac6ab",
"assets/build/pylib-android/token.py": "https://files.ballistica.net/cache/ba1/2d/f8/943c252465b687a5bc367315432f",
"assets/build/pylib-android/tokenize.py": "https://files.ballistica.net/cache/ba1/07/cc/13a7ec5c4d674ab025cb19186f7c",
"assets/build/pylib-android/trace.py": "https://files.ballistica.net/cache/ba1/9b/9d/d6806d339c36bfc6a2b4769688e0",
- "assets/build/pylib-android/traceback.py": "https://files.ballistica.net/cache/ba1/8b/67/e189e176678255fe36a67f9cfe71",
+ "assets/build/pylib-android/traceback.py": "https://files.ballistica.net/cache/ba1/fe/d7/2f880598e52c5c28a46df0ba0555",
"assets/build/pylib-android/tracemalloc.py": "https://files.ballistica.net/cache/ba1/46/49/5683d0d9e0e342392361adb6e9a3",
"assets/build/pylib-android/tty.py": "https://files.ballistica.net/cache/ba1/ad/19/a6ad29b8958fa9f5acc3cf71d3b2",
"assets/build/pylib-android/types.py": "https://files.ballistica.net/cache/ba1/b9/5d/5467b37ac0f36b2ff4dd8ef458fd",
- "assets/build/pylib-android/typing.py": "https://files.ballistica.net/cache/ba1/bf/f6/998b69740a766155dee2eabdf859",
+ "assets/build/pylib-android/typing.py": "https://files.ballistica.net/cache/ba1/de/0e/4506f09141585ca5fa94c90cf678",
"assets/build/pylib-android/urllib/__init__.py": "https://files.ballistica.net/cache/ba1/b0/56/87601ed47a5181d1e6a40eb4ea40",
"assets/build/pylib-android/urllib/error.py": "https://files.ballistica.net/cache/ba1/07/8c/573897fc3bdc6d3e2e8d449f17c7",
"assets/build/pylib-android/urllib/parse.py": "https://files.ballistica.net/cache/ba1/14/09/ffed6f45250b0b2dc1a86f3eb700",
- "assets/build/pylib-android/urllib/request.py": "https://files.ballistica.net/cache/ba1/fd/2c/abd2d31e790eb1bf4c6e19eacfd8",
+ "assets/build/pylib-android/urllib/request.py": "https://files.ballistica.net/cache/ba1/d7/3e/bba38f3fc5c737cef80f48f69184",
"assets/build/pylib-android/urllib/response.py": "https://files.ballistica.net/cache/ba1/c4/d5/676a8e9fc4f7bd21ac2f555fc3fc",
"assets/build/pylib-android/urllib/robotparser.py": "https://files.ballistica.net/cache/ba1/c7/a8/487a1aeccfbf4370fdb33b136b51",
"assets/build/pylib-android/uu.py": "https://files.ballistica.net/cache/ba1/a1/89/070ed8553858a75fcafae4b7bd37",
@@ -2954,7 +2954,7 @@
"assets/build/pylib-android/warnings.py": "https://files.ballistica.net/cache/ba1/74/1f/097efcf5f38c0b41fcba3f60b44d",
"assets/build/pylib-android/wave.py": "https://files.ballistica.net/cache/ba1/f8/72/9e060ca777991ea45d71eed336ca",
"assets/build/pylib-android/weakref.py": "https://files.ballistica.net/cache/ba1/d2/48/f82fb97686199616e57417ee9e7a",
- "assets/build/pylib-android/webbrowser.py": "https://files.ballistica.net/cache/ba1/c4/03/bd37d4bb045d5c20b78c518574fe",
+ "assets/build/pylib-android/webbrowser.py": "https://files.ballistica.net/cache/ba1/26/4a/b0ee4c8655e2c8ea7389d3a2b329",
"assets/build/pylib-android/xdrlib.py": "https://files.ballistica.net/cache/ba1/ec/bf/84d830dca1231ec1a67d8ccbb21f",
"assets/build/pylib-android/xml/__init__.py": "https://files.ballistica.net/cache/ba1/ba/67/bbd97e53f3db5ebc3abd3fef2275",
"assets/build/pylib-android/xml/dom/NodeFilter.py": "https://files.ballistica.net/cache/ba1/36/76/2a47e7bc727db1c44d157b23d2c3",
@@ -4135,16 +4135,16 @@
"assets/build/windows/x64/vc_redist.x64.exe": "https://files.ballistica.net/cache/ba1/ea/19/8b8787d81abcdce158ba608cd24f",
"assets/build/windows/x64/vcruntime140_1d.dll": "https://files.ballistica.net/cache/ba1/11/d8/ff6344b429b00c24d9a1930d4338",
"assets/build/windows/x64/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/20/33/0825e11e6518f87ece3009309933",
- "build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/d4/c1/8271c57f122e0b573e8794f7cd5b",
- "build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/28/75/9db6b288e2d175cf84f955dbf6bb",
- "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/7c/c0/45729931ae9b895cff96045e0fcd",
- "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/df/82/d918dfc09d4eebb56d46bf9b5c87",
- "build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b5/f0/f9b9b7f9de47e96a83ac415802ab",
- "build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/72/bc/8a8e931021e9c5ad34dd4363b0db",
- "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/20/b6/c0ec182a7d36823e401b445e86d6",
- "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/6e/42/7ff30ce0d325d9d5d6d3a7b5bd76",
- "build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/91/40/c29c43a8a01ec909e4743c68c664",
- "build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/1f/46/b28c2c2856aa79cae5130da98752",
- "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/df/df/a3f01417e4e3982e6e8964bd6b06",
- "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/cd/45/268e89bafe3d75129e4bc5a2acbe"
+ "build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/51/d5/b58e2da2a9dd4dba968acbbaf2a4",
+ "build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/71/74/ce3f41e66235e907aedbf609b3bf",
+ "build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/92/6b/ecebeada2b7401f9401877863a21",
+ "build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/07/18/c56004638b1ebd5234974ffe3644",
+ "build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b8/2a/6726ae2d5f56bdc9b663adda0e2e",
+ "build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/34/0c/8604fbcf8979a024d16cf1ad3f38",
+ "build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/00/75/f1d62f08e8b5f523270819bd1ad0",
+ "build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/b8/92/a15a90fe81687a2ef49ef5275617",
+ "build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/4c/f9/0ef6fa2ef75f77d3ebe357a060da",
+ "build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/e2/f6/eb48fccf54236e4016181b37fee6",
+ "build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/97/bc/dd92fe8e0f5ec65356e973228d4d",
+ "build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/19/d1/e83d59e2deb988d6dc2d4032e202"
}
\ No newline at end of file
diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml
index 5b2a603d..07924e3f 100644
--- a/.idea/dictionaries/ericf.xml
+++ b/.idea/dictionaries/ericf.xml
@@ -1392,6 +1392,7 @@
pandroid
parallelized
parsermodule
+ parsetok
partyqueue
partyval
passnode
@@ -1415,6 +1416,7 @@
peditui
pentry
perma
+ perrdetail
phasers
phello
photoshop
diff --git a/tools/efrotools/pybuild.py b/tools/efrotools/pybuild.py
index 3d7f93a4..e7362d69 100644
--- a/tools/efrotools/pybuild.py
+++ b/tools/efrotools/pybuild.py
@@ -297,7 +297,8 @@ def build_android(rootdir: str, arch: str, debug: bool = False) -> None:
efrotools.writefile('pybuild/packages/python.py', ftxt)
# Set this to a particular cpython commit to target exact releases from git
- commit = 'd7c567b08f9d7d6aef21b881340a2b72731129db' # 3.7.7 release
+ # commit = 'd7c567b08f9d7d6aef21b881340a2b72731129db' # 3.7.7 release
+ commit = '4b47a5b6ba66b02df9392feb97b8ead916f8c1fa' # 3.7.8 release
if commit is not None:
ftxt = efrotools.readfile('pybuild/source.py')
@@ -417,6 +418,52 @@ def android_patch() -> None:
' [A-Z]*=*) DEFS="$line$NL$DEFS"; continue;;')
efrotools.writefile(fname, txt)
+ # Add custom callbacks to Python's PyParser_ParseFileObject
+ # and PyParser_ParseString calls to debug a crash.
+ fname = 'src/cpython/Parser/parsetok.c'
+ txt = efrotools.readfile(fname)
+ txt = efrotools.replace_one(
+ txt, 'node *\n'
+ 'PyParser_ParseFileObject(FILE *fp, PyObject *filename,\n'
+ ' const char *enc, grammar *g, int start,\n'
+ ' const char *ps1, const char *ps2,\n'
+ ' perrdetail *err_ret, int *flags)\n'
+ '{\n', 'void (*PyParser_ParseFileObject_EfroCB)'
+ '(FILE *fp, PyObject *filename,\n'
+ ' const char *enc, grammar *g, int start,\n'
+ ' const char *ps1, const char *ps2,\n'
+ ' perrdetail *err_ret, int *flags) = NULL;\n'
+ 'node *\n'
+ 'PyParser_ParseFileObject(FILE *fp, PyObject *filename,\n'
+ ' const char *enc, grammar *g, int start,\n'
+ ' const char *ps1, const char *ps2,\n'
+ ' perrdetail *err_ret, int *flags)\n'
+ '{\n'
+ ' if (PyParser_ParseFileObject_EfroCB != NULL) {\n'
+ ' PyParser_ParseFileObject_EfroCB(fp, filename, enc, g,\n'
+ ' start, ps1, ps2,\n'
+ ' err_ret, flags);\n'
+ ' }\n')
+ txt = efrotools.replace_one(
+ txt, 'node *\n'
+ 'PyParser_ParseStringObject(const char *s, PyObject *filename,\n'
+ ' grammar *g, int start,\n'
+ ' perrdetail *err_ret, int *flags)\n'
+ '{\n', 'void (*PyParser_ParseStringObject_EfroCB)'
+ '(const char *s, PyObject *filename,\n'
+ ' grammar *g, int start,\n'
+ ' perrdetail *err_ret, int *flags) = NULL;\n'
+ 'node *\n'
+ 'PyParser_ParseStringObject(const char *s, PyObject *filename,\n'
+ ' grammar *g, int start,\n'
+ ' perrdetail *err_ret, int *flags)\n'
+ '{\n'
+ ' if (PyParser_ParseStringObject_EfroCB != NULL) {\n'
+ ' PyParser_ParseStringObject_EfroCB(s, filename, g, start,\n'
+ ' err_ret, flags);\n'
+ ' }\n')
+ efrotools.writefile(fname, txt)
+
print('APPLIED EFROTOOLS ANDROID BUILD PATCHES.')