diff --git a/python/vegafusion-jupyter/conda-win-64-cp310.lock b/python/vegafusion-jupyter/conda-win-64-cp310.lock index a33b2ec7b..18eb4f841 100644 --- a/python/vegafusion-jupyter/conda-win-64-cp310.lock +++ b/python/vegafusion-jupyter/conda-win-64-cp310.lock @@ -1,12 +1,12 @@ # Generated by conda-lock. # platform: win-64 -# input_hash: 1dc33e11a55c85392a21bf6d56c3fc4803e0c66a5c9aea72c0f582bc1bb7c9c3 +# input_hash: 32fabb56021a7b0a6e2f2322cc88d9fee399e2238a8dbc3f6078a1aa4b627947 @EXPLICIT https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2021.10.8-h5b45459_0.tar.bz2#2ddd48c9b52f7f65361b9645b2c5d370 https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2022.0.0-h57928b3_3663.tar.bz2#9617f0042f5eea1155970e6861f3ab6b https://conda.anaconda.org/conda-forge/win-64/msys2-conda-epoch-20160418-1.tar.bz2#b0309b72560df66f71a9d5e34a5efdfa -https://conda.anaconda.org/conda-forge/win-64/nodejs-17.1.0-h57928b3_2.tar.bz2#0fd78a8cb239257a30ab38b94840bc0d -https://conda.anaconda.org/conda-forge/win-64/pandoc-2.17-h8ffe710_0.tar.bz2#f2cea2040268a53502f647b04d87c182 +https://conda.anaconda.org/conda-forge/win-64/nodejs-17.4.0-h57928b3_0.tar.bz2#88f3519bd8fbf93ea05e72ceaaf391db +https://conda.anaconda.org/conda-forge/win-64/pandoc-2.17.1.1-h57928b3_0.tar.bz2#75ecf3cc83aad34874efde6f93d48c67 https://conda.anaconda.org/conda-forge/noarch/tzdata-2021e-he74cb21_0.tar.bz2#a751ec502589ebdc2eceb183ff602569 https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.20348.0-h57928b3_0.tar.bz2#6d666b6ea8251231ff508062d1e41f9c https://conda.anaconda.org/conda-forge/win-64/winpty-0.4.3-4.tar.bz2#1cee351bf20b830d991dbe0bc8cd7dfe @@ -18,18 +18,19 @@ https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz https://conda.anaconda.org/conda-forge/win-64/vc-14.2-hb210afc_6.tar.bz2#c2aecbc9b00ba6f352e27d3d61fd31fb https://conda.anaconda.org/conda-forge/win-64/blosc-1.21.0-h0e60522_0.tar.bz2#19b82b554c46598cc5cc01a58f30f547 https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h8ffe710_4.tar.bz2#7c03c66026944073040cb19a4f3ec3c9 -https://conda.anaconda.org/conda-forge/win-64/charls-2.2.0-h39d44d4_0.tar.bz2#7b4af3de4c91113430f2cafec2221764 +https://conda.anaconda.org/conda-forge/win-64/charls-2.3.4-h39d44d4_0.tar.bz2#bfbea80de69a6ceed0a717f63a91d326 +https://conda.anaconda.org/conda-forge/win-64/fribidi-1.0.10-h8d14728_0.tar.bz2#807e81d915f2bb2e49951648615241f6 https://conda.anaconda.org/conda-forge/win-64/giflib-5.2.1-h8d14728_2.tar.bz2#c577cd3be126d95e9a05ee5aa9d2875b https://conda.anaconda.org/conda-forge/win-64/jbig-2.1-h8d14728_2003.tar.bz2#37dcc26d63c315f6c0588579dca810da -https://conda.anaconda.org/conda-forge/win-64/jpeg-9d-h8ffe710_0.tar.bz2#9335a1b24eefef6075f4c02a03baf27a +https://conda.anaconda.org/conda-forge/win-64/jpeg-9e-h8ffe710_0.tar.bz2#83e0284f1306a3381a825d7a728aacc2 https://conda.anaconda.org/conda-forge/win-64/jxrlib-1.1-h8ffe710_2.tar.bz2#69f82948e102dc14928619140c29468d https://conda.anaconda.org/conda-forge/win-64/lerc-3.0-h0e60522_0.tar.bz2#756c8b51a32758df2ed6cddcc7b7ed58 https://conda.anaconda.org/conda-forge/win-64/libaec-1.0.6-h39d44d4_0.tar.bz2#ac78b243f1ee03a2412b6e328aa3a12d https://conda.anaconda.org/conda-forge/win-64/libbrotlicommon-1.0.9-h8ffe710_6.tar.bz2#e1611959ec9329ad406b2f5c84b8757f -https://conda.anaconda.org/conda-forge/win-64/libdeflate-1.8-h8ffe710_0.tar.bz2#8d90ca64db6b511cd5d3ab8b675f4c20 +https://conda.anaconda.org/conda-forge/win-64/libdeflate-1.10-h8ffe710_0.tar.bz2#ad4246997621fdf913fe6f958bc16fd4 https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2#2c96d1b6915b408893f9472569dee135 https://conda.anaconda.org/conda-forge/win-64/libsodium-1.0.18-h8d14728_1.tar.bz2#5c1fb45b5e2912c19098750ae8a32604 -https://conda.anaconda.org/conda-forge/win-64/libwebp-base-1.2.1-h8ffe710_0.tar.bz2#3bd686e19cc9722e674e2f8119bc476d +https://conda.anaconda.org/conda-forge/win-64/libwebp-base-1.2.2-h8ffe710_1.tar.bz2#24e23990217d3542fb821759a41d6ec2 https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.11-h8ffe710_1013.tar.bz2#b28dd2488b4e5f892c67071acc1d0a8c https://conda.anaconda.org/conda-forge/win-64/libzopfli-1.0.3-h0e60522_0.tar.bz2#b4b0cbc0abc9f26b730231ffdabf3881 https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.9.3-h8ffe710_1.tar.bz2#d12763533276560a931c1bd3df1adf63 @@ -38,19 +39,20 @@ https://conda.anaconda.org/conda-forge/win-64/openssl-1.1.1l-h8ffe710_0.tar.bz2# https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.8-ha925a31_3.tar.bz2#e227e973dec9f437b28b24f9f0e5f7fe https://conda.anaconda.org/conda-forge/win-64/sqlite-3.37.0-h8ffe710_0.tar.bz2#cc2d704449f994c1aa422a5a1cd8a64e https://conda.anaconda.org/conda-forge/win-64/tbb-2021.5.0-h2d74725_0.tar.bz2#81892af9e08d8bf7a98e9713189d6885 -https://conda.anaconda.org/conda-forge/win-64/tk-8.6.11-h8ffe710_1.tar.bz2#fd3c141a1ed5a77e5813795950fb7395 +https://conda.anaconda.org/conda-forge/win-64/tk-8.6.12-h8ffe710_0.tar.bz2#c69a5047cc9291ae40afd4a1ad6f0c0f https://conda.anaconda.org/conda-forge/win-64/xz-5.2.5-h62dcd97_1.tar.bz2#eabcbfedd14d7c18a514afca09ea0ebb https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h8ffe710_2.tar.bz2#adbfb9f45d1004a26763652246a33764 https://conda.anaconda.org/conda-forge/win-64/zfp-0.5.5-h0e60522_8.tar.bz2#01afc300e6617dbaad37fe834af41b11 https://conda.anaconda.org/conda-forge/win-64/krb5-1.19.2-h20d022d_3.tar.bz2#8a773a26af200fd95350e0866c02e2b3 https://conda.anaconda.org/conda-forge/win-64/libbrotlidec-1.0.9-h8ffe710_6.tar.bz2#147294ddd621c7a5288af3393c711760 https://conda.anaconda.org/conda-forge/win-64/libbrotlienc-1.0.9-h8ffe710_6.tar.bz2#a9d521d66b91eea8c265931032ac948e +https://conda.anaconda.org/conda-forge/win-64/libwebp-1.2.2-h57928b3_0.tar.bz2#80c0ce63cf8f69c5a5781ab7a9645942 https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-5.3.0-7.tar.bz2#fe759119b8b3bfa720b8762c6fdc35de -https://conda.anaconda.org/conda-forge/win-64/mkl-2021.4.0-h0e2418a_729.tar.bz2#42fcb45077a716cb8d967117b8b88f28 -https://conda.anaconda.org/conda-forge/win-64/python-3.10.2-h9a09f29_0_cpython.tar.bz2#a71076b607b8d8828d0a64f533022f83 +https://conda.anaconda.org/conda-forge/win-64/mkl-2022.0.0-h0e2418a_796.tar.bz2#54baa34953c02445bfd6f566c45decbb +https://conda.anaconda.org/conda-forge/win-64/python-3.10.2-h9a09f29_3_cpython.tar.bz2#81ec8e7d9481cd2963c302b7bb565d87 https://conda.anaconda.org/conda-forge/win-64/zeromq-4.3.4-h0e60522_1.tar.bz2#e1aff0583dda5fb917eb3d2c1025aa80 https://conda.anaconda.org/conda-forge/win-64/zlib-1.2.11-h8ffe710_1013.tar.bz2#866517df4fd8bb813bc20c24cf7b8f05 -https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.1-h6255e5f_0.tar.bz2#cf642c6d2533de5340d314027d5fba0d +https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.2-h6255e5f_0.tar.bz2#68de506283d23d66cf1e4ce3814d6cdc https://conda.anaconda.org/conda-forge/noarch/appdirs-1.4.4-pyh9f0ad1d_0.tar.bz2#5f095bc6454094e96f146491fd03633b https://conda.anaconda.org/conda-forge/noarch/async_generator-1.10-py_0.tar.bz2#d56c596e61b1c4952acf0a9920856c12 https://conda.anaconda.org/conda-forge/noarch/atomicwrites-1.4.0-pyh9f0ad1d_0.tar.bz2#5e36230ffaf3b7bb599424592684ae53 @@ -59,37 +61,42 @@ https://conda.anaconda.org/conda-forge/noarch/backcall-0.2.0-pyh9f0ad1d_0.tar.bz https://conda.anaconda.org/conda-forge/noarch/backports-1.0-py_2.tar.bz2#0da16b293affa6ac31812376f8eb79dd https://conda.anaconda.org/conda-forge/win-64/brotli-bin-1.0.9-h8ffe710_6.tar.bz2#94163a6bf564144f1b163535624ca4fc https://conda.anaconda.org/conda-forge/win-64/c-blosc2-2.0.4-h09319c2_1.tar.bz2#70ae80e8d7cd5382b1ae6ef63248c9d3 -https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-2.0.10-pyhd8ed1ab_0.tar.bz2#ea77236c8031cfa821720b21b4cb0ceb +https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-2.0.12-pyhd8ed1ab_0.tar.bz2#1f5b32dabae0f1893ae3283dac7f799e https://conda.anaconda.org/conda-forge/noarch/cloudpickle-2.0.0-pyhd8ed1ab_0.tar.bz2#3a8fc8b627d5fb6af827e126a10a86c6 https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.4-pyh9f0ad1d_0.tar.bz2#c08b4c1326b880ed44f3ffb04803332f https://conda.anaconda.org/conda-forge/noarch/cycler-0.11.0-pyhd8ed1ab_0.tar.bz2#a50559fad0affdbb33729a68669ca1cb +https://conda.anaconda.org/conda-forge/noarch/dataclasses-0.8-pyhc8e2a94_3.tar.bz2#a362b2124b06aad102e2ee4581acee7d https://conda.anaconda.org/conda-forge/noarch/decorator-5.1.1-pyhd8ed1ab_0.tar.bz2#43afe5ab04e35e17ba28649471dd7364 https://conda.anaconda.org/conda-forge/noarch/defusedxml-0.7.1-pyhd8ed1ab_0.tar.bz2#961b3a227b437d82ad7054484cfa71b2 -https://conda.anaconda.org/conda-forge/noarch/entrypoints-0.3-pyhd8ed1ab_1003.tar.bz2#bbf9a201f6ce99a506f4955374d9a9f4 -https://conda.anaconda.org/conda-forge/noarch/filelock-3.4.2-pyhd8ed1ab_1.tar.bz2#d3f5797d3f9625c64860c93fc4359e64 +https://conda.anaconda.org/conda-forge/noarch/entrypoints-0.4-pyhd8ed1ab_0.tar.bz2#3cf04868fee0a029769bd41f4b2fbf2d +https://conda.anaconda.org/conda-forge/noarch/executing-0.8.2-pyhd8ed1ab_0.tar.bz2#dcd884e2cf5bcdccdf78f7db35999d62 +https://conda.anaconda.org/conda-forge/noarch/filelock-3.5.1-pyhd8ed1ab_0.tar.bz2#e2587087f4809c3fb6dc4c29648ecfc8 https://conda.anaconda.org/conda-forge/noarch/flaky-3.7.0-pyh9f0ad1d_0.tar.bz2#d20be9ed08052d16593c88d51b774a82 https://conda.anaconda.org/conda-forge/noarch/flit-core-3.6.0-pyhd8ed1ab_0.tar.bz2#f8c17f22a3ce533876c468157ff8ff8f https://conda.anaconda.org/conda-forge/noarch/fsspec-2022.1.0-pyhd8ed1ab_0.tar.bz2#188e095f4dc38887bb48b065734b9e8d https://conda.anaconda.org/conda-forge/noarch/h11-0.12.0-pyhd8ed1ab_0.tar.bz2#a8c3c313e5339029946b66070cf24b39 -https://conda.anaconda.org/conda-forge/noarch/idna-3.1-pyhd3deb0d_0.tar.bz2#9c9aea4b8391264477df484f798562d0 +https://conda.anaconda.org/conda-forge/noarch/idna-3.3-pyhd8ed1ab_0.tar.bz2#40b50b8b030f5f2f22085c062ed013dd https://conda.anaconda.org/conda-forge/noarch/iniconfig-1.1.1-pyh9f0ad1d_0.tar.bz2#39161f81cc5e5ca45b8226fbb06c6905 https://conda.anaconda.org/conda-forge/noarch/ipython_genutils-0.2.0-py_1.tar.bz2#5071c982548b3a20caf70462f04f5287 https://conda.anaconda.org/conda-forge/noarch/json5-0.9.5-pyh9f0ad1d_0.tar.bz2#10759827a94e6b14996e81fb002c0bda -https://conda.anaconda.org/conda-forge/win-64/libblas-3.9.0-12_win64_mkl.tar.bz2#96b3e24fd626a2a964c81045da31c7b1 +https://conda.anaconda.org/conda-forge/win-64/libblas-3.9.0-13_win64_mkl.tar.bz2#5addc4aa3bae7e89ce6eb8720650b257 https://conda.anaconda.org/conda-forge/win-64/libpng-1.6.37-h1d00b33_2.tar.bz2#005ddb14b8f876ed6a85b76dfc9892db https://conda.anaconda.org/conda-forge/win-64/libssh2-1.10.0-h680486a_2.tar.bz2#7c3dab9db46226852f9c4c163870e4e4 -https://conda.anaconda.org/conda-forge/win-64/libtiff-4.3.0-hd413186_2.tar.bz2#40718c1376954db41607d76ebb81e1b3 +https://conda.anaconda.org/conda-forge/win-64/libtiff-4.3.0-hc4061b1_3.tar.bz2#2e9f4af7dd16047f2f370562fb9e81fc https://conda.anaconda.org/conda-forge/noarch/locket-0.2.0-py_2.tar.bz2#709e8671651c7ec3d1ad07800339ff1d https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyh9f0ad1d_0.tar.bz2#2ba8498c1018c1e9c61eb99b973dfe19 https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.5.4-pyhd8ed1ab_0.tar.bz2#0d86e4e6ac78912f3f47e0453b124aca -https://conda.anaconda.org/conda-forge/noarch/olefile-0.46-pyh9f0ad1d_1.tar.bz2#0b2e68acc8c78c8cc392b90983481f58 https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2#457c2c8c08e54905d6954e79cb5b5db9 https://conda.anaconda.org/conda-forge/noarch/parso-0.8.3-pyhd8ed1ab_0.tar.bz2#17a565a0c3899244e938cdf417e7b094 +https://conda.anaconda.org/conda-forge/noarch/pathspec-0.9.0-pyhd8ed1ab_0.tar.bz2#f93dc0ccbc0a8472624165f6e256c7d1 https://conda.anaconda.org/conda-forge/noarch/pickleshare-0.7.5-py_1003.tar.bz2#415f0ebb6198cc2801c73438a9fb5761 -https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.12.0-pyhd8ed1ab_0.tar.bz2#d7b366cccdf2c1e8ebdddbfff7c2ba00 +https://conda.anaconda.org/conda-forge/noarch/platformdirs-2.5.0-pyhd8ed1ab_0.tar.bz2#7fe854bc6252760836b0f0ab6ced04ce +https://conda.anaconda.org/conda-forge/noarch/prometheus_client-0.13.1-pyhd8ed1ab_0.tar.bz2#9259acd5dd8746e7721474fa62e046d7 +https://conda.anaconda.org/conda-forge/win-64/pthread-stubs-0.4-hcd874cb_1001.tar.bz2#a1f820480193ea83582b13249a7e7bd9 +https://conda.anaconda.org/conda-forge/noarch/pure_eval-0.2.2-pyhd8ed1ab_0.tar.bz2#6784285c7e55cb7212efabc79e4c2883 https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2#b4613d7e7a493916d867842a6a148054 https://conda.anaconda.org/conda-forge/noarch/pycparser-2.21-pyhd8ed1ab_0.tar.bz2#076becd9e05608f8dc72757d5f3a91ff -https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.0.6-pyhd8ed1ab_0.tar.bz2#3087df8c636c5a00e694605c39ce4982 +https://conda.anaconda.org/conda-forge/noarch/pyparsing-3.0.7-pyhd8ed1ab_0.tar.bz2#727e2216d9c47455d8ddc060eb2caad9 https://conda.anaconda.org/conda-forge/win-64/python_abi-3.10-2_cp310.tar.bz2#aaa900b98edb2e67106b461ff365ba57 https://conda.anaconda.org/conda-forge/noarch/pytz-2021.3-pyhd8ed1ab_0.tar.bz2#7e4f811bff46a5a6a7e0094921389395 https://conda.anaconda.org/conda-forge/noarch/send2trash-1.8.0-pyhd8ed1ab_0.tar.bz2#edab14119efe85c3bf131ad747e9005c @@ -98,115 +105,124 @@ https://conda.anaconda.org/conda-forge/noarch/sortedcontainers-2.4.0-pyhd8ed1ab_ https://conda.anaconda.org/conda-forge/noarch/tenacity-8.0.1-pyhd8ed1ab_0.tar.bz2#8b29b2c12cb21dbd057755e5fd22d005 https://conda.anaconda.org/conda-forge/noarch/testpath-0.5.0-pyhd8ed1ab_0.tar.bz2#53b57d6a468bebc7cef1253b177a5e9e https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2#f832c45a477c78bebd107098db465095 -https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.0-pyhd8ed1ab_1.tar.bz2#9b49de2db8b4a4a48c424629694fbd37 +https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2#5844808ffab9ebdb694585b50ba02a96 https://conda.anaconda.org/conda-forge/noarch/toolz-0.11.2-pyhd8ed1ab_0.tar.bz2#f348d1590550371edfac5ed3c1d44f7e https://conda.anaconda.org/conda-forge/noarch/traitlets-5.1.1-pyhd8ed1ab_0.tar.bz2#a1bc9765ef9499760e88f568b3a6622c https://conda.anaconda.org/conda-forge/noarch/typing-3.10.0.0-pyhd8ed1ab_0.tar.bz2#e6573ac68718f17b9d4f5c8eda3190f2 -https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.0.1-pyha770c72_0.tar.bz2#1fc03816925d3cb7fdab9ab234e7fea7 +https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.1.1-pyha770c72_0.tar.bz2#74761ba7bc682e9009520163a1031ace https://conda.anaconda.org/conda-forge/noarch/webencodings-0.5.1-py_1.tar.bz2#3563be4c5611a44210d9ba0c16113136 https://conda.anaconda.org/conda-forge/noarch/websocket-client-1.2.3-pyhd8ed1ab_0.tar.bz2#a9e89668df0da0f33c8c4ddf7c118f6d https://conda.anaconda.org/conda-forge/noarch/wheel-0.37.1-pyhd8ed1ab_0.tar.bz2#1ca02aaf78d9c70d9a81a3bed5752022 -https://conda.anaconda.org/conda-forge/noarch/zipp-3.7.0-pyhd8ed1ab_0.tar.bz2#947f7f41958eabc0f6e886557512bb76 +https://conda.anaconda.org/conda-forge/win-64/xorg-libxau-1.0.9-hcd874cb_0.tar.bz2#9cef622e75683c17d05ae62d66e69e6c +https://conda.anaconda.org/conda-forge/win-64/xorg-libxdmcp-1.1.3-hcd874cb_0.tar.bz2#46878ebb6b9cbd8afcf8088d7ef00ece +https://conda.anaconda.org/conda-forge/noarch/zipp-3.7.0-pyhd8ed1ab_1.tar.bz2#b689b2cbc8481b224777415e1a193170 +https://conda.anaconda.org/conda-forge/noarch/asttokens-2.0.5-pyhd8ed1ab_0.tar.bz2#74badce16f060701fee55c39332f5253 https://conda.anaconda.org/conda-forge/noarch/babel-2.9.1-pyh44b312d_0.tar.bz2#74136ed39bfea0832d338df1e58d013e https://conda.anaconda.org/conda-forge/win-64/brotli-1.0.9-h8ffe710_6.tar.bz2#d92e55db1cc5e34d1ba0812366c29826 https://conda.anaconda.org/conda-forge/win-64/certifi-2021.10.8-py310h5588dad_1.tar.bz2#d54dc314d865498a7349f4ebe35448a6 https://conda.anaconda.org/conda-forge/win-64/cffi-1.15.0-py310hcbf9ad4_0.tar.bz2#ffea8be6c3b061eb7361a8686af44861 https://conda.anaconda.org/conda-forge/win-64/click-8.0.3-py310h5588dad_1.tar.bz2#e8411019db120f883547b546dc3503a3 -https://conda.anaconda.org/conda-forge/win-64/coverage-6.2-py310he2412df_0.tar.bz2#8133d9e7a63ace0be562f04181ae0890 +https://conda.anaconda.org/conda-forge/win-64/coverage-6.3.1-py310he2412df_0.tar.bz2#81e085bdc5a38a5be11f23e2909646bd https://conda.anaconda.org/conda-forge/win-64/cytoolz-0.11.2-py310he2412df_1.tar.bz2#b1f0199fd7a7610c214d19343bb095f6 https://conda.anaconda.org/conda-forge/win-64/debugpy-1.5.1-py310h8a704f9_0.tar.bz2#5882f83cd4d4213bdea77fb4219a32b2 https://conda.anaconda.org/conda-forge/win-64/freetype-2.10.4-h546665d_1.tar.bz2#1215a2e49d23da91c28d97cff8de35ea -https://conda.anaconda.org/conda-forge/win-64/importlib-metadata-4.10.0-py310h5588dad_0.tar.bz2#01b21d7c88a60c78879144c1c7de78a3 +https://conda.anaconda.org/conda-forge/win-64/importlib-metadata-4.11.1-py310h5588dad_0.tar.bz2#9b44cfcdd177ccc9d9c320ed6b5b839d https://conda.anaconda.org/conda-forge/noarch/importlib_resources-5.4.0-pyhd8ed1ab_0.tar.bz2#9fb134dbabe7851a9d71411064b2c30d https://conda.anaconda.org/conda-forge/win-64/jedi-0.18.1-py310h5588dad_0.tar.bz2#f61b25ec030168c94b25cf20153cef3b https://conda.anaconda.org/conda-forge/win-64/kiwisolver-1.3.2-py310h476a331_1.tar.bz2#298c6a53b7685e97ef663a85a3148894 https://conda.anaconda.org/conda-forge/win-64/lcms2-2.12-h2a16943_0.tar.bz2#fee639c27301c4165b4d1f7e442de8a5 -https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-12_win64_mkl.tar.bz2#5103ff857d4086ae01f2df8757f31d0b +https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-13_win64_mkl.tar.bz2#0facf207b485dc20c4ef5f8b92c7c949 https://conda.anaconda.org/conda-forge/win-64/libcurl-7.81.0-h789b8ee_0.tar.bz2#c5ac1ff403590d7b4472d5e89adfbd32 -https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-12_win64_mkl.tar.bz2#e2971c6292cb0daf16bced80b9aa767a +https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-13_win64_mkl.tar.bz2#4a777de294375e4d78ad53e5581a9ede +https://conda.anaconda.org/conda-forge/win-64/libxcb-1.13-hcd874cb_1004.tar.bz2#a6d7fd030532378ecb6ba435cd9f8234 https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-1.1.0-pyhd8ed1ab_0.tar.bz2#84e8dfb1a9e6a824f32fd45b867271ca https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.0.1-py310he2412df_1.tar.bz2#b4da490d6d77767dd98e58d0dd3858e0 https://conda.anaconda.org/conda-forge/noarch/matplotlib-inline-0.1.3-pyhd8ed1ab_0.tar.bz2#be3bfd435802d2c768c6b2439f325f3d -https://conda.anaconda.org/conda-forge/win-64/maturin-0.12.6-py310hdc45392_0.tar.bz2#7450d594d7c13d1aa3de080f13f72a78 +https://conda.anaconda.org/conda-forge/win-64/maturin-0.12.8-py310hdc45392_0.tar.bz2#8ab039d48eb1d5ed330b6cb74548fcbd https://conda.anaconda.org/conda-forge/win-64/mistune-0.8.4-py310he2412df_1005.tar.bz2#b845e34a59732681cdd63f5c5d3456b4 +https://conda.anaconda.org/conda-forge/win-64/mypy_extensions-0.4.3-py310h5588dad_4.tar.bz2#52c10573dce166bb8a8318956dc6e1c4 https://conda.anaconda.org/conda-forge/win-64/openjpeg-2.4.0-hb211442_1.tar.bz2#0991d2e943e5ba7ec9b7b32eec14e2e3 https://conda.anaconda.org/conda-forge/noarch/outcome-1.1.0-pyhd8ed1ab_0.tar.bz2#a6baaddfb9fb5aa6b53534b634cb69c9 https://conda.anaconda.org/conda-forge/noarch/packaging-21.3-pyhd8ed1ab_0.tar.bz2#71f1ab2de48613876becddd496371c85 https://conda.anaconda.org/conda-forge/noarch/partd-1.2.0-pyhd8ed1ab_0.tar.bz2#0c32f563d7f22e3a34c95cad8cc95651 https://conda.anaconda.org/conda-forge/win-64/pluggy-1.0.0-py310h5588dad_2.tar.bz2#450125d98e2118237d0154922b7629da -https://conda.anaconda.org/conda-forge/win-64/pyrsistent-0.18.0-py310he2412df_0.tar.bz2#2f03eda695d46de8bcd06040a3c581d5 +https://conda.anaconda.org/conda-forge/win-64/pyrsistent-0.18.1-py310he2412df_0.tar.bz2#8d9847ea613b97a7d32cb77a3c8f100d https://conda.anaconda.org/conda-forge/noarch/python-dateutil-2.8.2-pyhd8ed1ab_0.tar.bz2#dd999d1cc9f79e67dbb855c8924c7984 https://conda.anaconda.org/conda-forge/win-64/pywin32-303-py310he2412df_0.tar.bz2#e034f495e69b266fc082c92f75398f22 -https://conda.anaconda.org/conda-forge/win-64/pywinpty-1.1.6-py310h00ffb61_0.tar.bz2#30c0f295449652ac5da226bb09c0713c +https://conda.anaconda.org/conda-forge/win-64/pywinpty-2.0.2-py310h00ffb61_0.tar.bz2#1f92491627fb709352994d13c247cb02 https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0-py310he2412df_3.tar.bz2#e9d0119d704abafde3ed6a0df854fc92 https://conda.anaconda.org/conda-forge/win-64/pyzmq-22.3.0-py310h73ada01_1.tar.bz2#43b030d14cfe99e90d1818e8121da170 -https://conda.anaconda.org/conda-forge/win-64/setuptools-59.8.0-py310h5588dad_0.tar.bz2#4c109fde68a2cf21af07c14bfc70538c +https://conda.anaconda.org/conda-forge/win-64/setuptools-60.9.2-py310h5588dad_0.tar.bz2#996ca846538740a34dbb5481a06c3d16 https://conda.anaconda.org/conda-forge/win-64/sniffio-1.2.0-py310h5588dad_2.tar.bz2#b2660bc27428af5519ac2b6df9d2cb05 -https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.8.0-pyha770c72_0.tar.bz2#3a38c81fc51f9d709e06719b7376e5f9 +https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.9.2-pyha770c72_0.tar.bz2#465606af3f79bb3d5b4654f4d02c7417 https://conda.anaconda.org/conda-forge/win-64/tornado-6.1-py310he2412df_2.tar.bz2#2e647cb68c37732867dee12dab2d36e2 -https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.0.1-hd8ed1ab_0.tar.bz2#c0d4ec4bcbceb927bff1103a997410d3 +https://conda.anaconda.org/conda-forge/win-64/typed-ast-1.5.2-py310he2412df_0.tar.bz2#a95a934729dd208d6d66ca5a320ed4d1 +https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.1.1-hd8ed1ab_0.tar.bz2#9d1b5bbaa13bca480c80893a87a52c4f +https://conda.anaconda.org/conda-forge/win-64/unicodedata2-14.0.0-py310he2412df_0.tar.bz2#43bc9f3f429a272a7368d40d98763330 https://conda.anaconda.org/conda-forge/win-64/websockets-10.1-py310he2412df_0.tar.bz2#56b8c1fa4abf27adf85754f01545a55f https://conda.anaconda.org/conda-forge/win-64/win_inet_pton-1.1.0-py310h5588dad_3.tar.bz2#076952825d5d17d31200c148f03ebe2b https://conda.anaconda.org/conda-forge/win-64/wsproto-1.0.0-py310h5588dad_2.tar.bz2#bf87b3ffd2f11e98aa6ffca18a9f8ef7 https://conda.anaconda.org/conda-forge/win-64/anyio-3.5.0-py310h5588dad_0.tar.bz2#d86b34b166a34530673809dc9a738303 https://conda.anaconda.org/conda-forge/win-64/argon2-cffi-bindings-21.2.0-py310he2412df_1.tar.bz2#65980510504e1aeb127decee2217fa77 https://conda.anaconda.org/conda-forge/noarch/backports.functools_lru_cache-1.6.4-pyhd8ed1ab_0.tar.bz2#c5b3edc62d6309088f4970b3eaaa65a6 +https://conda.anaconda.org/conda-forge/noarch/black-22.1.0-pyhd8ed1ab_0.tar.bz2#fbc4b306c6ba24c244ffb22a910424da https://conda.anaconda.org/conda-forge/noarch/bleach-4.1.0-pyhd8ed1ab_0.tar.bz2#4a2104c7b22c222bd0fe03aaef12862c https://conda.anaconda.org/conda-forge/win-64/brotlipy-0.7.0-py310he2412df_1003.tar.bz2#87576e9f785509ab8c09f2b87c7035ab https://conda.anaconda.org/conda-forge/win-64/cfitsio-4.0.0-hd67004f_0.tar.bz2#637c0b5964878c8f438750a8d8c1bf7c https://conda.anaconda.org/conda-forge/noarch/click-default-group-1.2.2-pyhd8ed1ab_1.tar.bz2#72a46ffc25701c173932fd55cf0965d3 https://conda.anaconda.org/conda-forge/win-64/cryptography-36.0.1-py310ha857299_0.tar.bz2#98b944590e40d3252242b4c3f853f784 -https://conda.anaconda.org/conda-forge/noarch/dask-core-2022.1.0-pyhd8ed1ab_0.tar.bz2#e7d934ff2c617f0bfc62ab77c160f093 +https://conda.anaconda.org/conda-forge/noarch/dask-core-2022.2.0-pyhd8ed1ab_0.tar.bz2#d8410c1ab31b3f5196e0cff0125779c1 https://conda.anaconda.org/conda-forge/noarch/deprecation-2.1.0-pyh9f0ad1d_0.tar.bz2#7b6747d7cc2076341029cff659669e8b -https://conda.anaconda.org/conda-forge/win-64/fonttools-4.28.5-py310he2412df_0.tar.bz2#e8da4e483d92b54769a34b36dc94573c +https://conda.anaconda.org/conda-forge/win-64/fonttools-4.29.1-py310he2412df_0.tar.bz2#305cff3af19f7710275fda6719b9a89d https://conda.anaconda.org/conda-forge/noarch/jinja2-3.0.3-pyhd8ed1ab_0.tar.bz2#036d872c653780cb26e797e2e2f61b4c https://conda.anaconda.org/conda-forge/noarch/jsonschema-4.4.0-pyhd8ed1ab_0.tar.bz2#17ec41acce882e5db4efdcc4c01ca7e0 -https://conda.anaconda.org/conda-forge/win-64/jupyter_core-4.9.1-py310h5588dad_1.tar.bz2#350238bf565fe82efb4b5f401efcc2ed +https://conda.anaconda.org/conda-forge/win-64/jupyter_core-4.9.2-py310h5588dad_0.tar.bz2#cfaab1787333d1d4bd12770562e36c7b https://conda.anaconda.org/conda-forge/noarch/mdit-py-plugins-0.3.0-pyhd8ed1ab_0.tar.bz2#adf9129f76ca651869acf2219fac2050 -https://conda.anaconda.org/conda-forge/win-64/numpy-1.22.0-py310hcae7c84_0.tar.bz2#a6bac75208a83474372f9167c735a9f2 -https://conda.anaconda.org/conda-forge/win-64/pillow-8.4.0-py310h22f3323_0.tar.bz2#cf0cd830f6846cbdda770a67766adc37 -https://conda.anaconda.org/conda-forge/noarch/pip-21.3.1-pyhd8ed1ab_0.tar.bz2#e4fe2a9af78ff11f1aced7e62128c6a8 +https://conda.anaconda.org/conda-forge/win-64/numpy-1.22.2-py310hcae7c84_0.tar.bz2#a59065c55cab7fd8f65a380f49da597f +https://conda.anaconda.org/conda-forge/win-64/pillow-9.0.1-py310h767b3fd_1.tar.bz2#b5392084d31948d54853d5de8959abfd +https://conda.anaconda.org/conda-forge/noarch/pip-22.0.3-pyhd8ed1ab_0.tar.bz2#45dedae69a0ea21cb8566d04b2ca5536 https://conda.anaconda.org/conda-forge/win-64/pydantic-1.9.0-py310he2412df_0.tar.bz2#89b3da947b5f35bb334e933d87090334 https://conda.anaconda.org/conda-forge/noarch/pygments-2.11.2-pyhd8ed1ab_0.tar.bz2#caef60540e2239e27bf62569a5015e3b https://conda.anaconda.org/conda-forge/win-64/pysocks-1.7.1-py310h5588dad_4.tar.bz2#1a6a04ff640bddc94b0db9294ea5de01 -https://conda.anaconda.org/conda-forge/win-64/pytest-6.2.5-py310h5588dad_2.tar.bz2#23084d3d1f1fe3711e34e962b0060a6b -https://conda.anaconda.org/conda-forge/win-64/python-chromedriver-binary-96.0.4664.45.0-py310h5588dad_0.tar.bz2#ec50daa932d64a5ef67c77d32617939c -https://conda.anaconda.org/conda-forge/win-64/terminado-0.12.1-py310h5588dad_1.tar.bz2#63d16b9859fdea18195b04b1a642fb55 +https://conda.anaconda.org/conda-forge/win-64/pytest-7.0.1-py310h5588dad_0.tar.bz2#74b98fe688cf23a8db11de7225c71afa +https://conda.anaconda.org/conda-forge/win-64/python-chromedriver-binary-98.0.4758.80.0-py310h5588dad_0.tar.bz2#b7743e5838d3c5723dc1be77f74036f6 +https://conda.anaconda.org/conda-forge/noarch/stack_data-0.2.0-pyhd8ed1ab_0.tar.bz2#8c0ce3e6bf18a0c810125aef58a2a6f3 +https://conda.anaconda.org/conda-forge/win-64/terminado-0.13.1-py310h5588dad_0.tar.bz2#0cdf91b8a8a7794cb94fae96d6e8295c https://conda.anaconda.org/conda-forge/win-64/trio-0.19.0-py310h5588dad_1.tar.bz2#2dc4914af425bcda0b45037f171965bb https://conda.anaconda.org/conda-forge/noarch/argon2-cffi-21.3.0-pyhd8ed1ab_0.tar.bz2#a0b402db58f73aaab8ee0ca1025a362e -https://conda.anaconda.org/conda-forge/win-64/imagecodecs-2021.11.20-py310h94038b5_1.tar.bz2#bc4cdf06c48083a7e7fa87509de14e9a -https://conda.anaconda.org/conda-forge/noarch/imageio-2.13.5-pyh239f2a4_0.tar.bz2#68b42c3670093b73a058b4a795a632c0 +https://conda.anaconda.org/conda-forge/win-64/imagecodecs-2021.11.20-py310h7704284_2.tar.bz2#ddd3f2fed2b51d9bed4568eb847a7137 +https://conda.anaconda.org/conda-forge/noarch/imageio-2.16.0-pyhcf75d05_0.tar.bz2#2f66b44c933bb86e90e1803716658f21 https://conda.anaconda.org/conda-forge/noarch/jupyter-packaging-0.11.1-pyhd8ed1ab_0.tar.bz2#26db422f83443689cba3af9ae43caf65 -https://conda.anaconda.org/conda-forge/noarch/jupyter_client-7.1.1-pyhd8ed1ab_0.tar.bz2#531f22e91137a4812cb0c864b87fa54e +https://conda.anaconda.org/conda-forge/noarch/jupyter_client-7.1.2-pyhd8ed1ab_0.tar.bz2#9a332b6f8f05629435ce59032df8cfa9 https://conda.anaconda.org/conda-forge/noarch/jupyterlab_pygments-0.1.2-pyh9f0ad1d_0.tar.bz2#2cbd910890bb328e8959246a1e16fac7 https://conda.anaconda.org/conda-forge/win-64/matplotlib-base-3.5.1-py310h79a7439_0.tar.bz2#87c0a748e6e15c4d3bea14147851f02b https://conda.anaconda.org/conda-forge/noarch/nbformat-5.1.3-pyhd8ed1ab_0.tar.bz2#bafa5df6d4f8db69a4d197b4657127e7 -https://conda.anaconda.org/conda-forge/win-64/pandas-1.3.5-py310hf5e1058_0.tar.bz2#d4b5ef00ec931c47dbabe6d329a05531 -https://conda.anaconda.org/conda-forge/noarch/pyopenssl-21.0.0-pyhd8ed1ab_0.tar.bz2#8c49efecb7dca466e18b06015e8c88ce +https://conda.anaconda.org/conda-forge/win-64/pandas-1.4.1-py310hf5e1058_0.tar.bz2#e6d11c7ddad24c7679748b94186e5c66 +https://conda.anaconda.org/conda-forge/noarch/pyopenssl-22.0.0-pyhd8ed1ab_0.tar.bz2#1d7e241dfaf5475e893d4b824bb71b44 https://conda.anaconda.org/conda-forge/noarch/pytest-cov-3.0.0-pyhd8ed1ab_0.tar.bz2#0f7cac11bb696b62d378bde725bfc3eb https://conda.anaconda.org/conda-forge/win-64/pywavelets-1.2.0-py310h2873277_1.tar.bz2#b3842340538035083e79730dcbf698d2 -https://conda.anaconda.org/conda-forge/win-64/scipy-1.7.3-py310h33db832_0.tar.bz2#ebf83a246b208fb8706afd96705653f4 +https://conda.anaconda.org/conda-forge/win-64/scipy-1.8.0-py310h33db832_1.tar.bz2#94aed18abea504ed1053fed14887bd53 https://conda.anaconda.org/conda-forge/noarch/trio-websocket-0.9.2-pyhd8ed1ab_0.tar.bz2#7acf3fc982eef23b24aed10e80d5dc99 https://conda.anaconda.org/conda-forge/noarch/wcwidth-0.2.5-pyh9f0ad1d_2.tar.bz2#5266fcd697043c59621fda522b3d78ee -https://conda.anaconda.org/conda-forge/noarch/jupytext-1.13.6-pyheef035f_0.tar.bz2#686b0fb2e2183e96ebb8faadbb491652 -https://conda.anaconda.org/conda-forge/noarch/nbclient-0.5.10-pyhd8ed1ab_1.tar.bz2#000cfe33d6fa746c5a9d1b29a79342a3 +https://conda.anaconda.org/conda-forge/noarch/jupytext-1.13.7-pyhd0ecf6b_0.tar.bz2#6e8deee97d83b8f99d34be2db26ccc6e +https://conda.anaconda.org/conda-forge/noarch/nbclient-0.5.11-pyhd8ed1ab_0.tar.bz2#5f613d000dca7369b6309f0a3995f08b https://conda.anaconda.org/conda-forge/noarch/networkx-2.6.3-pyhd8ed1ab_1.tar.bz2#4028eff5a1d3deed58c98774e7aa9891 -https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.24-pyha770c72_0.tar.bz2#edaf527a6d394e2b965aff228c2e552f -https://conda.anaconda.org/conda-forge/noarch/tifffile-2021.11.2-pyhd8ed1ab_0.tar.bz2#b07562132d44945a4ae301f75cf731b1 +https://conda.anaconda.org/conda-forge/noarch/prompt-toolkit-3.0.27-pyha770c72_0.tar.bz2#6c23d05d56ee3a82b57af972a8509888 +https://conda.anaconda.org/conda-forge/noarch/tifffile-2022.2.9-pyhd8ed1ab_0.tar.bz2#619b7bd585e11ae063c72e2cf9880145 https://conda.anaconda.org/conda-forge/noarch/urllib3-1.26.8-pyhd8ed1ab_1.tar.bz2#53f1387c68c21cecb386e2cde51b3f7c https://conda.anaconda.org/conda-forge/noarch/vega_datasets-0.9.0-pyhd3deb0d_0.tar.bz2#c754e69d9d5de4a69ff0972318349bd0 -https://conda.anaconda.org/conda-forge/win-64/ipython-7.31.0-py310h5588dad_0.tar.bz2#8ed2acac70603e492b0a22b83982907b -https://conda.anaconda.org/conda-forge/win-64/nbconvert-6.4.0-py310h5588dad_0.tar.bz2#0e1f6f618f497c381746760ffbf26ba7 +https://conda.anaconda.org/conda-forge/win-64/ipython-8.0.1-py310h5588dad_2.tar.bz2#f891ab0617770f29b8b9bce7ef793d0b +https://conda.anaconda.org/conda-forge/win-64/nbconvert-6.4.2-py310h5588dad_0.tar.bz2#8b61a7dc5b50ca890d1379f90fe7474b https://conda.anaconda.org/conda-forge/noarch/requests-2.27.1-pyhd8ed1ab_0.tar.bz2#7c1c427246b057b8fa97200ecdb2ed62 https://conda.anaconda.org/conda-forge/win-64/scikit-image-0.19.1-py310hf5e1058_0.tar.bz2#99f76f01fe093ef88470455d4d89d09a https://conda.anaconda.org/conda-forge/noarch/selenium-4.1.0-pyhd8ed1ab_0.tar.bz2#54d6ec87313ba485cc787b81bf4142c0 https://conda.anaconda.org/conda-forge/noarch/ensureconda-1.4.1-pyhd8ed1ab_0.tar.bz2#52a7f7cc9076e2c8a25e15e19ad42821 -https://conda.anaconda.org/conda-forge/win-64/ipykernel-6.7.0-py310hbbfc1a7_0.tar.bz2#f205d5d215881d298ef9e06edd8ec291 -https://conda.anaconda.org/conda-forge/noarch/jupyter_server-1.13.3-pyhd8ed1ab_0.tar.bz2#0701d62fbbd51356ac3212f401ad18b6 +https://conda.anaconda.org/conda-forge/win-64/ipykernel-6.9.1-py310hbbfc1a7_0.tar.bz2#b6cef5777da0d3b02807a240eda61fb1 +https://conda.anaconda.org/conda-forge/noarch/jupyter_server-1.13.5-pyhd8ed1ab_0.tar.bz2#de2bff665fa83862dbaa9d85720e7719 https://conda.anaconda.org/conda-forge/noarch/conda-lock-0.13.2-pyhd8ed1ab_0.tar.bz2#4fa525b4257e4938eaeb2269fdf33d1f https://conda.anaconda.org/conda-forge/noarch/jupyterlab_server-2.10.3-pyhd8ed1ab_0.tar.bz2#65d62a616bed5237b85b9e2a88378ec0 https://conda.anaconda.org/conda-forge/noarch/nbval-0.9.6-pyh9f0ad1d_0.tar.bz2#b627e05284e7affc46b6e4878aa1d96b -https://conda.anaconda.org/conda-forge/noarch/notebook-6.4.7-pyha770c72_0.tar.bz2#8bf6e732d753521a06571d1efe8e58f2 -https://conda.anaconda.org/conda-forge/noarch/voila-0.3.0-pyhd8ed1ab_1.tar.bz2#5093d08d3afcc35b5ab8184f3b19c028 +https://conda.anaconda.org/conda-forge/noarch/notebook-6.4.8-pyha770c72_0.tar.bz2#87d880386179ed952a9d656faf2ff860 +https://conda.anaconda.org/conda-forge/noarch/voila-0.3.1-pyhd8ed1ab_0.tar.bz2#57d04a687ad1b72d30159a1b2bbf8f3e https://conda.anaconda.org/conda-forge/noarch/nbclassic-0.3.5-pyhd8ed1ab_0.tar.bz2#e9e2281b7dc08d876fc789af0f571ade -https://conda.anaconda.org/conda-forge/noarch/jupyterlab-3.2.8-pyhd8ed1ab_0.tar.bz2#e2cc0671571f14af58f832c912dee025 +https://conda.anaconda.org/conda-forge/noarch/jupyterlab-3.2.9-pyhd8ed1ab_0.tar.bz2#610d3fc318b6eb159483151070b301f4 diff --git a/python/vegafusion/setup.cfg b/python/vegafusion/setup.cfg index 8af15d2b0..e4e0a340b 100644 --- a/python/vegafusion/setup.cfg +++ b/python/vegafusion/setup.cfg @@ -31,6 +31,7 @@ install_requires = altair>=4.2.0 pyarrow>=6 pandas + psutil [options.extras_require] embed = vegafusion-python-embed diff --git a/python/vegafusion/vegafusion/runtime.py b/python/vegafusion/vegafusion/runtime.py index fe9d92acd..6a65e625f 100644 --- a/python/vegafusion/vegafusion/runtime.py +++ b/python/vegafusion/vegafusion/runtime.py @@ -15,12 +15,14 @@ # along with this program. If not, see . import multiprocessing +import psutil class VegaFusionRuntime: - def __init__(self, cache_capacity, worker_threads): + def __init__(self, cache_capacity, memory_limit, worker_threads): self._runtime = None self._cache_capacity = cache_capacity + self._memory_limit = memory_limit self._worker_threads = worker_threads @property @@ -29,7 +31,7 @@ def runtime(self): # Try to initialize an embedded runtime from vegafusion_embed import PyTaskGraphRuntime - self._runtime = PyTaskGraphRuntime(self.cache_capacity, self.worker_threads) + self._runtime = PyTaskGraphRuntime(self.cache_capacity, self.memory_limit, self.worker_threads) return self._runtime def process_request_bytes(self, request): @@ -50,6 +52,49 @@ def worker_threads(self, value): self._worker_threads = value self.reset() + @property + def total_memory(self): + if self._runtime: + return self._runtime.total_memory() + else: + return None + + @property + def _protected_memory(self): + if self._runtime: + return self._runtime.protected_memory() + else: + return None + + @property + def _probationary_memory(self): + if self._runtime: + return self._runtime.probationary_memory() + else: + return None + + @property + def size(self): + if self._runtime: + return self._runtime.size() + else: + return None + + @property + def memory_limit(self): + return self._memory_limit + + @memory_limit.setter + def memory_limit(self, value): + """ + Restart the runtime with the specified memory limit + + :param threads: Max approximate memory usage of cache + """ + if value != self._memory_limit: + self._memory_limit = value + self.reset() + @property def cache_capacity(self): return self._cache_capacity @@ -78,4 +123,4 @@ def __repr__(self): ) -runtime = VegaFusionRuntime(16, multiprocessing.cpu_count()) +runtime = VegaFusionRuntime(64, psutil.virtual_memory().total // 2, psutil.cpu_count()) diff --git a/vegafusion-core/src/task_graph/memory.rs b/vegafusion-core/src/task_graph/memory.rs new file mode 100644 index 000000000..a1d1024ec --- /dev/null +++ b/vegafusion-core/src/task_graph/memory.rs @@ -0,0 +1,95 @@ +use crate::data::scalar::ScalarValue; +use crate::data::table::VegaFusionTable; +use arrow::array::ArrayRef; +use arrow::datatypes::{DataType, Field, Schema}; +use arrow::record_batch::RecordBatch; +use std::mem::{size_of, size_of_val}; + +/// Get the size of a Field value, including any inner heap-allocated data +fn size_of_field(field: &Field) -> usize { + size_of::() + inner_size_of_dtype(field.data_type()) +} + +/// Get the size of inner heap-allocated data associated with a DataType value +fn inner_size_of_dtype(value: &DataType) -> usize { + match value { + DataType::Map(field, _) => size_of_field(field), + DataType::Timestamp(_, Some(tz)) => size_of::() + size_of_val(tz.as_bytes()), + DataType::List(field) => size_of_field(field), + DataType::LargeList(field) => size_of_field(field), + DataType::FixedSizeList(field, _) => size_of_field(field), + DataType::Struct(fields) => { + size_of::>() + fields.iter().map(size_of_field).sum::() + } + DataType::Union(fields) => { + size_of::>() + fields.iter().map(size_of_field).sum::() + } + DataType::Dictionary(key_dtype, value_dtype) => { + 2 * size_of::() + + inner_size_of_dtype(key_dtype) + + inner_size_of_dtype(value_dtype) + } + _ => { + // No inner heap-allocated data + 0 + } + } +} + +/// Get the size of inner heap-allocated data associated with a ScalarValue value +pub fn inner_size_of_scalar(value: &ScalarValue) -> usize { + match value { + ScalarValue::Utf8(Some(s)) => size_of_val(s.as_bytes()) + size_of::(), + ScalarValue::LargeUtf8(Some(s)) => size_of_val(s.as_bytes()) + size_of::(), + ScalarValue::Binary(Some(b)) => size_of_val(b.as_slice()) + size_of::>(), + ScalarValue::LargeBinary(Some(b)) => size_of_val(b.as_slice()) + size_of::>(), + ScalarValue::List(Some(values), dtype) => { + let values_bytes: usize = size_of::>() + + values + .iter() + .map(|v| size_of::() + inner_size_of_scalar(v)) + .sum::(); + + let dtype_bytes = size_of::() + inner_size_of_dtype(dtype); + + values_bytes + dtype_bytes + } + ScalarValue::Struct(Some(values), fields) => { + let values_bytes: usize = size_of::>() + + values + .iter() + .map(|v| size_of::() + inner_size_of_scalar(v)) + .sum::(); + + let fields_bytes: usize = + size_of::>() + fields.iter().map(size_of_field).sum::(); + + values_bytes + fields_bytes + } + _ => { + // No inner heap-allocated data + 0 + } + } +} + +pub fn size_of_array_ref(array: &ArrayRef) -> usize { + array.get_array_memory_size() + inner_size_of_dtype(array.data_type()) + size_of::() +} + +pub fn size_of_schema(schema: &Schema) -> usize { + size_of::() + schema.fields().iter().map(size_of_field).sum::() +} + +pub fn size_of_record_batch(batch: &RecordBatch) -> usize { + let schema = batch.schema(); + let schema_size: usize = size_of_schema(schema.as_ref()); + let arrays_size: usize = batch.columns().iter().map(size_of_array_ref).sum(); + size_of::() + schema_size + arrays_size +} + +pub fn inner_size_of_table(value: &VegaFusionTable) -> usize { + let schema_size: usize = size_of_schema(&value.schema); + let size_of_batches: usize = value.batches.iter().map(size_of_record_batch).sum(); + schema_size + size_of_batches +} diff --git a/vegafusion-core/src/task_graph/mod.rs b/vegafusion-core/src/task_graph/mod.rs index 22d4ffe69..da5ddb31a 100644 --- a/vegafusion-core/src/task_graph/mod.rs +++ b/vegafusion-core/src/task_graph/mod.rs @@ -17,6 +17,7 @@ * If not, see http://www.gnu.org/licenses/. */ pub mod graph; +pub mod memory; pub mod scope; pub mod task; pub mod task_value; diff --git a/vegafusion-core/src/task_graph/task_value.rs b/vegafusion-core/src/task_graph/task_value.rs index 57528d5d2..eb61e7fdc 100644 --- a/vegafusion-core/src/task_graph/task_value.rs +++ b/vegafusion-core/src/task_graph/task_value.rs @@ -21,6 +21,7 @@ use crate::data::table::VegaFusionTable; use crate::error::{Result, VegaFusionError}; use crate::proto::gen::tasks::task_value::Data; use crate::proto::gen::tasks::TaskValue as ProtoTaskValue; +use crate::task_graph::memory::{inner_size_of_scalar, inner_size_of_table}; use arrow::record_batch::RecordBatch; use serde_json::Value; use std::convert::TryFrom; @@ -52,6 +53,15 @@ impl TaskValue { TaskValue::Table(value) => Ok(value.to_json()), } } + + pub fn size_of(&self) -> usize { + let inner_size = match self { + TaskValue::Scalar(scalar) => inner_size_of_scalar(scalar), + TaskValue::Table(table) => inner_size_of_table(table), + }; + + std::mem::size_of::() + inner_size + } } impl TryFrom<&ProtoTaskValue> for TaskValue { diff --git a/vegafusion-python-embed/src/lib.rs b/vegafusion-python-embed/src/lib.rs index ef99b36a1..13c325c7a 100644 --- a/vegafusion-python-embed/src/lib.rs +++ b/vegafusion-python-embed/src/lib.rs @@ -32,7 +32,11 @@ struct PyTaskGraphRuntime { #[pymethods] impl PyTaskGraphRuntime { #[new] - pub fn new(max_capacity: i32, worker_threads: Option) -> PyResult { + pub fn new( + max_capacity: Option, + memory_limit: Option, + worker_threads: Option, + ) -> PyResult { let mut tokio_runtime_builder = tokio::runtime::Builder::new_multi_thread(); tokio_runtime_builder.enable_all(); @@ -46,7 +50,7 @@ impl PyTaskGraphRuntime { .external("Failed to create Tokio thread pool")?; Ok(Self { - runtime: TaskGraphRuntime::new(max_capacity as usize), + runtime: TaskGraphRuntime::new(max_capacity, memory_limit), tokio_runtime, }) } @@ -61,6 +65,22 @@ impl PyTaskGraphRuntime { pub fn clear_cache(&self) { self.tokio_runtime.block_on(self.runtime.clear_cache()); } + + pub fn size(&self) -> usize { + self.runtime.cache.size() + } + + pub fn total_memory(&self) -> usize { + self.runtime.cache.total_memory() + } + + pub fn protected_memory(&self) -> usize { + self.runtime.cache.protected_memory() + } + + pub fn probationary_memory(&self) -> usize { + self.runtime.cache.probationary_memory() + } } /// A Python module implemented in Rust. The name of this function must match diff --git a/vegafusion-rt-datafusion/src/task_graph/cache.rs b/vegafusion-rt-datafusion/src/task_graph/cache.rs index 922b50f16..3adf294f1 100644 --- a/vegafusion-rt-datafusion/src/task_graph/cache.rs +++ b/vegafusion-rt-datafusion/src/task_graph/cache.rs @@ -16,56 +16,254 @@ * License along with this program. * If not, see http://www.gnu.org/licenses/. */ -use async_lock::{Mutex, RwLock}; +use async_lock::{Mutex, MutexGuard, RwLock}; use futures::FutureExt; use lru::LruCache; use std::collections::hash_map::Entry; use std::collections::HashMap; use std::future::Future; use std::panic::{resume_unwind, AssertUnwindSafe}; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; +use std::time::Instant; use vegafusion_core::error::{DuplicateResult, Result, ToExternalError}; use vegafusion_core::task_graph::task_value::TaskValue; #[derive(Debug, Clone)] struct CachedValue { - value: NodeValue, // Maybe add metrics like compute time, or a cache weight + value: NodeValue, + calculation_millis: u128, +} + +impl CachedValue { + pub fn size_of(&self) -> usize { + self.value.0.size_of() + self.value.1.iter().map(|v| v.size_of()).sum::() + } } type NodeValue = (TaskValue, Vec); type Initializer = Arc>>>; +/// The VegaFusionCache uses a Segmented LRU (SLRU) cache policy +/// (https://en.wikipedia.org/wiki/Cache_replacement_policies#Segmented_LRU_(SLRU)) where both the +/// protected and probationary LRU caches are limited by capacity (number of entries) and memory +/// limit. #[derive(Debug, Clone)] pub struct VegaFusionCache { - values: Arc>>, + protected_cache: Arc>>, + probationary_cache: Arc>>, + protected_fraction: f64, initializers: Arc>>, + size: Arc, + protected_memory: Arc, + probationary_memory: Arc, + capacity: Option, + memory_limit: Option, } impl VegaFusionCache { - pub fn new(capacity: usize) -> Self { + pub fn new(capacity: Option, size_limit: Option) -> Self { Self { - values: Arc::new(Mutex::new(LruCache::new(capacity))), + protected_cache: Arc::new(Mutex::new(LruCache::unbounded())), + probationary_cache: Arc::new(Mutex::new(LruCache::unbounded())), + protected_fraction: 0.5, initializers: Default::default(), + capacity, + memory_limit: size_limit, + size: Arc::new(AtomicUsize::new(0)), + protected_memory: Arc::new(AtomicUsize::new(0)), + probationary_memory: Arc::new(AtomicUsize::new(0)), } } + pub fn capacity(&self) -> Option { + self.capacity + } + + pub fn memory_limit(&self) -> Option { + self.memory_limit + } + + pub fn size(&self) -> usize { + self.size.load(Ordering::Relaxed) + } + + pub fn total_memory(&self) -> usize { + self.protected_memory() + self.probationary_memory() + } + + pub fn protected_memory(&self) -> usize { + self.protected_memory.load(Ordering::Relaxed) + } + + pub fn probationary_memory(&self) -> usize { + self.probationary_memory.load(Ordering::Relaxed) + } + pub async fn clear(&self) { // Clear the values cache. There may still be initializers representing in progress // futures which will not be cleared. - self.values.lock().await.clear(); + self.protected_cache.lock().await.clear(); + self.probationary_cache.lock().await.clear(); + self.protected_memory.store(0, Ordering::Relaxed); + self.probationary_memory.store(0, Ordering::Relaxed); + self.size.store(0, Ordering::Relaxed); + } + + async fn get(&self, state_fingerprint: u64) -> Option { + let mut protected = self.protected_cache.lock().await; + let mut probationary = self.probationary_cache.lock().await; + + if protected.contains(&state_fingerprint) { + protected.get(&state_fingerprint).cloned() + } else if probationary.contains(&state_fingerprint) { + // Promote entry from probationary to protected + let value = probationary.pop(&state_fingerprint).unwrap(); + let value_memory = value.size_of(); + protected.put(state_fingerprint, value.clone()); + + self.protected_memory + .fetch_add(value_memory, Ordering::Relaxed); + self.probationary_memory + .fetch_sub(value_memory, Ordering::Relaxed); + + // Balance caches + self.balance(&mut protected, &mut probationary); + + Some(value) + } else { + None + } + } + + fn pop_protected_lru( + &self, + protected: &mut MutexGuard>, + probationary: &mut MutexGuard>, + ) { + // Remove one protected LRU entry + let (key, popped_value) = protected.pop_lru().unwrap(); + let popped_memory = popped_value.size_of(); + + // Decrement protected memory + self.protected_memory + .fetch_sub(popped_memory, Ordering::Relaxed); + + // Add entry to probationary cache + probationary.put(key, popped_value); + + // Increment probationary memory + self.probationary_memory + .fetch_add(popped_memory, Ordering::Relaxed); } - async fn get_from_values(&self, state_fingerprint: u64) -> Option { - // This is a write lock because the LruCache.get function mutates the Cache to update - // the LRU status - self.values.lock().await.get(&state_fingerprint).cloned() + fn pop_probationary_lru(&self, probationary: &mut MutexGuard>) { + let (_, popped_value) = probationary.pop_lru().unwrap(); + let popped_memory = popped_value.size_of(); + + // Decrement protected memory + self.probationary_memory + .fetch_sub(popped_memory, Ordering::Relaxed); } - async fn set_value(&self, state_fingerprint: u64, value: NodeValue) -> Option { - self.values - .lock() - .await - .put(state_fingerprint, CachedValue { value }) + fn balance( + &self, + protected: &mut MutexGuard>, + probationary: &mut MutexGuard>, + ) { + // Compute capacity and memory limits for both protected and probationary caches + let (protected_capacity, probationary_capacity) = if let Some(capacity) = self.capacity { + let protected_capacity = (capacity as f64 * self.protected_fraction).ceil() as usize; + ( + Some(protected_capacity), + Some(capacity - protected_capacity), + ) + } else { + (None, None) + }; + + let (protected_mem_limit, probationary_mem_limit) = + if let Some(memory_limit) = self.memory_limit { + let protected_mem_limit = + (memory_limit as f64 * self.protected_fraction).ceil() as usize; + ( + Some(protected_mem_limit), + Some(memory_limit - protected_mem_limit), + ) + } else { + (None, None) + }; + + // Step 1: Shrink protected cache until it satisfies limits, moving evicted items to + // probationary cache + // Pop to capacity limit + if let Some(capacity) = protected_capacity { + while protected.len() > 1 && protected.len() > capacity { + self.pop_protected_lru(protected, probationary); + } + } + + // Pop LRU to memory limit + if let Some(memory_limit) = protected_mem_limit { + while protected.len() > 1 + && self.protected_memory.load(Ordering::Relaxed) > memory_limit + { + self.pop_protected_lru(protected, probationary); + } + } + + // Step 2: Shrink probationary cache until it satisfies limits, + // decrementing memory estimate + if let Some(capacity) = probationary_capacity { + while probationary.len() > 1 && probationary.len() > capacity { + self.pop_probationary_lru(probationary); + } + } + + // Pop LRU to memory limit + if let Some(memory_limit) = probationary_mem_limit { + while probationary.len() > 1 + && self.probationary_memory.load(Ordering::Relaxed) > memory_limit + { + self.pop_probationary_lru(probationary); + } + } + + // Step 3: Update size atomics + self.size + .store(protected.len() + probationary.len(), Ordering::Relaxed); + } + + async fn set_value(&self, state_fingerprint: u64, value: NodeValue, calculation_millis: u128) { + let cache_value = CachedValue { + value, + calculation_millis, + }; + let value_memory = cache_value.size_of(); + + let mut protected = self.protected_cache.lock().await; + let mut probationary = self.probationary_cache.lock().await; + if protected.contains(&state_fingerprint) { + // Set on protected to update usage + protected.put(state_fingerprint, cache_value); + } else if probationary.contains(&state_fingerprint) { + // Promote from probationary to protected + protected.put( + state_fingerprint, + probationary.pop(&state_fingerprint).unwrap(), + ); + self.protected_memory + .fetch_add(value_memory, Ordering::Relaxed); + self.probationary_memory + .fetch_sub(value_memory, Ordering::Relaxed); + self.balance(&mut protected, &mut probationary); + } else { + // Add to probationary and update memory usage + probationary.put(state_fingerprint, cache_value); + self.probationary_memory + .fetch_add(value_memory, Ordering::Relaxed); + self.balance(&mut protected, &mut probationary); + } } async fn remove_initializer(&self, state_fingerprint: u64) -> Option { @@ -81,7 +279,7 @@ impl VegaFusionCache { F: Future> + Send + 'static, { // Check if present in the values cache - if let Some(value) = self.get_from_values(state_fingerprint).await { + if let Some(value) = self.get(state_fingerprint).await { return Ok(value.value); } @@ -111,6 +309,9 @@ impl VegaFusionCache { // Drop write lock drop(initializers_lock); + // Record start time + let start = Instant::now(); + // Invoke future to initialize match AssertUnwindSafe(tokio::spawn(init)).catch_unwind().await { // Resolved. @@ -119,7 +320,12 @@ impl VegaFusionCache { match value { Ok(value) => { *initializer_lock = Some(Ok(value.clone())); - self.set_value(state_fingerprint, value.clone()).await; + + // Check if we should add value to long-term cache + let duration = start.elapsed(); + let millis = duration.as_millis(); + self.set_value(state_fingerprint, value.clone(), millis) + .await; // Stored initializer no longer required. Initializers are Arc // pointers, so it's fine to drop initializer from here even if @@ -164,7 +370,7 @@ mod test_cache { #[tokio::test(flavor = "multi_thread")] async fn try_cache() { - let cache = VegaFusionCache::new(4); + let cache = VegaFusionCache::new(Some(4), None); let value_future1 = cache.get_or_try_insert_with(1, make_value(ScalarValue::from(23.5))); let value_future2 = cache.get_or_try_insert_with(1, make_value(ScalarValue::from(23.5))); diff --git a/vegafusion-rt-datafusion/src/task_graph/runtime.rs b/vegafusion-rt-datafusion/src/task_graph/runtime.rs index d0dc0be1f..1ef03f509 100644 --- a/vegafusion-rt-datafusion/src/task_graph/runtime.rs +++ b/vegafusion-rt-datafusion/src/task_graph/runtime.rs @@ -45,9 +45,9 @@ pub struct TaskGraphRuntime { } impl TaskGraphRuntime { - pub fn new(max_capacity: usize) -> Self { + pub fn new(capacity: Option, memory_limit: Option) -> Self { Self { - cache: VegaFusionCache::new(max_capacity), + cache: VegaFusionCache::new(capacity, memory_limit), } } diff --git a/vegafusion-rt-datafusion/tests/test_image_comparison.rs b/vegafusion-rt-datafusion/tests/test_image_comparison.rs index 29f1f9e88..742d78d56 100644 --- a/vegafusion-rt-datafusion/tests/test_image_comparison.rs +++ b/vegafusion-rt-datafusion/tests/test_image_comparison.rs @@ -1151,7 +1151,7 @@ async fn check_spec_sequence( .collect(); // Initialize task graph runtime - let runtime = TaskGraphRuntime::new(10); + let runtime = TaskGraphRuntime::new(Some(16), Some(1024_i32.pow(3) as usize)); // Extract the initial values of all of the variables that should be sent from the // server to the client diff --git a/vegafusion-rt-datafusion/tests/test_planning.rs b/vegafusion-rt-datafusion/tests/test_planning.rs index 34acb7b8a..4e007de2a 100644 --- a/vegafusion-rt-datafusion/tests/test_planning.rs +++ b/vegafusion-rt-datafusion/tests/test_planning.rs @@ -71,7 +71,7 @@ async fn test_extract_server_data() { let mapping = graph.build_mapping(); // println!("{:#?}", mapping); - let graph_runtime = TaskGraphRuntime::new(20); + let graph_runtime = TaskGraphRuntime::new(Some(20), Some(1024_i32.pow(3) as usize)); let _data_3 = graph_runtime .get_node_value( graph.clone(), diff --git a/vegafusion-rt-datafusion/tests/test_task_graph_runtime.rs b/vegafusion-rt-datafusion/tests/test_task_graph_runtime.rs index 95e515613..e1efdc0d7 100644 --- a/vegafusion-rt-datafusion/tests/test_task_graph_runtime.rs +++ b/vegafusion-rt-datafusion/tests/test_task_graph_runtime.rs @@ -85,7 +85,7 @@ async fn try_it() { let graph = Arc::new(TaskGraph::new(tasks, &task_scope).unwrap()); - let graph_runtime = TaskGraphRuntime::new(20); + let graph_runtime = TaskGraphRuntime::new(Some(20), Some(1024_i32.pow(3) as usize)); // let result = graph_runtime.get_node_value(graph, 2, None).await.unwrap(); let result = graph_runtime .get_node_value(graph, &NodeValueIndex::new(2, Some(0))) @@ -139,7 +139,7 @@ async fn try_it_from_spec() { let graph = Arc::new(TaskGraph::new(tasks, &task_scope).unwrap()); - let graph_runtime = TaskGraphRuntime::new(20); + let graph_runtime = TaskGraphRuntime::new(Some(20), Some(1024_i32.pow(3) as usize)); let result = graph_runtime .get_node_value(graph, &NodeValueIndex::new(2, Some(0))) .await diff --git a/vegafusion-wasm/examples/websocket_server.rs b/vegafusion-wasm/examples/websocket_server.rs index 9fab2a0b9..af8ccb7f8 100644 --- a/vegafusion-wasm/examples/websocket_server.rs +++ b/vegafusion-wasm/examples/websocket_server.rs @@ -54,7 +54,7 @@ async fn main() -> std::result::Result<(), Error> { let listener = try_socket.expect("Failed to bind"); println!("Listening on: {}", addr); - let runtime = TaskGraphRuntime::new(10); + let runtime = TaskGraphRuntime::new(Some(64), Some(1024_i32.pow(3) as usize)); while let Ok((stream, _)) = listener.accept().await { tokio::spawn(accept_connection(stream, runtime.clone()));