added soft_default functionality to dataclassio

This commit is contained in:
Eric Froemling 2022-04-21 17:54:36 -07:00
parent 7677658104
commit 9529c7cf32
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
21 changed files with 293 additions and 97 deletions

View File

@ -3971,50 +3971,50 @@
"assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e", "assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e",
"assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34", "assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/b2/e5/0ee0561e16257a32830645239f34",
"ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a", "ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a",
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/fd/f8/10dab633b840e11d48028ece0e94", "build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/3a/d3/38075453348d9d2abd102554a937",
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/95/5c/25082f7cccc42c15e5b83c75c475", "build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/9c/1c/1cd7a078b292c0d01d634f97f222",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/5e/97/9e0e1c1dc834ad181859b0ee0b78", "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/fa/20/4f69c5c8a3e9bf9afabff8a7118f",
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/89/b2/1c0acb568e9c59ac9fd5874cae5f", "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3a/3a/d23f5fabe309b6e8694aff471b9b",
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/0b/18/2bc39720f1316779415cc94cb113", "build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/4d/6f/12942dd120a3ec0963249b596989",
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/ac/a7/6a840428e14ef51bcd0df363a434", "build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/4d/90/3b11a947cd2befe576c12dc58a9c",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c2/41/0c32e18e1e70a972a1115e92e186", "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/77/77/2c01655f3144cd40c9ee252c7226",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/47/64/7ccc6f00b6956c1a7432432549bd", "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f2/62/a0ba340093f8c143ab39149244e9",
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/c9/4f/5440667c1b6fea19ae0de266bfd8", "build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/67/a9/4b48db661bc7b1f6338ee0389e87",
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/32/f0/239dbf6e7dd3cd3db7486fde7407", "build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/8e/44/c087c45ca09e5a8e4284076d4663",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/98/72/6c901ee766aebf76fb80eae90589", "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/d8/ee/452c5c9164807e82d97214f7fc5b",
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/db/1e/6774a41b43542afc038908d8e89b", "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/7a/f0/2a4003966c6e7ec531bcfb19f013",
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/df/d2/1fd51009e9fb22045c2a583cd64a", "build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ec/be/637f05ea13de731126047d88a6c2",
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/fd/81/3fc11ac92e6ebcec071c7f93ffe7", "build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/53/c6/2503d6a33f1a86d3504732091540",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/33/7b/20b1def5897ee9f60817b75cb51f", "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/26/14/ba5b7d47bec90c93af50fe344a1e",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/51/13/b66b6692b578e3c1b7a253ac764e", "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/89/79/e08d502d6b980db9c9506b6614ca",
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/06/e4/45df563117d8cc07f606d3df504f", "build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/62/a7/c88cf55d6242a7b28467b193cb7f",
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/cf/d4/885ba111bb2b13084cf31f64cede", "build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/36/7e/6f55132fea94bbca6b41cc764a28",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/20/2d/3c0bc587aea1bd0e04702bfe2291", "build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/f4/4a/a7aa2270ca1bd8cc15cb5204d089",
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/19/25/9ae33702dec28a19114b023f9dd5", "build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/86/df/dd3bef3462b735d85243e24540f9",
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c2/86/37c7b19623c5f72eb4223f1fa6a2", "build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f9/81/e339e45d6c650df8217acbfb5f29",
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f2/ee/e42d3fe7a0d2ad6a4395c6b5fd1f", "build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/de/d8/ce0ae67d8fa1bc4afb931c2e8a0f",
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/27/4a/439e5c93cf7fdf31893dcc1cfaa3", "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7b/0a/4907ea64f8492164a84ab9503aaf",
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/cf/4e/a1085b9060bb4c7ee260bcd3291c", "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/48/b4/8ed406ae6ff13da64c7ec97b6f56",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/84/42/59f61b5645662d30c1ad2c6410b9", "build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/63/60/190e42f26c0f1224c2ffa69e3992",
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/3d/f8/9298792aa9378a520596bba6a388", "build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d0/61/a4936fb9455dcd014a1eb5e570f1",
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/27/bb/cae4aa7229c869262db19e9dcdd8", "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/29/75/b61dae6070661f68ddb54cf14ee4",
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/5a/de/1e35235ed2b1279fd95b845ed04d", "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2f/31/1373c730b4e06c515a439b2e15d9",
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/53/05/e570e9edd509552a3d2028ab099d", "build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7e/f2/567e3019d15c23424bd9c8562679",
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/20/e9/9a956250851d65a3602c20ae990a", "build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b2/43/4c8e335e4771c9bbc01737ca8ca8",
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/09/1c/d3536f33192842c6b30b06771611", "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0b/4c/6d68b4f4b2e10597ca74dff0b0cb",
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0c/4a/77171c3984442e73727bbf47ddec", "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1d/c1/f566397ffc7d5c943b32c6508479",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a1/a7/25adabdaa21491cd25ef28a4f846", "build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4d/07/d0ed02b5363672e0e1039567ce60",
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ba/0f/eaee0823fe7a1f299e3a19578451", "build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8f/fc/e9c87d067c8511b8183f09dcd05d",
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/66/fe/17320024436fd49b4d8886075fc9", "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f7/e0/94da6e5b577853226c1ca81978de",
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c4/77/17075093fd218bd46e6dad294f3f", "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1b/06/983ab3446f2bf0b31a0d8c93322b",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/f3/f3/a31d843c10f30086f84368376b35", "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/1c/dd/cf46a040f49e72b0693f10f72ca6",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/c9/e9/221a9f0d18117353851624446b32", "build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/1b/f9/c5b6eeb4493d4a8acba006bc4293",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/c3/54/0de51809c3a7edf28c38dd144a10", "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/cc/d1/e7965899f642259e45adc059b629",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/03/4d/76acfd2bcd4c0c94a85e450bc3d3", "build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/09/67/573507643fe3790b9f19ec707be0",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/a4/94/76a46fa659db22ca2155e1b423a9", "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/1a/d0/a33a7402cdf38076ac726f155fcf",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/60/a3/5e7fe045108577d6c17076838c99", "build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/81/fb/68aaa7cb8fad0a49c6a9b47590b5",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/9d/5d/7d24ce4b8cccfca69c593ff59bfe", "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/7f/83/62496b38a9828d6ed21d41a636ea",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/c9/4c/751c6d0ea202603d20385aaa1d94", "build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/89/1a/9d4b19c0c6fa33db78e75376c7e8",
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/b3/15/7c6d580b3482870b5b058858624c", "src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/b3/15/7c6d580b3482870b5b058858624c",
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/d3/db/e73d4dcf1280d5f677c3cf8b47c3" "src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/d3/db/e73d4dcf1280d5f677c3cf8b47c3"
} }

