From c37657929655ba846a6b48a496857f9e617016a6 Mon Sep 17 00:00:00 2001 From: Phoevos Kalemkeris Date: Tue, 19 Sep 2023 14:24:07 +0100 Subject: [PATCH] feat: Pin Python dependencies (#25) * Move notebook dependencies to `requirements.in` files * Compile dependencies into `requirements.txt` files using the root-level tox `update-requirements` action * Install dependencies from the corresponding `requirements.txt` before running each notebook Closes #24 Signed-off-by: Phoevos Kalemkeris --- requirements-fmt.txt | 6 +- requirements-lint.txt | 18 +- requirements.txt | 12 +- .../e2e-wine/e2e-wine-kfp-mlflow-seldon.ipynb | 8 +- tests/notebooks/e2e-wine/requirements.in | 13 + tests/notebooks/e2e-wine/requirements.txt | 350 ++++++++++++++++++ .../{ => katib}/katib-integration.ipynb | 6 +- tests/notebooks/katib/requirements.in | 2 + tests/notebooks/katib/requirements.txt | 68 ++++ .../notebooks/{ => kfp}/kfp-integration.ipynb | 8 +- tests/notebooks/kfp/requirements.in | 4 + tests/notebooks/kfp/requirements.txt | 177 +++++++++ .../{ => kserve}/kserve-integration.ipynb | 6 +- tests/notebooks/kserve/requirements.in | 4 + tests/notebooks/kserve/requirements.txt | 274 ++++++++++++++ .../minio-integration.ipynb | 6 +- tests/notebooks/minio/requirements.in | 3 + tests/notebooks/minio/requirements.txt | 68 ++++ .../{minio-integration => minio}/sample.csv | 0 .../{minio-integration => minio}/sample.txt | 0 .../{ => mlflow}/mlflow-integration.ipynb | 5 +- tests/notebooks/mlflow/requirements.in | 5 + tests/notebooks/mlflow/requirements.txt | 206 +++++++++++ tests/notebooks/training/requirements.in | 2 + tests/notebooks/training/requirements.txt | 66 ++++ .../{ => training}/training-integration.ipynb | 6 +- tests/test_notebooks.py | 11 +- tests/utils.py | 6 + 28 files changed, 1313 insertions(+), 27 deletions(-) create mode 100644 tests/notebooks/e2e-wine/requirements.in create mode 100644 tests/notebooks/e2e-wine/requirements.txt rename tests/notebooks/{ => katib}/katib-integration.ipynb (99%) create mode 100644 tests/notebooks/katib/requirements.in create mode 100644 tests/notebooks/katib/requirements.txt rename tests/notebooks/{ => kfp}/kfp-integration.ipynb (96%) create mode 100644 tests/notebooks/kfp/requirements.in create mode 100644 tests/notebooks/kfp/requirements.txt rename tests/notebooks/{ => kserve}/kserve-integration.ipynb (99%) create mode 100644 tests/notebooks/kserve/requirements.in create mode 100644 tests/notebooks/kserve/requirements.txt rename tests/notebooks/{minio-integration => minio}/minio-integration.ipynb (99%) create mode 100644 tests/notebooks/minio/requirements.in create mode 100644 tests/notebooks/minio/requirements.txt rename tests/notebooks/{minio-integration => minio}/sample.csv (100%) rename tests/notebooks/{minio-integration => minio}/sample.txt (100%) rename tests/notebooks/{ => mlflow}/mlflow-integration.ipynb (99%) create mode 100644 tests/notebooks/mlflow/requirements.in create mode 100644 tests/notebooks/mlflow/requirements.txt create mode 100644 tests/notebooks/training/requirements.in create mode 100644 tests/notebooks/training/requirements.txt rename tests/notebooks/{ => training}/training-integration.ipynb (99%) diff --git a/requirements-fmt.txt b/requirements-fmt.txt index 090e6eb..a0318fe 100644 --- a/requirements-fmt.txt +++ b/requirements-fmt.txt @@ -2,14 +2,14 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile ./requirements-fmt.in +# pip-compile requirements-fmt.in # black==23.7.0 - # via -r ./requirements-fmt.in + # via -r requirements-fmt.in click==8.1.6 # via black isort==5.12.0 - # via -r ./requirements-fmt.in + # via -r requirements-fmt.in mypy-extensions==1.0.0 # via black packaging==23.1 diff --git a/requirements-lint.txt b/requirements-lint.txt index 890bea0..1edc2e8 100644 --- a/requirements-lint.txt +++ b/requirements-lint.txt @@ -2,26 +2,26 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile ./requirements-lint.in +# pip-compile requirements-lint.in # black==23.7.0 - # via -r ./requirements-lint.in + # via -r requirements-lint.in click==8.1.6 # via black codespell==2.2.5 - # via -r ./requirements-lint.in + # via -r requirements-lint.in flake8==6.0.0 # via - # -r ./requirements-lint.in + # -r requirements-lint.in # flake8-builtins # pep8-naming # pyproject-flake8 flake8-builtins==2.1.0 - # via -r ./requirements-lint.in + # via -r requirements-lint.in flake8-copyright==0.2.4 - # via -r ./requirements-lint.in + # via -r requirements-lint.in isort==5.12.0 - # via -r ./requirements-lint.in + # via -r requirements-lint.in mccabe==0.7.0 # via flake8 mypy-extensions==1.0.0 @@ -31,7 +31,7 @@ packaging==23.1 pathspec==0.11.2 # via black pep8-naming==0.13.3 - # via -r ./requirements-lint.in + # via -r requirements-lint.in platformdirs==3.10.0 # via black pycodestyle==2.10.0 @@ -39,7 +39,7 @@ pycodestyle==2.10.0 pyflakes==3.0.1 # via flake8 pyproject-flake8==6.0.0.post1 - # via -r ./requirements-lint.in + # via -r requirements-lint.in tomli==2.0.1 # via # black diff --git a/requirements.txt b/requirements.txt index 447beee..0eb0550 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile ./requirements.in +# pip-compile requirements.in # anyio==3.7.1 # via httpcore @@ -63,14 +63,14 @@ jinja2==3.1.2 # via pytest-operator juju==2.9.44.0 # via - # -r ./requirements.in + # -r requirements.in # pytest-operator jujubundlelib==0.5.7 # via theblues kubernetes==27.2.0 # via juju lightkube==0.14.0 - # via -r ./requirements.in + # via -r requirements.in lightkube-models==1.27.1.4 # via lightkube macaroonbakery==1.3.1 @@ -131,13 +131,13 @@ pyrfc3339==1.1 # macaroonbakery pytest==7.4.0 # via - # -r ./requirements.in + # -r requirements.in # pytest-asyncio # pytest-operator pytest-asyncio==0.21.1 # via pytest-operator pytest-operator==0.28.0 - # via -r ./requirements.in + # via -r requirements.in python-dateutil==2.8.2 # via kubernetes pytz==2023.3 @@ -176,7 +176,7 @@ sniffio==1.3.0 stack-data==0.6.2 # via ipython tenacity==8.2.2 - # via -r ./requirements.in + # via -r requirements.in theblues==0.5.2 # via juju tomli==2.0.1 diff --git a/tests/notebooks/e2e-wine/e2e-wine-kfp-mlflow-seldon.ipynb b/tests/notebooks/e2e-wine/e2e-wine-kfp-mlflow-seldon.ipynb index ca503d6..9d39e6c 100644 --- a/tests/notebooks/e2e-wine/e2e-wine-kfp-mlflow-seldon.ipynb +++ b/tests/notebooks/e2e-wine/e2e-wine-kfp-mlflow-seldon.ipynb @@ -50,10 +50,16 @@ "execution_count": null, "id": "6e34b594", "metadata": { - "tags": [] + "tags": [ + "pytest-skip" + ] }, "outputs": [], "source": [ + "# pin kfp to the latest <2.0 version to ensure compatibility\n", + "# with the KFP API server version deployed in CKF 1.7\n", + "# pin the mlflow client to match the version of the deployed MLflow server\n", + "# pin scikit-learn to ensure compatibility with the installed mlflow client\n", "!pip install boto3 kfp==1.8.22 minio mlflow==2.1.1 numpy pyarrow requests \"scikit-learn<1.2\" tenacity -q" ] }, diff --git a/tests/notebooks/e2e-wine/requirements.in b/tests/notebooks/e2e-wine/requirements.in new file mode 100644 index 0000000..cb69b40 --- /dev/null +++ b/tests/notebooks/e2e-wine/requirements.in @@ -0,0 +1,13 @@ +boto3 +# pin to the latest <2.0 version to ensure compatibility +# with the KFP API server version deployed in CKF 1.7 +kfp==1.8.22 +minio +# pin the client to match the version of the deployed MLflow server +mlflow==2.1.1 +numpy +pyarrow +requests +# pin to ensure compatibility with the installed mlflow client +scikit-learn<1.2 +tenacity diff --git a/tests/notebooks/e2e-wine/requirements.txt b/tests/notebooks/e2e-wine/requirements.txt new file mode 100644 index 0000000..e660799 --- /dev/null +++ b/tests/notebooks/e2e-wine/requirements.txt @@ -0,0 +1,350 @@ +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile requirements.in +# +absl-py==1.4.0 + # via kfp +alembic==1.12.0 + # via mlflow +attrs==23.1.0 + # via + # jsonschema + # referencing +blinker==1.6.2 + # via flask +boto3==1.28.45 + # via -r requirements.in +botocore==1.31.45 + # via + # boto3 + # s3transfer +cachetools==5.3.1 + # via google-auth +certifi==2023.7.22 + # via + # kfp-server-api + # kubernetes + # minio + # requests +charset-normalizer==3.2.0 + # via requests +click==8.1.7 + # via + # databricks-cli + # flask + # kfp + # mlflow + # typer +cloudpickle==2.2.1 + # via + # kfp + # mlflow + # shap +contourpy==1.1.0 + # via matplotlib +cycler==0.11.0 + # via matplotlib +databricks-cli==0.17.7 + # via mlflow +deprecated==1.2.14 + # via kfp +docker==6.1.3 + # via mlflow +docstring-parser==0.15 + # via kfp +entrypoints==0.4 + # via mlflow +fire==0.5.0 + # via kfp +flask==2.3.3 + # via mlflow +fonttools==4.42.1 + # via matplotlib +gitdb==4.0.10 + # via gitpython +gitpython==3.1.36 + # via mlflow +google-api-core==2.11.1 + # via + # google-api-python-client + # google-cloud-core + # google-cloud-storage + # kfp +google-api-python-client==1.12.11 + # via kfp +google-auth==2.23.0 + # via + # google-api-core + # google-api-python-client + # google-auth-httplib2 + # google-cloud-core + # google-cloud-storage + # kfp + # kubernetes +google-auth-httplib2==0.1.1 + # via google-api-python-client +google-cloud-core==2.3.3 + # via google-cloud-storage +google-cloud-storage==2.10.0 + # via kfp +google-crc32c==1.5.0 + # via google-resumable-media +google-resumable-media==2.6.0 + # via google-cloud-storage +googleapis-common-protos==1.60.0 + # via google-api-core +greenlet==2.0.2 + # via sqlalchemy +gunicorn==20.1.0 + # via mlflow +httplib2==0.22.0 + # via + # google-api-python-client + # google-auth-httplib2 +idna==3.4 + # via requests +importlib-metadata==5.2.0 + # via + # alembic + # flask + # markdown + # mlflow + # numba +importlib-resources==6.0.1 + # via + # alembic + # jsonschema + # jsonschema-specifications + # matplotlib +itsdangerous==2.1.2 + # via flask +jinja2==3.1.2 + # via + # flask + # mlflow +jmespath==1.0.1 + # via + # boto3 + # botocore +joblib==1.3.2 + # via scikit-learn +jsonschema==4.19.0 + # via kfp +jsonschema-specifications==2023.7.1 + # via jsonschema +kfp==1.8.22 + # via -r requirements.in +kfp-pipeline-spec==0.1.16 + # via kfp +kfp-server-api==1.8.5 + # via kfp +kiwisolver==1.4.5 + # via matplotlib +kubernetes==25.3.0 + # via kfp +llvmlite==0.40.1 + # via numba +mako==1.2.4 + # via alembic +markdown==3.4.4 + # via mlflow +markupsafe==2.1.3 + # via + # jinja2 + # mako + # werkzeug +matplotlib==3.7.3 + # via mlflow +minio==7.1.16 + # via -r requirements.in +mlflow==2.1.1 + # via -r requirements.in +numba==0.57.1 + # via shap +numpy==1.24.4 + # via + # -r requirements.in + # contourpy + # matplotlib + # mlflow + # numba + # pandas + # pyarrow + # scikit-learn + # scipy + # shap +oauthlib==3.2.2 + # via + # databricks-cli + # requests-oauthlib +packaging==22.0 + # via + # docker + # matplotlib + # mlflow + # shap +pandas==1.5.3 + # via + # mlflow + # shap +pillow==10.0.0 + # via matplotlib +pkgutil-resolve-name==1.3.10 + # via jsonschema +protobuf==3.20.3 + # via + # google-api-core + # googleapis-common-protos + # kfp + # kfp-pipeline-spec + # mlflow +pyarrow==10.0.1 + # via + # -r requirements.in + # mlflow +pyasn1==0.5.0 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.3.0 + # via google-auth +pydantic==1.10.12 + # via kfp +pyjwt==2.8.0 + # via databricks-cli +pyparsing==3.1.1 + # via + # httplib2 + # matplotlib +python-dateutil==2.8.2 + # via + # botocore + # kfp-server-api + # kubernetes + # matplotlib + # pandas +pytz==2022.7.1 + # via + # mlflow + # pandas +pyyaml==6.0.1 + # via + # kfp + # kubernetes + # mlflow +querystring-parser==1.2.4 + # via mlflow +referencing==0.30.2 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # -r requirements.in + # databricks-cli + # docker + # google-api-core + # google-cloud-storage + # kubernetes + # mlflow + # requests-oauthlib + # requests-toolbelt +requests-oauthlib==1.3.1 + # via kubernetes +requests-toolbelt==0.10.1 + # via kfp +rpds-py==0.10.2 + # via + # jsonschema + # referencing +rsa==4.9 + # via google-auth +s3transfer==0.6.2 + # via boto3 +scikit-learn==1.1.3 + # via + # -r requirements.in + # mlflow + # shap +scipy==1.10.1 + # via + # mlflow + # scikit-learn + # shap +shap==0.42.1 + # via mlflow +six==1.16.0 + # via + # databricks-cli + # fire + # google-api-python-client + # kfp-server-api + # kubernetes + # python-dateutil + # querystring-parser +slicer==0.0.7 + # via shap +smmap==5.0.0 + # via gitdb +sqlalchemy==1.4.49 + # via + # alembic + # mlflow +sqlparse==0.4.4 + # via mlflow +strip-hints==0.1.10 + # via kfp +tabulate==0.9.0 + # via + # databricks-cli + # kfp +tenacity==8.2.3 + # via -r requirements.in +termcolor==2.3.0 + # via fire +threadpoolctl==3.2.0 + # via scikit-learn +tqdm==4.66.1 + # via shap +typer==0.9.0 + # via kfp +typing-extensions==4.7.1 + # via + # alembic + # kfp + # pydantic + # typer +uritemplate==3.0.1 + # via + # google-api-python-client + # kfp +urllib3==1.26.16 + # via + # botocore + # databricks-cli + # docker + # google-auth + # kfp + # kfp-server-api + # kubernetes + # minio + # requests +websocket-client==1.6.3 + # via + # docker + # kubernetes +werkzeug==2.3.7 + # via flask +wheel==0.41.2 + # via strip-hints +wrapt==1.15.0 + # via deprecated +zipp==3.16.2 + # via + # importlib-metadata + # importlib-resources + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/tests/notebooks/katib-integration.ipynb b/tests/notebooks/katib/katib-integration.ipynb similarity index 99% rename from tests/notebooks/katib-integration.ipynb rename to tests/notebooks/katib/katib-integration.ipynb index 0ab2a38..570b00e 100644 --- a/tests/notebooks/katib-integration.ipynb +++ b/tests/notebooks/katib/katib-integration.ipynb @@ -26,7 +26,11 @@ { "cell_type": "code", "execution_count": 1, - "metadata": {}, + "metadata": { + "tags": [ + "pytest-skip" + ] + }, "outputs": [], "source": [ "!pip install kubeflow-katib tenacity -q" diff --git a/tests/notebooks/katib/requirements.in b/tests/notebooks/katib/requirements.in new file mode 100644 index 0000000..ea10ae9 --- /dev/null +++ b/tests/notebooks/katib/requirements.in @@ -0,0 +1,2 @@ +kubeflow-katib +tenacity diff --git a/tests/notebooks/katib/requirements.txt b/tests/notebooks/katib/requirements.txt new file mode 100644 index 0000000..fa437af --- /dev/null +++ b/tests/notebooks/katib/requirements.txt @@ -0,0 +1,68 @@ +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile requirements.in +# +cachetools==5.3.1 + # via google-auth +certifi==2023.7.22 + # via + # kubeflow-katib + # kubernetes + # requests +charset-normalizer==3.2.0 + # via requests +google-auth==2.23.0 + # via kubernetes +grpcio==1.41.1 + # via kubeflow-katib +idna==3.4 + # via requests +kubeflow-katib==0.15.0 + # via -r requirements.in +kubernetes==27.2.0 + # via kubeflow-katib +oauthlib==3.2.2 + # via + # kubernetes + # requests-oauthlib +protobuf==3.19.5 + # via kubeflow-katib +pyasn1==0.5.0 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.3.0 + # via google-auth +python-dateutil==2.8.2 + # via kubernetes +pyyaml==6.0.1 + # via kubernetes +requests==2.31.0 + # via + # kubernetes + # requests-oauthlib +requests-oauthlib==1.3.1 + # via kubernetes +rsa==4.9 + # via google-auth +six==1.16.0 + # via + # grpcio + # kubeflow-katib + # kubernetes + # python-dateutil +tenacity==8.2.3 + # via -r requirements.in +urllib3==1.26.16 + # via + # google-auth + # kubeflow-katib + # kubernetes + # requests +websocket-client==1.6.3 + # via kubernetes + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/tests/notebooks/kfp-integration.ipynb b/tests/notebooks/kfp/kfp-integration.ipynb similarity index 96% rename from tests/notebooks/kfp-integration.ipynb rename to tests/notebooks/kfp/kfp-integration.ipynb index 92affee..b571117 100644 --- a/tests/notebooks/kfp-integration.ipynb +++ b/tests/notebooks/kfp/kfp-integration.ipynb @@ -16,9 +16,15 @@ "cell_type": "code", "execution_count": 1, "id": "28f75e55-7bad-44e7-a65f-aedc81734a48", - "metadata": {}, + "metadata": { + "tags": [ + "pytest-skip" + ] + }, "outputs": [], "source": [ + "# pin kfp to the latest <2.0 version to ensure compatibility\n", + "# with the KFP API server version deployed in CKF 1.7\n", "!pip install kfp==1.8.22 tenacity -q" ] }, diff --git a/tests/notebooks/kfp/requirements.in b/tests/notebooks/kfp/requirements.in new file mode 100644 index 0000000..d0dfb0f --- /dev/null +++ b/tests/notebooks/kfp/requirements.in @@ -0,0 +1,4 @@ +# pin to the latest <2.0 version to ensure compatibility +# with the KFP API server version deployed in CKF 1.7 +kfp==1.8.22 +tenacity diff --git a/tests/notebooks/kfp/requirements.txt b/tests/notebooks/kfp/requirements.txt new file mode 100644 index 0000000..72cb1c2 --- /dev/null +++ b/tests/notebooks/kfp/requirements.txt @@ -0,0 +1,177 @@ +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile requirements.in +# +absl-py==1.4.0 + # via kfp +attrs==23.1.0 + # via + # jsonschema + # referencing +cachetools==5.3.1 + # via google-auth +certifi==2023.7.22 + # via + # kfp-server-api + # kubernetes + # requests +charset-normalizer==3.2.0 + # via requests +click==8.1.7 + # via + # kfp + # typer +cloudpickle==2.2.1 + # via kfp +deprecated==1.2.14 + # via kfp +docstring-parser==0.15 + # via kfp +fire==0.5.0 + # via kfp +google-api-core==2.11.1 + # via + # google-api-python-client + # google-cloud-core + # google-cloud-storage + # kfp +google-api-python-client==1.12.11 + # via kfp +google-auth==2.23.0 + # via + # google-api-core + # google-api-python-client + # google-auth-httplib2 + # google-cloud-core + # google-cloud-storage + # kfp + # kubernetes +google-auth-httplib2==0.1.1 + # via google-api-python-client +google-cloud-core==2.3.3 + # via google-cloud-storage +google-cloud-storage==2.10.0 + # via kfp +google-crc32c==1.5.0 + # via google-resumable-media +google-resumable-media==2.6.0 + # via google-cloud-storage +googleapis-common-protos==1.60.0 + # via google-api-core +httplib2==0.22.0 + # via + # google-api-python-client + # google-auth-httplib2 +idna==3.4 + # via requests +importlib-resources==6.0.1 + # via + # jsonschema + # jsonschema-specifications +jsonschema==4.19.0 + # via kfp +jsonschema-specifications==2023.7.1 + # via jsonschema +kfp==1.8.22 + # via -r requirements.in +kfp-pipeline-spec==0.1.16 + # via kfp +kfp-server-api==1.8.5 + # via kfp +kubernetes==25.3.0 + # via kfp +oauthlib==3.2.2 + # via requests-oauthlib +pkgutil-resolve-name==1.3.10 + # via jsonschema +protobuf==3.20.3 + # via + # google-api-core + # googleapis-common-protos + # kfp + # kfp-pipeline-spec +pyasn1==0.5.0 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.3.0 + # via google-auth +pydantic==1.10.12 + # via kfp +pyparsing==3.1.1 + # via httplib2 +python-dateutil==2.8.2 + # via + # kfp-server-api + # kubernetes +pyyaml==6.0.1 + # via + # kfp + # kubernetes +referencing==0.30.2 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # google-api-core + # google-cloud-storage + # kubernetes + # requests-oauthlib + # requests-toolbelt +requests-oauthlib==1.3.1 + # via kubernetes +requests-toolbelt==0.10.1 + # via kfp +rpds-py==0.10.2 + # via + # jsonschema + # referencing +rsa==4.9 + # via google-auth +six==1.16.0 + # via + # fire + # google-api-python-client + # kfp-server-api + # kubernetes + # python-dateutil +strip-hints==0.1.10 + # via kfp +tabulate==0.9.0 + # via kfp +tenacity==8.2.3 + # via -r requirements.in +termcolor==2.3.0 + # via fire +typer==0.9.0 + # via kfp +typing-extensions==4.7.1 + # via + # kfp + # pydantic + # typer +uritemplate==3.0.1 + # via + # google-api-python-client + # kfp +urllib3==1.26.16 + # via + # google-auth + # kfp + # kfp-server-api + # kubernetes + # requests +websocket-client==1.6.3 + # via kubernetes +wheel==0.41.2 + # via strip-hints +wrapt==1.15.0 + # via deprecated +zipp==3.16.2 + # via importlib-resources + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/tests/notebooks/kserve-integration.ipynb b/tests/notebooks/kserve/kserve-integration.ipynb similarity index 99% rename from tests/notebooks/kserve-integration.ipynb rename to tests/notebooks/kserve/kserve-integration.ipynb index 0a69a81..e06db45 100644 --- a/tests/notebooks/kserve-integration.ipynb +++ b/tests/notebooks/kserve/kserve-integration.ipynb @@ -25,7 +25,11 @@ "cell_type": "code", "execution_count": 1, "id": "9fbb8bc8-0eb0-4853-bef6-e2098eb2829c", - "metadata": {}, + "metadata": { + "tags": [ + "pytest-skip" + ] + }, "outputs": [], "source": [ "!pip install kserve kubernetes requests tenacity -q" diff --git a/tests/notebooks/kserve/requirements.in b/tests/notebooks/kserve/requirements.in new file mode 100644 index 0000000..582d366 --- /dev/null +++ b/tests/notebooks/kserve/requirements.in @@ -0,0 +1,4 @@ +kserve +kubernetes +requests +tenacity diff --git a/tests/notebooks/kserve/requirements.txt b/tests/notebooks/kserve/requirements.txt new file mode 100644 index 0000000..2210058 --- /dev/null +++ b/tests/notebooks/kserve/requirements.txt @@ -0,0 +1,274 @@ +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile requirements.in +# +aiohttp==3.8.5 + # via + # aiohttp-cors + # ray +aiohttp-cors==0.7.0 + # via ray +aiorwlock==1.3.0 + # via ray +aiosignal==1.3.1 + # via + # aiohttp + # ray +anyio==4.0.0 + # via + # httpcore + # starlette + # watchfiles +async-timeout==4.0.3 + # via aiohttp +attrs==23.1.0 + # via + # aiohttp + # jsonschema + # ray + # referencing +blessed==1.20.0 + # via gpustat +cachetools==5.3.1 + # via google-auth +certifi==2023.7.22 + # via + # httpcore + # httpx + # kubernetes + # requests +charset-normalizer==3.2.0 + # via + # aiohttp + # requests +click==8.1.7 + # via + # ray + # uvicorn +cloudevents==1.9.0 + # via kserve +colorful==0.5.5 + # via ray +cuda-python==12.2.0 + # via tritonclient +cython==3.0.2 + # via cuda-python +deprecation==2.1.0 + # via cloudevents +distlib==0.3.7 + # via virtualenv +exceptiongroup==1.1.3 + # via anyio +fastapi==0.95.2 + # via + # kserve + # ray +filelock==3.12.3 + # via + # ray + # virtualenv +frozenlist==1.4.0 + # via + # aiohttp + # aiosignal + # ray +google-api-core==2.11.1 + # via opencensus +google-auth==2.23.0 + # via + # google-api-core + # kubernetes +googleapis-common-protos==1.60.0 + # via google-api-core +gpustat==1.1.1 + # via ray +grpcio==1.51.3 + # via + # kserve + # ray +h11==0.14.0 + # via + # httpcore + # uvicorn +httpcore==0.16.3 + # via httpx +httptools==0.6.0 + # via uvicorn +httpx==0.23.3 + # via kserve +idna==3.4 + # via + # anyio + # requests + # rfc3986 + # yarl +importlib-resources==6.0.1 + # via + # jsonschema + # jsonschema-specifications +jsonschema==4.19.0 + # via ray +jsonschema-specifications==2023.7.1 + # via jsonschema +kserve==0.11.0 + # via -r requirements.in +kubernetes==27.2.0 + # via + # -r requirements.in + # kserve +msgpack==1.0.5 + # via ray +multidict==6.0.4 + # via + # aiohttp + # yarl +numpy==1.24.4 + # via + # kserve + # pandas + # ray + # tritonclient +nvidia-ml-py==12.535.108 + # via gpustat +oauthlib==3.2.2 + # via + # kubernetes + # requests-oauthlib +opencensus==0.11.2 + # via ray +opencensus-context==0.1.3 + # via opencensus +orjson==3.9.7 + # via kserve +packaging==23.1 + # via deprecation +pandas==2.0.3 + # via kserve +pkgutil-resolve-name==1.3.10 + # via jsonschema +platformdirs==3.10.0 + # via virtualenv +prometheus-client==0.13.1 + # via + # kserve + # ray +protobuf==3.20.3 + # via + # google-api-core + # googleapis-common-protos + # kserve + # ray +psutil==5.9.5 + # via + # gpustat + # kserve +py-spy==0.3.14 + # via ray +pyasn1==0.5.0 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.3.0 + # via google-auth +pydantic==1.10.12 + # via + # fastapi + # ray +python-dateutil==2.8.2 + # via + # kserve + # kubernetes + # pandas +python-dotenv==1.0.0 + # via uvicorn +python-rapidjson==1.11 + # via tritonclient +pytz==2023.3.post1 + # via pandas +pyyaml==6.0.1 + # via + # kubernetes + # ray + # uvicorn +ray[serve]==2.4.0 + # via kserve +referencing==0.30.2 + # via + # jsonschema + # jsonschema-specifications +requests==2.31.0 + # via + # -r requirements.in + # google-api-core + # kubernetes + # ray + # requests-oauthlib +requests-oauthlib==1.3.1 + # via kubernetes +rfc3986[idna2008]==1.5.0 + # via httpx +rpds-py==0.10.2 + # via + # jsonschema + # referencing +rsa==4.9 + # via google-auth +six==1.16.0 + # via + # blessed + # kserve + # kubernetes + # python-dateutil +smart-open==6.4.0 + # via ray +sniffio==1.3.0 + # via + # anyio + # httpcore + # httpx +starlette==0.27.0 + # via + # fastapi + # ray +tabulate==0.9.0 + # via kserve +tenacity==8.2.3 + # via -r requirements.in +timing-asgi==0.3.1 + # via kserve +tritonclient==2.37.0.9383150 + # via kserve +typing-extensions==4.7.1 + # via + # filelock + # pydantic + # starlette +tzdata==2023.3 + # via pandas +urllib3==1.26.16 + # via + # google-auth + # kubernetes + # requests +uvicorn[standard]==0.19.0 + # via + # kserve + # ray +uvloop==0.17.0 + # via uvicorn +virtualenv==20.21.0 + # via ray +watchfiles==0.20.0 + # via uvicorn +wcwidth==0.2.6 + # via blessed +websocket-client==1.6.3 + # via kubernetes +websockets==11.0.3 + # via uvicorn +yarl==1.9.2 + # via aiohttp +zipp==3.16.2 + # via importlib-resources diff --git a/tests/notebooks/minio-integration/minio-integration.ipynb b/tests/notebooks/minio/minio-integration.ipynb similarity index 99% rename from tests/notebooks/minio-integration/minio-integration.ipynb rename to tests/notebooks/minio/minio-integration.ipynb index bfd222c..2825bcf 100644 --- a/tests/notebooks/minio-integration/minio-integration.ipynb +++ b/tests/notebooks/minio/minio-integration.ipynb @@ -27,7 +27,11 @@ "cell_type": "code", "execution_count": 1, "id": "03ddcaea-c3b6-4fe7-830f-a1f52a812319", - "metadata": {}, + "metadata": { + "tags": [ + "pytest-skip" + ] + }, "outputs": [ { "name": "stdout", diff --git a/tests/notebooks/minio/requirements.in b/tests/notebooks/minio/requirements.in new file mode 100644 index 0000000..c172259 --- /dev/null +++ b/tests/notebooks/minio/requirements.in @@ -0,0 +1,3 @@ +minio +pandas +s3fs diff --git a/tests/notebooks/minio/requirements.txt b/tests/notebooks/minio/requirements.txt new file mode 100644 index 0000000..cab674b --- /dev/null +++ b/tests/notebooks/minio/requirements.txt @@ -0,0 +1,68 @@ +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile requirements.in +# +aiobotocore==2.5.4 + # via s3fs +aiohttp==3.8.5 + # via + # aiobotocore + # s3fs +aioitertools==0.11.0 + # via aiobotocore +aiosignal==1.3.1 + # via aiohttp +async-timeout==4.0.3 + # via aiohttp +attrs==23.1.0 + # via aiohttp +botocore==1.31.17 + # via aiobotocore +certifi==2023.7.22 + # via minio +charset-normalizer==3.2.0 + # via aiohttp +frozenlist==1.4.0 + # via + # aiohttp + # aiosignal +fsspec==2023.9.0 + # via s3fs +idna==3.4 + # via yarl +jmespath==1.0.1 + # via botocore +minio==7.1.16 + # via -r requirements.in +multidict==6.0.4 + # via + # aiohttp + # yarl +numpy==1.24.4 + # via pandas +pandas==2.0.3 + # via -r requirements.in +python-dateutil==2.8.2 + # via + # botocore + # pandas +pytz==2023.3.post1 + # via pandas +s3fs==2023.9.0 + # via -r requirements.in +six==1.16.0 + # via python-dateutil +typing-extensions==4.7.1 + # via aioitertools +tzdata==2023.3 + # via pandas +urllib3==1.26.16 + # via + # botocore + # minio +wrapt==1.15.0 + # via aiobotocore +yarl==1.9.2 + # via aiohttp diff --git a/tests/notebooks/minio-integration/sample.csv b/tests/notebooks/minio/sample.csv similarity index 100% rename from tests/notebooks/minio-integration/sample.csv rename to tests/notebooks/minio/sample.csv diff --git a/tests/notebooks/minio-integration/sample.txt b/tests/notebooks/minio/sample.txt similarity index 100% rename from tests/notebooks/minio-integration/sample.txt rename to tests/notebooks/minio/sample.txt diff --git a/tests/notebooks/mlflow-integration.ipynb b/tests/notebooks/mlflow/mlflow-integration.ipynb similarity index 99% rename from tests/notebooks/mlflow-integration.ipynb rename to tests/notebooks/mlflow/mlflow-integration.ipynb index ee198cf..7c16d12 100644 --- a/tests/notebooks/mlflow-integration.ipynb +++ b/tests/notebooks/mlflow/mlflow-integration.ipynb @@ -18,10 +18,13 @@ "execution_count": 1, "id": "opening-plate", "metadata": { - "tags": [] + "tags": [ + "pytest-skip" + ] }, "outputs": [], "source": [ + "# pin the mlflow client to match the version of the deployed MLflow server\n", "!pip install minio mlflow==2.1.1 boto3 tenacity -q" ] }, diff --git a/tests/notebooks/mlflow/requirements.in b/tests/notebooks/mlflow/requirements.in new file mode 100644 index 0000000..9830916 --- /dev/null +++ b/tests/notebooks/mlflow/requirements.in @@ -0,0 +1,5 @@ +boto3 +minio +# pin the client to match the version of the deployed MLflow server +mlflow==2.1.1 +tenacity diff --git a/tests/notebooks/mlflow/requirements.txt b/tests/notebooks/mlflow/requirements.txt new file mode 100644 index 0000000..bbf2882 --- /dev/null +++ b/tests/notebooks/mlflow/requirements.txt @@ -0,0 +1,206 @@ +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile requirements.in +# +alembic==1.12.0 + # via mlflow +blinker==1.6.2 + # via flask +boto3==1.28.45 + # via -r requirements.in +botocore==1.31.45 + # via + # boto3 + # s3transfer +certifi==2023.7.22 + # via + # minio + # requests +charset-normalizer==3.2.0 + # via requests +click==8.1.7 + # via + # databricks-cli + # flask + # mlflow +cloudpickle==2.2.1 + # via + # mlflow + # shap +contourpy==1.1.0 + # via matplotlib +cycler==0.11.0 + # via matplotlib +databricks-cli==0.17.7 + # via mlflow +docker==6.1.3 + # via mlflow +entrypoints==0.4 + # via mlflow +flask==2.3.3 + # via mlflow +fonttools==4.42.1 + # via matplotlib +gitdb==4.0.10 + # via gitpython +gitpython==3.1.36 + # via mlflow +greenlet==2.0.2 + # via sqlalchemy +gunicorn==20.1.0 + # via mlflow +idna==3.4 + # via requests +importlib-metadata==5.2.0 + # via + # alembic + # flask + # markdown + # mlflow + # numba +importlib-resources==6.0.1 + # via + # alembic + # matplotlib +itsdangerous==2.1.2 + # via flask +jinja2==3.1.2 + # via + # flask + # mlflow +jmespath==1.0.1 + # via + # boto3 + # botocore +joblib==1.3.2 + # via scikit-learn +kiwisolver==1.4.5 + # via matplotlib +llvmlite==0.40.1 + # via numba +mako==1.2.4 + # via alembic +markdown==3.4.4 + # via mlflow +markupsafe==2.1.3 + # via + # jinja2 + # mako + # werkzeug +matplotlib==3.7.3 + # via mlflow +minio==7.1.16 + # via -r requirements.in +mlflow==2.1.1 + # via -r requirements.in +numba==0.57.1 + # via shap +numpy==1.24.4 + # via + # contourpy + # matplotlib + # mlflow + # numba + # pandas + # pyarrow + # scikit-learn + # scipy + # shap +oauthlib==3.2.2 + # via databricks-cli +packaging==22.0 + # via + # docker + # matplotlib + # mlflow + # shap +pandas==1.5.3 + # via + # mlflow + # shap +pillow==10.0.0 + # via matplotlib +protobuf==4.24.3 + # via mlflow +pyarrow==10.0.1 + # via mlflow +pyjwt==2.8.0 + # via databricks-cli +pyparsing==3.1.1 + # via matplotlib +python-dateutil==2.8.2 + # via + # botocore + # matplotlib + # pandas +pytz==2022.7.1 + # via + # mlflow + # pandas +pyyaml==6.0.1 + # via mlflow +querystring-parser==1.2.4 + # via mlflow +requests==2.31.0 + # via + # databricks-cli + # docker + # mlflow +s3transfer==0.6.2 + # via boto3 +scikit-learn==1.3.0 + # via + # mlflow + # shap +scipy==1.10.1 + # via + # mlflow + # scikit-learn + # shap +shap==0.42.1 + # via mlflow +six==1.16.0 + # via + # databricks-cli + # python-dateutil + # querystring-parser +slicer==0.0.7 + # via shap +smmap==5.0.0 + # via gitdb +sqlalchemy==1.4.49 + # via + # alembic + # mlflow +sqlparse==0.4.4 + # via mlflow +tabulate==0.9.0 + # via databricks-cli +tenacity==8.2.3 + # via -r requirements.in +threadpoolctl==3.2.0 + # via scikit-learn +tqdm==4.66.1 + # via shap +typing-extensions==4.7.1 + # via alembic +urllib3==1.26.16 + # via + # botocore + # databricks-cli + # docker + # minio + # requests +websocket-client==1.6.3 + # via docker +werkzeug==2.3.7 + # via flask +zipp==3.16.2 + # via + # importlib-metadata + # importlib-resources + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/tests/notebooks/training/requirements.in b/tests/notebooks/training/requirements.in new file mode 100644 index 0000000..505fcc5 --- /dev/null +++ b/tests/notebooks/training/requirements.in @@ -0,0 +1,2 @@ +kubeflow-training +tenacity diff --git a/tests/notebooks/training/requirements.txt b/tests/notebooks/training/requirements.txt new file mode 100644 index 0000000..5257004 --- /dev/null +++ b/tests/notebooks/training/requirements.txt @@ -0,0 +1,66 @@ +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile requirements.in +# +cachetools==5.3.1 + # via google-auth +certifi==2023.7.22 + # via + # kubeflow-training + # kubernetes + # requests +charset-normalizer==3.2.0 + # via requests +google-auth==2.23.0 + # via kubernetes +idna==3.4 + # via requests +kubeflow-training==1.6.0 + # via -r requirements.in +kubernetes==27.2.0 + # via kubeflow-training +oauthlib==3.2.2 + # via + # kubernetes + # requests-oauthlib +pyasn1==0.5.0 + # via + # pyasn1-modules + # rsa +pyasn1-modules==0.3.0 + # via google-auth +python-dateutil==2.8.2 + # via kubernetes +pyyaml==6.0.1 + # via kubernetes +requests==2.31.0 + # via + # kubernetes + # requests-oauthlib +requests-oauthlib==1.3.1 + # via kubernetes +retrying==1.3.4 + # via kubeflow-training +rsa==4.9 + # via google-auth +six==1.16.0 + # via + # kubeflow-training + # kubernetes + # python-dateutil + # retrying +tenacity==8.2.3 + # via -r requirements.in +urllib3==1.26.16 + # via + # google-auth + # kubeflow-training + # kubernetes + # requests +websocket-client==1.6.3 + # via kubernetes + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/tests/notebooks/training-integration.ipynb b/tests/notebooks/training/training-integration.ipynb similarity index 99% rename from tests/notebooks/training-integration.ipynb rename to tests/notebooks/training/training-integration.ipynb index d43bcdc..ed81a3b 100644 --- a/tests/notebooks/training-integration.ipynb +++ b/tests/notebooks/training/training-integration.ipynb @@ -24,7 +24,11 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [ + "pytest-skip" + ] + }, "outputs": [], "source": [ "!pip install kubeflow-training tenacity -q" diff --git a/tests/test_notebooks.py b/tests/test_notebooks.py index 44777af..9880018 100644 --- a/tests/test_notebooks.py +++ b/tests/test_notebooks.py @@ -8,7 +8,12 @@ import pytest from nbclient.exceptions import CellExecutionError from nbconvert.preprocessors import ExecutePreprocessor -from utils import discover_notebooks, format_error_message, save_notebook +from utils import ( + discover_notebooks, + format_error_message, + install_python_requirements, + save_notebook, +) EXAMPLES_DIR = "notebooks" NOTEBOOKS = discover_notebooks(EXAMPLES_DIR) @@ -30,7 +35,9 @@ def test_notebook(test_notebook): with open(test_notebook) as nb: notebook = nbformat.read(nb, as_version=nbformat.NO_CONVERT) - ep = ExecutePreprocessor(timeout=-1, kernel_name="python3") + ep = ExecutePreprocessor( + timeout=-1, kernel_name="python3", on_notebook_start=install_python_requirements + ) ep.skip_cells_with_tag = "pytest-skip" try: diff --git a/tests/utils.py b/tests/utils.py index 8443548..c532fec 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,10 +2,16 @@ # See LICENSE file for licensing details. import os +import subprocess import nbformat +def install_python_requirements(requirements_file: str = "requirements.txt", *args, **kwargs): + """Install Python dependencies specified in the provided requirements file.""" + subprocess.run(["pip", "install", "-r", requirements_file]) + + def format_error_message(traceback: list): """Format error message.""" return "".join(traceback[-2:])