diff --git a/.gitignore b/.gitignore index b1c52f250..a4af067d2 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,5 @@ traces/ apps/jupyter/bind_dir/poetry_cache apps/query-ui/cache_dir docs/build +cache notebooks/default-prep-data diff --git a/apps/jupyter/Dockerfile.buildx b/apps/jupyter/Dockerfile.buildx index 7ac99ed70..c2aaf5d21 100644 --- a/apps/jupyter/Dockerfile.buildx +++ b/apps/jupyter/Dockerfile.buildx @@ -9,7 +9,6 @@ FROM arynai/sycamore-base:$TAG ARG GIT_BRANCH="unknown" ARG GIT_COMMIT="unknown" ARG GIT_DIFF="unknown" -ARG ERIC_TEST="foo" ENV GIT_BRANCH=${GIT_BRANCH} ENV GIT_COMMIT=${GIT_COMMIT} diff --git a/apps/jupyter/run-jupyter.sh b/apps/jupyter/run-jupyter.sh index 36c15ed72..f4ddb703e 100755 --- a/apps/jupyter/run-jupyter.sh +++ b/apps/jupyter/run-jupyter.sh @@ -29,15 +29,42 @@ if [[ -x "${BIND_DIR}/setup.sh" ]]; then SETUP_FAILED=true fi fi + +if [[ "${JUPYTER_CONFIG_RESET}" == yes ]]; then + echo "Resetting jupyter configuration" + rm -f "${JUPYTER_CONFIG_DOCKER}" +fi + if [[ ! -f "${JUPYTER_CONFIG_DOCKER}" ]]; then TOKEN=$(openssl rand -hex 24) - cat >"${JUPYTER_CONFIG_DOCKER}" <"${JUPYTER_CONFIG_DOCKER}".tmp <>"${JUPYTER_CONFIG_DOCKER}".tmp <>"${JUPYTER_CONFIG_DOCKER}".tmp ;; + esac + fi + mv "${JUPYTER_CONFIG_DOCKER}".tmp "${JUPYTER_CONFIG_DOCKER}" fi ln -snf "${JUPYTER_CONFIG_DOCKER}" $HOME/.jupyter @@ -77,10 +104,13 @@ fi exit 1 fi - sleep 1 # reduce race with file being written REDIRECT="${BIND_DIR}/redirect.html" - perl -ne 's,://\S+:8888/tree,://localhost:8888/tree,;print' < "${FILE}" >"${REDIRECT}" - URL=$(perl -ne 'print $1 if m,url=(https?://localhost:8888/tree\S+)",;' <"${REDIRECT}") + while [[ "${URL}" == "" ]]; do + echo "Waiting to find the URL in ${FILE}..." + sleep 1 + perl -ne 's,://\S+:8888/lab,://localhost:8888/lab,;print' < "${FILE}" >"${REDIRECT}" + URL=$(perl -ne 'print $1 if m,url=(https?://localhost:8888/lab\S+)",;' <"${REDIRECT}") + done for i in {1..10}; do echo @@ -93,6 +123,7 @@ fi echo " c) docker compose cp jupyter:${BIND_DIR}/redirect.html ." echo " and open redirect.html in a browser" echo " Note: the token is stable unless you delete docker_volume/jupyter_notebook_config.py" + echo " or you set JUPYTER_CONFIG_RESET=yes when starting the container" sleep 30 done ) & @@ -100,4 +131,4 @@ fi trap "kill $!" EXIT cd "${WORK_DIR}" -poetry run jupyter notebook "${SSLARG[@]}" --no-browser --ip 0.0.0.0 "$@" +poetry run jupyter lab "${SSLARG[@]}" --no-browser --ip 0.0.0.0 "$@" diff --git a/compose.yaml b/compose.yaml index fbbd39366..c9c8c7081 100644 --- a/compose.yaml +++ b/compose.yaml @@ -71,6 +71,9 @@ services: - AWS_SECRET_ACCESS_KEY - AWS_SESSION_TOKEN - AWS_CREDENTIAL_EXPIRATION + - JUPYTER_S3_BUCKET + - JUPYTER_S3_PREFIX + - JUPYTER_CONFIG_RESET # set this to 'yes' to reset the configuration - SSL # Set to 1 if you want self-signed certificates ### Optional profiles below here diff --git a/poetry.lock b/poetry.lock index 0cef84433..911c3b532 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,26 @@ -# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "aiobotocore" +version = "2.15.1" +description = "Async client for aws services using botocore and aiohttp" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aiobotocore-2.15.1-py3-none-any.whl", hash = "sha256:0f738cde74108553b753b24655094289a3c7ea0f0f179ed1c0f8cea488999a35"}, + {file = "aiobotocore-2.15.1.tar.gz", hash = "sha256:1f9f16eec2a3da32df162b5db12da779ec6d6c6311715c936cad511f436efa74"}, +] + +[package.dependencies] +aiohttp = ">=3.9.2,<4.0.0" +aioitertools = ">=0.5.1,<1.0.0" +boto3 = {version = ">=1.35.16,<1.35.24", optional = true, markers = "extra == \"boto3\""} +botocore = ">=1.35.16,<1.35.24" +wrapt = ">=1.10.10,<2.0.0" + +[package.extras] +awscli = ["awscli (>=1.34.16,<1.34.24)"] +boto3 = ["boto3 (>=1.35.16,<1.35.24)"] [[package]] name = "aiohappyeyeballs" @@ -122,6 +144,24 @@ files = [ [package.dependencies] aiohttp = ">=1.1" +[[package]] +name = "aioitertools" +version = "0.12.0" +description = "itertools and builtins for AsyncIO and mixed iterables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "aioitertools-0.12.0-py3-none-any.whl", hash = "sha256:fc1f5fac3d737354de8831cbba3eb04f79dd649d8f3afb4c5b114925e662a796"}, + {file = "aioitertools-0.12.0.tar.gz", hash = "sha256:c2a9055b4fbb7705f561b9d86053e8af5d10cc845d22c32008c43490b2d8dd6b"}, +] + +[package.dependencies] +typing_extensions = {version = ">=4.0", markers = "python_version < \"3.10\""} + +[package.extras] +dev = ["attribution (==1.8.0)", "black (==24.8.0)", "build (>=1.2)", "coverage (==7.6.1)", "flake8 (==7.1.1)", "flit (==3.9.0)", "mypy (==1.11.2)", "ufmt (==2.7.1)", "usort (==1.0.8.post1)"] +docs = ["sphinx (==8.0.2)", "sphinx-mdinclude (==0.6.2)"] + [[package]] name = "aiosignal" version = "1.3.1" @@ -2292,6 +2332,30 @@ pygments = ">=2.7" sphinx = ">=6.0,<8.0" sphinx-basic-ng = "*" +[[package]] +name = "gcsfs" +version = "2024.2.0" +description = "Convenient Filesystem interface over GCS" +optional = false +python-versions = ">=3.8" +files = [ + {file = "gcsfs-2024.2.0-py2.py3-none-any.whl", hash = "sha256:20bf70cc81d580474dd299d55e1ffcf8b3e81721aeb562e148ca0a3c900d0421"}, + {file = "gcsfs-2024.2.0.tar.gz", hash = "sha256:f7cffd7cae2fb50c56ef883f8aef9792be045b5059f06c1902c3a6151509f506"}, +] + +[package.dependencies] +aiohttp = "<4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1" +decorator = ">4.1.2" +fsspec = "2024.2.0" +google-auth = ">=1.2" +google-auth-oauthlib = "*" +google-cloud-storage = "*" +requests = "*" + +[package.extras] +crc = ["crcmod"] +gcsfuse = ["fusepy"] + [[package]] name = "gitdb" version = "4.0.11" @@ -2370,6 +2434,122 @@ pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] requests = ["requests (>=2.20.0,<3.0.0.dev0)"] +[[package]] +name = "google-auth-oauthlib" +version = "1.2.1" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.6" +files = [ + {file = "google_auth_oauthlib-1.2.1-py2.py3-none-any.whl", hash = "sha256:2d58a27262d55aa1b87678c3ba7142a080098cbc2024f903c62355deb235d91f"}, + {file = "google_auth_oauthlib-1.2.1.tar.gz", hash = "sha256:afd0cad092a2eaa53cd8e8298557d6de1034c6cb4a740500b5357b648af97263"}, +] + +[package.dependencies] +google-auth = ">=2.15.0" +requests-oauthlib = ">=0.7.0" + +[package.extras] +tool = ["click (>=6.0.0)"] + +[[package]] +name = "google-cloud-core" +version = "2.4.1" +description = "Google Cloud API client core library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-cloud-core-2.4.1.tar.gz", hash = "sha256:9b7749272a812bde58fff28868d0c5e2f585b82f37e09a1f6ed2d4d10f134073"}, + {file = "google_cloud_core-2.4.1-py2.py3-none-any.whl", hash = "sha256:a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61"}, +] + +[package.dependencies] +google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" +google-auth = ">=1.25.0,<3.0dev" + +[package.extras] +grpc = ["grpcio (>=1.38.0,<2.0dev)", "grpcio-status (>=1.38.0,<2.0.dev0)"] + +[[package]] +name = "google-cloud-storage" +version = "2.18.2" +description = "Google Cloud Storage API client library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google_cloud_storage-2.18.2-py2.py3-none-any.whl", hash = "sha256:97a4d45c368b7d401ed48c4fdfe86e1e1cb96401c9e199e419d289e2c0370166"}, + {file = "google_cloud_storage-2.18.2.tar.gz", hash = "sha256:aaf7acd70cdad9f274d29332673fcab98708d0e1f4dceb5a5356aaef06af4d99"}, +] + +[package.dependencies] +google-api-core = ">=2.15.0,<3.0.0dev" +google-auth = ">=2.26.1,<3.0dev" +google-cloud-core = ">=2.3.0,<3.0dev" +google-crc32c = ">=1.0,<2.0dev" +google-resumable-media = ">=2.7.2" +requests = ">=2.18.0,<3.0.0dev" + +[package.extras] +protobuf = ["protobuf (<6.0.0dev)"] +tracing = ["opentelemetry-api (>=1.1.0)"] + +[[package]] +name = "google-crc32c" +version = "1.6.0" +description = "A python wrapper of the C library 'Google CRC32C'" +optional = false +python-versions = ">=3.9" +files = [ + {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:5bcc90b34df28a4b38653c36bb5ada35671ad105c99cfe915fb5bed7ad6924aa"}, + {file = "google_crc32c-1.6.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:d9e9913f7bd69e093b81da4535ce27af842e7bf371cde42d1ae9e9bd382dc0e9"}, + {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a184243544811e4a50d345838a883733461e67578959ac59964e43cca2c791e7"}, + {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:236c87a46cdf06384f614e9092b82c05f81bd34b80248021f729396a78e55d7e"}, + {file = "google_crc32c-1.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebab974b1687509e5c973b5c4b8b146683e101e102e17a86bd196ecaa4d099fc"}, + {file = "google_crc32c-1.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:50cf2a96da226dcbff8671233ecf37bf6e95de98b2a2ebadbfdf455e6d05df42"}, + {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:f7a1fc29803712f80879b0806cb83ab24ce62fc8daf0569f2204a0cfd7f68ed4"}, + {file = "google_crc32c-1.6.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:40b05ab32a5067525670880eb5d169529089a26fe35dce8891127aeddc1950e8"}, + {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e4b426c3702f3cd23b933436487eb34e01e00327fac20c9aebb68ccf34117d"}, + {file = "google_crc32c-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51c4f54dd8c6dfeb58d1df5e4f7f97df8abf17a36626a217f169893d1d7f3e9f"}, + {file = "google_crc32c-1.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:bb8b3c75bd157010459b15222c3fd30577042a7060e29d42dabce449c087f2b3"}, + {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ed767bf4ba90104c1216b68111613f0d5926fb3780660ea1198fc469af410e9d"}, + {file = "google_crc32c-1.6.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:62f6d4a29fea082ac4a3c9be5e415218255cf11684ac6ef5488eea0c9132689b"}, + {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c87d98c7c4a69066fd31701c4e10d178a648c2cac3452e62c6b24dc51f9fcc00"}, + {file = "google_crc32c-1.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd5e7d2445d1a958c266bfa5d04c39932dc54093fa391736dbfdb0f1929c1fb3"}, + {file = "google_crc32c-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:7aec8e88a3583515f9e0957fe4f5f6d8d4997e36d0f61624e70469771584c760"}, + {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:e2806553238cd076f0a55bddab37a532b53580e699ed8e5606d0de1f856b5205"}, + {file = "google_crc32c-1.6.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:bb0966e1c50d0ef5bc743312cc730b533491d60585a9a08f897274e57c3f70e0"}, + {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:386122eeaaa76951a8196310432c5b0ef3b53590ef4c317ec7588ec554fec5d2"}, + {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2952396dc604544ea7476b33fe87faedc24d666fb0c2d5ac971a2b9576ab871"}, + {file = "google_crc32c-1.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35834855408429cecf495cac67ccbab802de269e948e27478b1e47dfb6465e57"}, + {file = "google_crc32c-1.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:d8797406499f28b5ef791f339594b0b5fdedf54e203b5066675c406ba69d705c"}, + {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48abd62ca76a2cbe034542ed1b6aee851b6f28aaca4e6551b5599b6f3ef175cc"}, + {file = "google_crc32c-1.6.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e311c64008f1f1379158158bb3f0c8d72635b9eb4f9545f8cf990c5668e59d"}, + {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05e2d8c9a2f853ff116db9706b4a27350587f341eda835f46db3c0a8c8ce2f24"}, + {file = "google_crc32c-1.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ca8145b060679ec9176e6de4f89b07363d6805bd4760631ef254905503598d"}, + {file = "google_crc32c-1.6.0.tar.gz", hash = "sha256:6eceb6ad197656a1ff49ebfbbfa870678c75be4344feb35ac1edf694309413dc"}, +] + +[package.extras] +testing = ["pytest"] + +[[package]] +name = "google-resumable-media" +version = "2.7.2" +description = "Utilities for Google Media Downloads and Resumable Uploads" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa"}, + {file = "google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0"}, +] + +[package.dependencies] +google-crc32c = ">=1.0,<2.0dev" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "google-auth (>=1.22.0,<2.0dev)"] +requests = ["requests (>=2.18.0,<3.0.0dev)"] + [[package]] name = "googleapis-common-protos" version = "1.63.2" @@ -5055,6 +5235,22 @@ files = [ {file = "nvidia_nvtx_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:65f4d98982b31b60026e0e6de73fbdfc09d08a96f4656dd3665ca616a11e1e82"}, ] +[[package]] +name = "oauthlib" +version = "3.2.2" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +optional = false +python-versions = ">=3.6" +files = [ + {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, + {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, +] + +[package.extras] +rsa = ["cryptography (>=3.0.0)"] +signals = ["blinker (>=1.4.0)"] +signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] + [[package]] name = "openai" version = "1.40.2" @@ -5524,6 +5720,17 @@ dense = ["openai (>=1.2.3,<2.0.0)", "sentence-transformers (>=2.0.0)", "torch (> openai = ["openai (>=1.2.3,<2.0.0)"] splade = ["sentence-transformers (>=2.0.0)", "torch (>=1.13.1)", "transformers (>=4.26.1)"] +[[package]] +name = "pip" +version = "24.2" +description = "The PyPA recommended tool for installing Python packages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pip-24.2-py3-none-any.whl", hash = "sha256:2cd581cf58ab7fcfca4ce8efa6dcacd0de5bf8d0a3eb9ec927e07405f4d9e2a2"}, + {file = "pip-24.2.tar.gz", hash = "sha256:5b5e490b5e9cb275c879595064adce9ebd31b854e3e803740b72f9ccf34a45b8"}, +] + [[package]] name = "platformdirs" version = "4.2.2" @@ -7064,6 +7271,24 @@ files = [ [package.dependencies] requests = ">=1.0.0" +[[package]] +name = "requests-oauthlib" +version = "2.0.0" +description = "OAuthlib authentication support for Requests." +optional = false +python-versions = ">=3.4" +files = [ + {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, + {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, +] + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib[signedtoken] (>=3.0.0)"] + [[package]] name = "rfc3339-validator" version = "0.1.4" @@ -7269,6 +7494,46 @@ files = [ {file = "ruff-0.0.287.tar.gz", hash = "sha256:02dc4f5bf53ef136e459d467f3ce3e04844d509bc46c025a05b018feb37bbc39"}, ] +[[package]] +name = "s3contents" +version = "0.11.2" +description = "S3 Contents Manager for Jupyter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "s3contents-0.11.2-py3-none-any.whl", hash = "sha256:ea9e7163de5224cffac9183b1c6295c7118ddaf7a801c1b26a22da1b77e4caee"}, + {file = "s3contents-0.11.2.tar.gz", hash = "sha256:9b9278a381cd4c9be3b698c2daeadc31ae5434ae9572b5609ab829eb37c68001"}, +] + +[package.dependencies] +aiobotocore = {version = ">=1.4.0", extras = ["boto3"]} +gcsfs = ">=2021.11.0" +nbconvert = ">=6.0,<8.0" +s3fs = ">=2021.11.0" + +[package.extras] +test = ["coverage[toml]", "nose", "pytest", "pytest-cov"] + +[[package]] +name = "s3fs" +version = "2024.2.0" +description = "Convenient Filesystem interface over S3" +optional = false +python-versions = ">= 3.8" +files = [ + {file = "s3fs-2024.2.0-py3-none-any.whl", hash = "sha256:c140de37175c157cb662aa6ad7423365df732ac5f10ef5bf7b76078c6333a942"}, + {file = "s3fs-2024.2.0.tar.gz", hash = "sha256:f8064f522ad088b56b043047c825734847c0269df19f2613c956d4c20de15b62"}, +] + +[package.dependencies] +aiobotocore = ">=2.5.4,<3.0.0" +aiohttp = "<4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1" +fsspec = "2024.2.0" + +[package.extras] +awscli = ["aiobotocore[awscli] (>=2.5.4,<3.0.0)"] +boto3 = ["aiobotocore[boto3] (>=2.5.4,<3.0.0)"] + [[package]] name = "s3transfer" version = "0.10.2" @@ -9726,4 +9991,4 @@ docs = ["furo", "myst-parser", "sphinx"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.9.7 || >3.9.7,<3.13" -content-hash = "b5cddff2420f18118b7ce33179a4381e316fe34622e4c9734f4954e800cf9749" +content-hash = "3eb2e550134aa74749fa637952fd5ade6d6574cd3282530b13a5b6d52725aeac" diff --git a/pyproject.toml b/pyproject.toml index 75f3d45db..6249961ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ description = "Sycamore is an LLM-powered semantic data preparation system for b authors = ["aryn.ai "] readme = "README.md" repository = "https://github.com/aryn-ai/sycamore.git" - +package-mode = false [tool.poetry.urls] "Repository" = "https://github.com/aryn-ai/sycamore.git" @@ -44,12 +44,14 @@ black = "^24.4" pre-commit = "^3.4.0" mypy = "^1.11.0" nbmake = "^1.4.5" +pip = "^24.2" [tool.poetry.group.notebook.dependencies] jupyterlab = "^4.0.11" jupyter-lsp = "^2.2.2" ipywidgets = "^8.1.0" notebook = "^7.1.2" +s3contents = "^0.11" [tool.poetry.extras] docs = ["furo", "myst-parser", "sphinx"]