View File

@ -81,6 +81,7 @@
<w>anyofallof</w> <w>anyofallof</w>
<w>anyval</w> <w>anyval</w>
<w>aosp</w> <w>aosp</w>
<w>aparsed</w>
<w>apichanges</w> <w>apichanges</w>
<w>apis</w> <w>apis</w>
<w>apks</w> <w>apks</w>
@ -217,6 +218,7 @@
<w>bdir</w> <w>bdir</w>
<w>belarussian</w> <w>belarussian</w>
<w>benboncan</w> <w>benboncan</w>
<w>benning</w>
<w>bfiledir</w> <w>bfiledir</w>
<w>bfiles</w> <w>bfiles</w>
<w>bgmodel</w> <w>bgmodel</w>
@ -847,6 +849,7 @@
<w>flav</w> <w>flav</w>
<w>fldtypes</w> <w>fldtypes</w>
<w>flines</w> <w>flines</w>
<w>floinkdingle</w>
<w>floof</w> <w>floof</w>
<w>floofcls</w> <w>floofcls</w>
<w>floop</w> <w>floop</w>
@ -950,6 +953,7 @@
<w>gametypes</w> <w>gametypes</w>
<w>gameutils</w> <w>gameutils</w>
<w>gbytecount</w> <w>gbytecount</w>
<w>gcwe</w>
<w>gearvr</w> <w>gearvr</w>
<w>genchangelog</w> <w>genchangelog</w>
<w>gencmd</w> <w>gencmd</w>
@ -1383,6 +1387,7 @@
<w>ltypes</w> <w>ltypes</w>
<w>lubyte</w> <w>lubyte</w>
<w>luuid</w> <w>luuid</w>
<w>lval</w>
<w>lzma</w> <w>lzma</w>
<w>lzmamodule</w> <w>lzmamodule</w>
<w>macappstore</w> <w>macappstore</w>
@ -1648,6 +1653,7 @@
<w>ogval</w> <w>ogval</w>
<w>oival</w> <w>oival</w>
<w>okbtn</w> <w>okbtn</w>
<w>oldbook</w>
<w>oldlady</w> <w>oldlady</w>
<w>onln</w> <w>onln</w>
<w>onscreencountdown</w> <w>onscreencountdown</w>
@ -1818,6 +1824,7 @@
<w>prch</w> <w>prch</w>
<w>prec</w> <w>prec</w>
<w>precommand</w> <w>precommand</w>
<w>precompiling</w>
<w>preconfig</w> <w>preconfig</w>
<w>preexec</w> <w>preexec</w>
<w>prefablib</w> <w>prefablib</w>
@ -1877,6 +1884,7 @@
<w>ptrans</w> <w>ptrans</w>
<w>ptype</w> <w>ptype</w>
<w>ptypename</w> <w>ptypename</w>
<w>pubdeviceid</w>
<w>publictab</w> <w>publictab</w>
<w>pubsync</w> <w>pubsync</w>
<w>pubtargets</w> <w>pubtargets</w>

View File

@ -1,4 +1,4 @@
### 1.6.12 (20556, 2022-04-19) ### 1.6.12 (20561, 2022-04-21)
- More internal work on V2 master-server communication - More internal work on V2 master-server communication
### 1.6.11 (20539, 2022-03-23) ### 1.6.11 (20539, 2022-03-23)

View File

@ -695,6 +695,11 @@ test-message:
@tools/pcommand pytest -o log_cli=true -o log_cli_level=debug -s -vv \ @tools/pcommand pytest -o log_cli=true -o log_cli_level=debug -s -vv \
tests/test_efro/test_message.py tests/test_efro/test_message.py
# Individual test with extra output enabled.
test-dataclassio:
@tools/pcommand pytest -o log_cli=true -o log_cli_level=debug -s -vv \
tests/test_efro/test_dataclassio.py
# Individual test with extra output enabled. # Individual test with extra output enabled.
test-rpc: test-rpc:
@tools/pcommand pytest -o log_cli=true -o log_cli_level=debug -s -vv \ @tools/pcommand pytest -o log_cli=true -o log_cli_level=debug -s -vv \

View File

@ -53,6 +53,7 @@
<w>anyofallof</w> <w>anyofallof</w>
<w>anyval</w> <w>anyval</w>
<w>aosp</w> <w>aosp</w>
<w>aparsed</w>
<w>apientry</w> <w>apientry</w>
<w>apost</w> <w>apost</w>
<w>appconfig</w> <w>appconfig</w>
@ -104,6 +105,7 @@
<w>bbbbbbb</w> <w>bbbbbbb</w>
<w>bcfn</w> <w>bcfn</w>
<w>bdea</w> <w>bdea</w>
<w>benning</w>
<w>bezanson</w> <w>bezanson</w>
<w>bgra</w> <w>bgra</w>
<w>bigendian</w> <w>bigendian</w>
@ -418,6 +420,7 @@
<w>fjco</w> <w>fjco</w>
<w>fjcoiwef</w> <w>fjcoiwef</w>
<w>flipbit</w> <w>flipbit</w>
<w>floinkdingle</w>
<w>floop</w> <w>floop</w>
<w>flopsy</w> <w>flopsy</w>
<w>fname</w> <w>fname</w>
@ -462,6 +465,7 @@
<w>gasmsg</w> <w>gasmsg</w>
<w>gbus</w> <w>gbus</w>
<w>gcc's</w> <w>gcc's</w>
<w>gcwe</w>
<w>gearvr</w> <w>gearvr</w>
<w>genchangelog</w> <w>genchangelog</w>
<w>gencmd</w> <w>gencmd</w>
@ -668,6 +672,7 @@
<w>ltypes</w> <w>ltypes</w>
<w>lubyte</w> <w>lubyte</w>
<w>luuid</w> <w>luuid</w>
<w>lval</w>
<w>lvec</w> <w>lvec</w>
<w>lvoid</w> <w>lvoid</w>
<w>macbuild</w> <w>macbuild</w>
@ -821,6 +826,7 @@
<w>offsy</w> <w>offsy</w>
<w>oiffsss</w> <w>oiffsss</w>
<w>okbtn</w> <w>okbtn</w>
<w>oldbook</w>
<w>oldname</w> <w>oldname</w>
<w>oooo</w> <w>oooo</w>
<w>ooooooo</w> <w>ooooooo</w>
@ -896,6 +902,7 @@
<w>ppre</w> <w>ppre</w>
<w>pptabcom</w> <w>pptabcom</w>
<w>precalc</w> <w>precalc</w>
<w>precompiling</w>
<w>preconfig</w> <w>preconfig</w>
<w>predeclare</w> <w>predeclare</w>
<w>prefs</w> <w>prefs</w>
@ -926,6 +933,7 @@
<w>ptrs</w> <w>ptrs</w>
<w>ptype</w> <w>ptype</w>
<w>ptypename</w> <w>ptypename</w>
<w>pubdeviceid</w>
<w>publictab</w> <w>publictab</w>
<w>pubtargets</w> <w>pubtargets</w>
<w>pulseaudio</w> <w>pulseaudio</w>

View File

@ -10,8 +10,11 @@
<option name="clangTidyChecks" value="-*,bugprone-argument-comment,bugprone-assert-side-effect,bugprone-bad-signal-to-kill-thread,bugprone-branch-clone,bugprone-copy-constructor-init,bugprone-dangling-handle,bugprone-dynamic-static-initializers,bugprone-fold-init-type,bugprone-forward-declaration-namespace,bugprone-forwarding-reference-overload,bugprone-inaccurate-erase,bugprone-incorrect-roundings,bugprone-integer-division,bugprone-macro-parentheses,bugprone-macro-repeated-side-effects,bugprone-misplaced-operator-in-strlen-in-alloc,bugprone-misplaced-pointer-arithmetic-in-alloc,bugprone-misplaced-widening-cast,bugprone-move-forwarding-reference,bugprone-multiple-statement-macro,bugprone-no-escape,bugprone-not-null-terminated-result,bugprone-parent-virtual-call,bugprone-posix-return,bugprone-sizeof-container,bugprone-sizeof-expression,bugprone-spuriously-wake-up-functions,bugprone-string-constructor,bugprone-string-integer-assignment,bugprone-string-literal-with-embedded-nul,bugprone-suspicious-enum-usage,bugprone-suspicious-include,bugprone-suspicious-memset-usage,bugprone-suspicious-missing-comma,bugprone-suspicious-semicolon,bugprone-suspicious-string-compare,bugprone-swapped-arguments,bugprone-terminating-continue,bugprone-throw-keyword-missing,bugprone-too-small-loop-variable,bugprone-undefined-memory-manipulation,bugprone-undelegated-constructor,bugprone-unhandled-self-assignment,bugprone-unused-raii,bugprone-unused-return-value,bugprone-use-after-move,bugprone-virtual-near-miss,cert-dcl21-cpp,cert-dcl58-cpp,cert-err34-c,cert-err52-cpp,cert-err58-cpp,cert-err60-cpp,cert-flp30-c,cert-msc50-cpp,cert-msc51-cpp,cppcoreguidelines-interfaces-global-init,cppcoreguidelines-narrowing-conversions,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-slicing,google-default-arguments,google-explicit-constructor,google-runtime-operator,hicpp-exception-baseclass,hicpp-multiway-paths-covered,misc-misplaced-const,misc-new-delete-overloads,misc-no-recursion,misc-non-copyable-objects,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,misc-uniqueptr-reset-release,modernize-avoid-bind,modernize-concat-nested-namespaces,modernize-deprecated-headers,modernize-deprecated-ios-base-aliases,modernize-loop-convert,modernize-make-shared,modernize-make-unique,modernize-pass-by-value,modernize-raw-string-literal,modernize-redundant-void-arg,modernize-replace-auto-ptr,modernize-replace-disallow-copy-and-assign-macro,modernize-replace-random-shuffle,modernize-return-braced-init-list,modernize-shrink-to-fit,modernize-unary-static-assert,modernize-use-auto,modernize-use-bool-literals,modernize-use-emplace,modernize-use-equals-default,modernize-use-equals-delete,modernize-use-noexcept,modernize-use-nullptr,modernize-use-override,modernize-use-transparent-functors,modernize-use-uncaught-exceptions,mpi-buffer-deref,mpi-type-mismatch,openmp-use-default-none,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-algorithm,performance-inefficient-string-concatenation,performance-inefficient-vector-operation,performance-move-const-arg,performance-move-constructor-init,performance-no-automatic-move,performance-noexcept-move-constructor,performance-trivially-destructible,performance-type-promotion-in-math-fn,performance-unnecessary-copy-initialization,performance-unnecessary-value-param,portability-simd-intrinsics,readability-avoid-const-params-in-decls,readability-const-return-type,readability-container-size-empty,readability-delete-null-pointer,readability-deleted-default,readability-inconsistent-declaration-parameter-name,readability-misleading-indentation,readability-misplaced-array-index,readability-non-const-parameter,readability-redundant-control-flow,readability-redundant-declaration,readability-redundant-function-ptr-dereference,readability-redundant-smartptr-get,readability-redundant-string-cstr,readability-redundant-string-init,readability-simplify-subscript-expr,readability-static-accessed-through-instance,readability-static-definition-in-anonymous-namespace,readability-string-compare,readability-uniqueptr-delete-release,readability-use-anyofallof,-misc-no-recursion" /> <option name="clangTidyChecks" value="-*,bugprone-argument-comment,bugprone-assert-side-effect,bugprone-bad-signal-to-kill-thread,bugprone-branch-clone,bugprone-copy-constructor-init,bugprone-dangling-handle,bugprone-dynamic-static-initializers,bugprone-fold-init-type,bugprone-forward-declaration-namespace,bugprone-forwarding-reference-overload,bugprone-inaccurate-erase,bugprone-incorrect-roundings,bugprone-integer-division,bugprone-macro-parentheses,bugprone-macro-repeated-side-effects,bugprone-misplaced-operator-in-strlen-in-alloc,bugprone-misplaced-pointer-arithmetic-in-alloc,bugprone-misplaced-widening-cast,bugprone-move-forwarding-reference,bugprone-multiple-statement-macro,bugprone-no-escape,bugprone-not-null-terminated-result,bugprone-parent-virtual-call,bugprone-posix-return,bugprone-sizeof-container,bugprone-sizeof-expression,bugprone-spuriously-wake-up-functions,bugprone-string-constructor,bugprone-string-integer-assignment,bugprone-string-literal-with-embedded-nul,bugprone-suspicious-enum-usage,bugprone-suspicious-include,bugprone-suspicious-memset-usage,bugprone-suspicious-missing-comma,bugprone-suspicious-semicolon,bugprone-suspicious-string-compare,bugprone-swapped-arguments,bugprone-terminating-continue,bugprone-throw-keyword-missing,bugprone-too-small-loop-variable,bugprone-undefined-memory-manipulation,bugprone-undelegated-constructor,bugprone-unhandled-self-assignment,bugprone-unused-raii,bugprone-unused-return-value,bugprone-use-after-move,bugprone-virtual-near-miss,cert-dcl21-cpp,cert-dcl58-cpp,cert-err34-c,cert-err52-cpp,cert-err58-cpp,cert-err60-cpp,cert-flp30-c,cert-msc50-cpp,cert-msc51-cpp,cppcoreguidelines-interfaces-global-init,cppcoreguidelines-narrowing-conversions,cppcoreguidelines-pro-type-member-init,cppcoreguidelines-slicing,google-default-arguments,google-explicit-constructor,google-runtime-operator,hicpp-exception-baseclass,hicpp-multiway-paths-covered,misc-misplaced-const,misc-new-delete-overloads,misc-no-recursion,misc-non-copyable-objects,misc-throw-by-value-catch-by-reference,misc-unconventional-assign-operator,misc-uniqueptr-reset-release,modernize-avoid-bind,modernize-concat-nested-namespaces,modernize-deprecated-headers,modernize-deprecated-ios-base-aliases,modernize-loop-convert,modernize-make-shared,modernize-make-unique,modernize-pass-by-value,modernize-raw-string-literal,modernize-redundant-void-arg,modernize-replace-auto-ptr,modernize-replace-disallow-copy-and-assign-macro,modernize-replace-random-shuffle,modernize-return-braced-init-list,modernize-shrink-to-fit,modernize-unary-static-assert,modernize-use-auto,modernize-use-bool-literals,modernize-use-emplace,modernize-use-equals-default,modernize-use-equals-delete,modernize-use-noexcept,modernize-use-nullptr,modernize-use-override,modernize-use-transparent-functors,modernize-use-uncaught-exceptions,mpi-buffer-deref,mpi-type-mismatch,openmp-use-default-none,performance-faster-string-find,performance-for-range-copy,performance-implicit-conversion-in-loop,performance-inefficient-algorithm,performance-inefficient-string-concatenation,performance-inefficient-vector-operation,performance-move-const-arg,performance-move-constructor-init,performance-no-automatic-move,performance-noexcept-move-constructor,performance-trivially-destructible,performance-type-promotion-in-math-fn,performance-unnecessary-copy-initialization,performance-unnecessary-value-param,portability-simd-intrinsics,readability-avoid-const-params-in-decls,readability-const-return-type,readability-container-size-empty,readability-delete-null-pointer,readability-deleted-default,readability-inconsistent-declaration-parameter-name,readability-misleading-indentation,readability-misplaced-array-index,readability-non-const-parameter,readability-redundant-control-flow,readability-redundant-declaration,readability-redundant-function-ptr-dereference,readability-redundant-smartptr-get,readability-redundant-string-cstr,readability-redundant-string-init,readability-simplify-subscript-expr,readability-static-accessed-through-instance,readability-static-definition-in-anonymous-namespace,readability-string-compare,readability-uniqueptr-delete-release,readability-use-anyofallof,-misc-no-recursion" />
<option name="preferClangTidyFilesOverIDESettings" value="false" /> <option name="preferClangTidyFilesOverIDESettings" value="false" />
</inspection_tool> </inspection_tool>
<inspection_tool class="ConstantConditionsOC" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConstantFunctionResult" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConstructionIsNotAllowed" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="ConstructionIsNotAllowed" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DuplicateSwitchCase" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="DuplicateSwitchCase" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="EndlessLoop" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="GrazieInspection" enabled="false" level="TYPO" enabled_by_default="false" /> <inspection_tool class="GrazieInspection" enabled="false" level="TYPO" enabled_by_default="false" />
<inspection_tool class="HttpUrlsUsage" enabled="true" level="WEAK WARNING" enabled_by_default="true"> <inspection_tool class="HttpUrlsUsage" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredUrls"> <option name="ignoredUrls">
@ -93,6 +96,8 @@
<option name="enableSimplifyTernaryWithConstantBranch" value="false" /> <option name="enableSimplifyTernaryWithConstantBranch" value="false" />
</inspection_tool> </inspection_tool>
<inspection_tool class="StaticnessMismatch" enabled="false" level="ERROR" enabled_by_default="false" /> <inspection_tool class="StaticnessMismatch" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="UnreachableCallsOfFunction" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnreachableCode" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnusedExpressionResult" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="UnusedExpressionResult" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnusedGlobalDeclaration" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="UnusedGlobalDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="UnusedLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" /> <inspection_tool class="UnusedLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" />

View File

@ -21,7 +21,7 @@
namespace ballistica { namespace ballistica {
// These are set automatically via script; don't modify them here. // These are set automatically via script; don't modify them here.
const int kAppBuildNumber = 20556; const int kAppBuildNumber = 20561;
const char* kAppVersion = "1.6.12"; const char* kAppVersion = "1.6.12";
// Our standalone globals. // Our standalone globals.

View File

@ -5,6 +5,7 @@
#include "ballistica/ballistica.h" #include "ballistica/ballistica.h"
#include "ballistica/dynamics/material/material_action.h" #include "ballistica/dynamics/material/material_action.h"
#include "ballistica/media/component/sound.h"
namespace ballistica { namespace ballistica {

View File

@ -89,7 +89,9 @@ void TestInput::Process(millisecs_t time) {
HandleAlreadyPressedTwice(); HandleAlreadyPressedTwice();
} else { } else {
jump_pressed_ = !jump_pressed_; jump_pressed_ = !jump_pressed_;
if (jump_pressed_) join_press_count_++; if (jump_pressed_) {
join_press_count_++;
}
e.type = jump_pressed_ ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP; e.type = jump_pressed_ ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP;
e.jbutton.button = 0; e.jbutton.button = 0;
g_input->PushJoystickEvent(e, joystick_); g_input->PushJoystickEvent(e, joystick_);
@ -121,7 +123,9 @@ void TestInput::Process(millisecs_t time) {
HandleAlreadyPressedTwice(); HandleAlreadyPressedTwice();
} else { } else {
pickup_pressed_ = !pickup_pressed_; pickup_pressed_ = !pickup_pressed_;
if (pickup_pressed_) join_press_count_++; if (pickup_pressed_) {
join_press_count_++;
}
e.type = pickup_pressed_ ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP; e.type = pickup_pressed_ ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP;
e.jbutton.button = 3; e.jbutton.button = 3;
g_input->PushJoystickEvent(e, joystick_); g_input->PushJoystickEvent(e, joystick_);
@ -133,7 +137,9 @@ void TestInput::Process(millisecs_t time) {
HandleAlreadyPressedTwice(); HandleAlreadyPressedTwice();
} else { } else {
punch_pressed_ = !punch_pressed_; punch_pressed_ = !punch_pressed_;
if (punch_pressed_) join_press_count_++; if (punch_pressed_) {
join_press_count_++;
}
e.type = punch_pressed_ ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP; e.type = punch_pressed_ ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP;
e.jbutton.button = 1; e.jbutton.button = 1;
g_input->PushJoystickEvent(e, joystick_); g_input->PushJoystickEvent(e, joystick_);

View File

@ -77,7 +77,7 @@ class PlatformApple : public Platform {
auto DoClipboardHasText() -> bool override; auto DoClipboardHasText() -> bool override;
auto DoClipboardSetText(const std::string& text) -> void override; auto DoClipboardSetText(const std::string& text) -> void override;
auto DoClipboardGetText() -> std::string override; auto DoClipboardGetText() -> std::string override;
auto GetPublicDeviceUUIDInputs() -> std::list<std::string> override; auto GetDeviceUUIDInputs() -> std::list<std::string> override;
private: private:
}; };

View File

@ -29,7 +29,7 @@ std::string PlatformLinux::GenerateUUID() {
return val; return val;
} }
auto PlatformLinux::GetPublicDeviceUUIDInputs() -> std::list<std::string> { auto PlatformLinux::GetDeviceUUIDInputs() -> std::list<std::string> {
std::list<std::string> out; std::list<std::string> out;
// For now let's just go with machine-id. // For now let's just go with machine-id.

View File

@ -21,7 +21,7 @@ class PlatformLinux : public Platform {
auto OpenDirExternally(const std::string& path) -> void override; auto OpenDirExternally(const std::string& path) -> void override;
auto GetPlatformName() -> std::string override; auto GetPlatformName() -> std::string override;
auto GetSubplatformName() -> std::string override; auto GetSubplatformName() -> std::string override;
auto GetPublicDeviceUUIDInputs() -> std::list<std::string> override; auto GetDeviceUUIDInputs() -> std::list<std::string> override;
}; };
} // namespace ballistica } // namespace ballistica

View File

@ -184,17 +184,13 @@ auto Platform::GenerateUUID() -> std::string {
auto Platform::GetPublicDeviceUUID() -> std::string { auto Platform::GetPublicDeviceUUID() -> std::string {
assert(g_python); assert(g_python);
if (public_device_uuid_.empty()) { if (public_device_uuid_.empty()) {
std::list<std::string> inputs{GetPublicDeviceUUIDInputs()}; std::list<std::string> inputs{GetDeviceUUIDInputs()};
// This UUID is supposed to change periodically, so let's plug in // This UUID is supposed to change periodically, so let's plug in
// some stuff to enforce that. // some stuff to enforce that.
inputs.emplace_back(GetOSVersionString()); inputs.emplace_back(GetOSVersionString());
inputs.emplace_back(kAppVersion); inputs.emplace_back(kAppVersion);
inputs.emplace_back("kerploople"); inputs.emplace_back("kerploople");
// int i{};
// for (auto&& input : inputs) {
// printf("INPUT %d IS %s\n", i + 1, input.c_str());
// }
auto gil{Python::ScopedInterpreterLock()}; auto gil{Python::ScopedInterpreterLock()};
auto pylist{g_python->StringList(inputs)}; auto pylist{g_python->StringList(inputs)};
auto args{g_python->SingleMemberTuple(pylist)}; auto args{g_python->SingleMemberTuple(pylist)};
@ -205,8 +201,8 @@ auto Platform::GetPublicDeviceUUID() -> std::string {
return public_device_uuid_; return public_device_uuid_;
} }
auto Platform::GetPublicDeviceUUIDInputs() -> std::list<std::string> { auto Platform::GetDeviceUUIDInputs() -> std::list<std::string> {
throw Exception("GetPublicDeviceUUIDInputs unimplemented"); throw Exception("GetDeviceUUIDInputs unimplemented");
} }
auto Platform::GetDefaultConfigDir() -> std::string { auto Platform::GetDefaultConfigDir() -> std::string {
@ -860,7 +856,7 @@ auto Platform::GetUserAgentString() -> std::string {
+ "; " + GetLocale() + ")"}; + "; " + GetLocale() + ")"};
// This gets shipped to various places which might choke on fancy unicode // This gets shipped to various places which might choke on fancy unicode
// characers, so let's limit to simple ascii. // characters, so let's limit to simple ascii.
out = Utils::StripNonAsciiFromUTF8(out); out = Utils::StripNonAsciiFromUTF8(out);
return out; return out;

View File

@ -186,13 +186,12 @@ class Platform {
/// server bans or spam prevention. /// server bans or spam prevention.
auto GetPublicDeviceUUID() -> std::string; auto GetPublicDeviceUUID() -> std::string;
/// Return values which will be hashed to create a public device uuid. /// Return values which can be hashed to create a public device uuid.
/// These values may include things that may change periodically such /// Ideally these values should come from an OS-provided guid. They
/// as minor os version numbers, but they should not include things /// should not include anything that is easily user-changeable.
/// that change constantly or that can be changed easily by the user. /// IMPORTANT: Only hashed/transformed versions of these values should
/// Only hashed versions of these values should ever be shared beyond /// ever be shared beyond the local device.
/// the local device. virtual auto GetDeviceUUIDInputs() -> std::list<std::string>;
virtual auto GetPublicDeviceUUIDInputs() -> std::list<std::string>;
/// Return whether there is an actual legacy-device-uuid value for /// Return whether there is an actual legacy-device-uuid value for
/// this platform, and also return it if so. /// this platform, and also return it if so.

View File

@ -127,7 +127,7 @@ void PlatformWindows::SetupInterruptHandling() {
} }
} }
auto PlatformWindows::GetPublicDeviceUUIDInputs() -> std::list<std::string> { auto PlatformWindows::GetDeviceUUIDInputs() -> std::list<std::string> {
std::list<std::string> out; std::list<std::string> out;
std::string ret; std::string ret;

View File

@ -16,7 +16,7 @@ class PlatformWindows : public Platform {
PlatformWindows(); PlatformWindows();
void SetupInterruptHandling() override; void SetupInterruptHandling() override;
auto GetDeviceAccountUUIDPrefix() -> std::string override { return "w"; } auto GetDeviceAccountUUIDPrefix() -> std::string override { return "w"; }
auto GetPublicDeviceUUIDInputs() -> std::list<std::string> override; auto GetDeviceUUIDInputs() -> std::list<std::string> override;
auto GenerateUUID() -> std::string override; auto GenerateUUID() -> std::string override;
auto GetDefaultConfigDir() -> std::string override; auto GetDefaultConfigDir() -> std::string override;
auto Remove(const char* path) -> int; auto Remove(const char* path) -> int;

View File

@ -873,3 +873,84 @@ def test_extended_data() -> None:
# Uses our output filter. # Uses our output filter.
assert dataclass_to_dict(_TestClass2(vals=(1, 2))) == {'vals': [0, 0]} assert dataclass_to_dict(_TestClass2(vals=(1, 2))) == {'vals': [0, 0]}
def test_soft_default() -> None:
"""Test soft_default IOAttr value."""
# Try both of these with and without storage_name to make sure
# soft_default interacts correctly with both cases.
@ioprepped
@dataclass
class _TestClassA:
ival: int
@ioprepped
@dataclass
class _TestClassA2:
ival: Annotated[int, IOAttrs('i')]
@ioprepped
@dataclass
class _TestClassB:
ival: Annotated[int, IOAttrs(soft_default=0)]
@ioprepped
@dataclass
class _TestClassB2:
ival: Annotated[int, IOAttrs('i', soft_default=0)]
@ioprepped
@dataclass
class _TestClassB3:
ival: Annotated[int, IOAttrs('i', soft_default_factory=lambda: 0)]
# These should fail because there's no value for ival.
with pytest.raises(ValueError):
dataclass_from_dict(_TestClassA, {})
with pytest.raises(ValueError):
dataclass_from_dict(_TestClassA2, {})
# These should succeed because it has a soft-default value to
# fall back on.
dataclass_from_dict(_TestClassB, {})
dataclass_from_dict(_TestClassB2, {})
dataclass_from_dict(_TestClassB3, {})
# soft_default should also allow using store_default=False without
# requiring the dataclass to contain a default or default_factory
@ioprepped
@dataclass
class _TestClassC:
ival: Annotated[int, IOAttrs(store_default=False)] = 0
assert dataclass_to_dict(_TestClassC()) == {}
# This should fail since store_default would be meaningless without
# any source for the default value.
with pytest.raises(TypeError):
@ioprepped
@dataclass
class _TestClassC2:
ival: Annotated[int, IOAttrs(store_default=False)]
# However with our shiny soft_default it should work.
@ioprepped
@dataclass
class _TestClassC3:
ival: Annotated[int, IOAttrs(store_default=False, soft_default=0)]
assert dataclass_to_dict(_TestClassC3(0)) == {}
# we should disallow passing a few mutable types as soft_defaults
# just as dataclass does with regular defaults.
with pytest.raises(TypeError):
@ioprepped
@dataclass
class _TestClassD:
lval: Annotated[list, IOAttrs(soft_default=[])]

View File

@ -13,7 +13,7 @@ from typing import TYPE_CHECKING, get_args
from typing import _AnnotatedAlias # type: ignore from typing import _AnnotatedAlias # type: ignore
if TYPE_CHECKING: if TYPE_CHECKING:
from typing import Any, Optional from typing import Any, Optional, Callable, Union
# Types which we can pass through as-is. # Types which we can pass through as-is.
SIMPLE_TYPES = {int, bool, str, float, type(None)} SIMPLE_TYPES = {int, bool, str, float, type(None)}
@ -96,18 +96,50 @@ def _is_valid_for_codec(obj: Any, codec: Codec) -> bool:
class IOAttrs: class IOAttrs:
"""For specifying io behavior in annotations.""" """For specifying io behavior in annotations.
'storagename', if passed, is the name used when storing to json/etc.
'store_default' can be set to False to avoid writing values when equal
to the default value. Note that this requires the dataclass field
to define a default or default_factory or for its IOAttrs to
define a soft_default value.
'whole_days', if True, requires datetime values to be exactly on day
boundaries (see efro.util.utc_today()).
'whole_hours', if True, requires datetime values to lie exactly on hour
boundaries (see efro.util.utc_this_hour()).
'soft_default', if passed, is used as a default for loading and storing
purposes, but leaves the dataclass itself expecting a value to
be passed in all constructor calls/etc. This is useful when fields
are added that should not be considered optional in new code but for
which there may exist old data that does not contain those values.
'soft_default_factory' should be given instead of 'soft_default' for
mutable types such as lists (to prevent the default from changing
over time).
"""
# A sentinel object to detect if a parameter is supplied or not. Use
# a class to give it a better repr.
class _MissingType:
pass
MISSING = _MissingType()
storagename: Optional[str] = None storagename: Optional[str] = None
store_default: bool = True store_default: bool = True
whole_days: bool = False whole_days: bool = False
whole_hours: bool = False whole_hours: bool = False
soft_default: Any = MISSING
soft_default_factory: Union[Callable[[], Any], _MissingType] = MISSING
def __init__(self, def __init__(
storagename: Optional[str] = storagename, self,
store_default: bool = store_default, storagename: Optional[str] = storagename,
whole_days: bool = whole_days, store_default: bool = store_default,
whole_hours: bool = whole_hours): whole_days: bool = whole_days,
whole_hours: bool = whole_hours,
soft_default: Any = MISSING,
soft_default_factory: Union[Callable[[], Any], _MissingType] = MISSING,
):
# Only store values that differ from class defaults to keep # Only store values that differ from class defaults to keep
# our instances nice and lean. # our instances nice and lean.
@ -120,18 +152,34 @@ class IOAttrs:
self.whole_days = whole_days self.whole_days = whole_days
if whole_hours != cls.whole_hours: if whole_hours != cls.whole_hours:
self.whole_hours = whole_hours self.whole_hours = whole_hours
if soft_default is not cls.soft_default:
# Do what dataclasses does with its default types and
# tell the user to use factory for mutable ones.
if isinstance(soft_default, (list, dict, set)):
raise ValueError(
f'mutable {type(soft_default)} is not allowed'
f' for soft_default; use soft_default_factory.')
self.soft_default = soft_default
if soft_default_factory is not cls.soft_default_factory:
self.soft_default_factory = soft_default_factory
def validate_for_field(self, cls: type, field: dataclasses.Field) -> None: def validate_for_field(self, cls: type, field: dataclasses.Field) -> None:
"""Ensure the IOAttrs instance is ok to use with the provided field.""" """Ensure the IOAttrs instance is ok to use with the provided field."""
# Turning off store_default requires the field to have either # Turning off store_default requires the field to have either
# a default_factory or a default # a default or a a default_factory or for us to have soft equivalents.
if not self.store_default: if not self.store_default:
default_factory: Any = field.default_factory field_default_factory: Any = field.default_factory
if (default_factory is dataclasses.MISSING if (field_default_factory is dataclasses.MISSING
and field.default is dataclasses.MISSING): and field.default is dataclasses.MISSING
and self.soft_default is self.MISSING
and self.soft_default_factory is self.MISSING):
raise TypeError(f'Field {field.name} of {cls} has' raise TypeError(f'Field {field.name} of {cls} has'
f' neither a default nor a default_factory;' f' neither a default nor a default_factory'
f' and IOAttrs contains neither a soft_default'
f' nor a soft_default_factory;'
f' store_default=False cannot be set for it.') f' store_default=False cannot be set for it.')
def validate_datetime(self, value: datetime.datetime, def validate_datetime(self, value: datetime.datetime,

View File

@ -158,6 +158,7 @@ class _Inputter(Generic[T]):
associated values, and nested dataclasses should be passed as dicts. associated values, and nested dataclasses should be passed as dicts.
""" """
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
# pylint: disable=too-many-branches
if not isinstance(values, dict): if not isinstance(values, dict):
raise TypeError( raise TypeError(
f'Expected a dict for {fieldpath} on {cls.__name__};' f'Expected a dict for {fieldpath} on {cls.__name__};'
@ -172,6 +173,16 @@ class _Inputter(Generic[T]):
# noinspection PyDataclass # noinspection PyDataclass
fields = dataclasses.fields(cls) fields = dataclasses.fields(cls)
fields_by_name = {f.name: f for f in fields} fields_by_name = {f.name: f for f in fields}
# Preprocess all fields to convert Annotated[] to contained types
# and IOAttrs.
parsed_field_annotations = {
f.name: _parse_annotated(prep.annotations[f.name])
for f in fields
}
# Go through all data in the input, converting it to either dataclass
# args or extra data.
args: dict[str, Any] = {} args: dict[str, Any] = {}
for rawkey, value in values.items(): for rawkey, value in values.items():
key = prep.storage_names_to_attr_names.get(rawkey, rawkey) key = prep.storage_names_to_attr_names.get(rawkey, rawkey)
@ -197,18 +208,32 @@ class _Inputter(Generic[T]):
f"'{cls.__name__}' has no '{key}' field.") f"'{cls.__name__}' has no '{key}' field.")
else: else:
fieldname = field.name fieldname = field.name
anntype = prep.annotations[fieldname] anntype, ioattrs = parsed_field_annotations[fieldname]
anntype, ioattrs = _parse_annotated(anntype)
subfieldpath = (f'{fieldpath}.{fieldname}' subfieldpath = (f'{fieldpath}.{fieldname}'
if fieldpath else fieldname) if fieldpath else fieldname)
args[key] = self._value_from_input(cls, subfieldpath, anntype, args[key] = self._value_from_input(cls, subfieldpath, anntype,
value, ioattrs) value, ioattrs)
# Go through all fields looking for any not yet present in our data.
# If we find any such fields with a soft-default value or factory
# defined, inject that value into our args.
for key, aparsed in parsed_field_annotations.items():
if key not in args:
ioattrs = aparsed[1]
if (ioattrs is not None and
(ioattrs.soft_default is not ioattrs.MISSING
or ioattrs.soft_default_factory is not ioattrs.MISSING)):
if ioattrs.soft_default is not ioattrs.MISSING:
args[key] = ioattrs.soft_default
else:
assert callable(ioattrs.soft_default_factory)
args[key] = ioattrs.soft_default_factory()
try: try:
out = cls(**args) out = cls(**args)
except Exception as exc: except Exception as exc:
raise RuntimeError(f'Error instantiating class {cls.__name__}' raise ValueError(f'Error instantiating class {cls.__name__}'
f' at {fieldpath}: {exc}') from exc f' at {fieldpath}: {exc}') from exc
if extra_attrs: if extra_attrs:
setattr(out, EXTRA_ATTRS_ATTR, extra_attrs) setattr(out, EXTRA_ATTRS_ATTR, extra_attrs)
return out return out

View File

@ -68,18 +68,25 @@ class _Outputter:
# we can skip all output processing if we've got a default value. # we can skip all output processing if we've got a default value.
if ioattrs is not None and not ioattrs.store_default: if ioattrs is not None and not ioattrs.store_default:
default_factory: Any = field.default_factory default_factory: Any = field.default_factory
if default_factory is not dataclasses.MISSING: if field.default is not dataclasses.MISSING:
if field.default == value:
continue
elif default_factory is not dataclasses.MISSING:
if default_factory() == value: if default_factory() == value:
continue continue
elif field.default is not dataclasses.MISSING: elif ioattrs.soft_default is not ioattrs.MISSING:
if field.default == value: if ioattrs.soft_default == value:
continue
elif ioattrs.soft_default_factory is not ioattrs.MISSING:
assert callable(ioattrs.soft_default_factory)
if ioattrs.soft_default_factory() == value:
continue continue
else: else:
raise RuntimeError( raise RuntimeError(
f'Field {fieldname} of {cls.__name__} has' f'Field {fieldname} of {cls.__name__} has'
f' neither a default nor a default_factory;' f' no source of default values; store_default=False'
f' store_default=False cannot be set for it.' f' cannot be set for it. (AND THIS SHOULD HAVE BEEN'
f' (AND THIS SHOULD HAVE BEEN CAUGHT IN PREP!)') f' CAUGHT IN PREP!)')
outvalue = self._process_value(cls, subfieldpath, anntype, value, outvalue = self._process_value(cls, subfieldpath, anntype, value,
ioattrs) ioattrs)

View File

@ -316,10 +316,6 @@ class RPCEndpoint:
self._debug_print_call( self._debug_print_call(
f'{self._label}: tasks finished; waiting for writer close...') f'{self._label}: tasks finished; waiting for writer close...')
# At this point we shouldn't touch our tasks anymore.
# Clearing them out allows us to go down
# del self._tasks
# Now wait for our writer to finish going down. # Now wait for our writer to finish going down.
# When we close our writer it generally triggers errors # When we close our writer it generally triggers errors
# in our current blocked read/writes. However that same # in our current blocked read/writes. However that same
@ -328,7 +324,18 @@ class RPCEndpoint:
# So let's silently ignore it when that happens. # So let's silently ignore it when that happens.
assert self._writer.is_closing() assert self._writer.is_closing()
try: try:
await self._writer.wait_closed() # It seems that as of Python 3.9.x it is possible for this to hang
# indefinitely. See https://github.com/python/cpython/issues/83939
# It sounds like this should be fixed in 3.11 but for now just
# forcing the issue with a timeout here.
await asyncio.wait_for(self._writer.wait_closed(), timeout=10.0)
except asyncio.TimeoutError:
logging.info('Timeout on _writer.wait_closed() for %s.',
self._label)
if self._debug_print:
self._debug_print_call(
f'{self._label}: got timeout in _writer.wait_closed();'
' This should be fixed in future Python versions.')
except Exception as exc: except Exception as exc:
if not self._is_expected_connection_error(exc): if not self._is_expected_connection_error(exc):
logging.exception('Error closing _writer for %s.', self._label) logging.exception('Error closing _writer for %s.', self._label)