diff --git a/.flake8 b/.flake8 index 4599eaac..72bac135 100644 --- a/.flake8 +++ b/.flake8 @@ -7,3 +7,4 @@ exclude = .git,__pycache__,.nox,docs/source/conf.py,old,build,dist,configs/ipyth per-file-ignores = # imported but unused __init__.py: F401 + scripts/check_toolkit_imports.py: F401 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aca103a0..76660374 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -433,6 +433,46 @@ jobs: path: coverage-data/coverage.xml retention-days: 30 + # Other jobs take the toolkit's dependencies from poetry.lock; this one resolves + # the wheel's own requirements, as `pip install deepnote-toolkit` does for users. + wheel-install-check: + name: Wheel Install Check - Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] + steps: + - name: Checkout code + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + with: + fetch-depth: 0 + fetch-tags: true + persist-credentials: false + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install Poetry + uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1 + with: + version: ${{ env.POETRY_VERSION }} + + - name: Build wheel + id: build + uses: ./.github/actions/build-wheel + + - name: Install wheel without the lock and import the toolkit + env: + WHEEL_PATH: ${{ steps.build.outputs.wheel-path }} + run: | + python -m venv /tmp/smoke + /tmp/smoke/bin/python -m pip install "${WHEEL_PATH}[server]" + /tmp/smoke/bin/python scripts/check_toolkit_imports.py + audit-prod: name: Audit - Production runs-on: ubuntu-latest diff --git a/poetry.lock b/poetry.lock index ef5df170..c4b784c6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -9458,4 +9458,4 @@ server = ["deepnote-python-lsp-server", "jupyter-resource-usage", "jupyter-serve [metadata] lock-version = "2.1" python-versions = ">=3.10.0,<3.15" -content-hash = "04a325f38a272beccf64959c3054ef9764fcbc230fcf8f2c6ce1aa57e94977aa" +content-hash = "7c9e1e2316e450b768c48877b533b5b5ad2399666880f5d236c40fb89d3197ff" diff --git a/pyproject.toml b/pyproject.toml index 636e11ef..d78bee64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,8 @@ dependencies = [ "pyarrow>=16.0.0,<18.0.0; python_version == '3.10' and sys_platform == 'darwin'", "pyarrow>=13.0.0,<=17.0.0; python_version == '3.11' and sys_platform != 'darwin'", "pyarrow>=16.0.0,<=18.0.0; python_version == '3.11' and sys_platform == 'darwin'", - "pyarrow>=23.0.1; python_version == '3.12'", # 23.0.1 patches CVE-2026-25087 (GHSA-rgxp-2hwp-jwgg) + # pyarrow 26 requires NumPy 2 at import time without declaring it, and 3.12 is on numpy<2. + "pyarrow>=23.0.1,<26; python_version == '3.12'", "pyarrow>=23.0.1; python_version >= '3.13'", # 3.10/3.11 stay <17 via databricks-sqlalchemy 1.x (SQLAlchemy 1.x compat) "db-dtypes>=1.2.0,<1.4", diff --git a/scripts/check_toolkit_imports.py b/scripts/check_toolkit_imports.py new file mode 100644 index 00000000..052d13e2 --- /dev/null +++ b/scripts/check_toolkit_imports.py @@ -0,0 +1,32 @@ +"""Import every name deepnote_toolkit/__init__.py loads, so a broken dependency fails.""" + +import deepnote_toolkit +from deepnote_toolkit import artifacts, experimental_components, ocelots +from deepnote_toolkit.artifacts import delete_dataframe, store_dataframe +from deepnote_toolkit.chart import DeepnoteChart +from deepnote_toolkit.dataframe_utils import browse_dataframe +from deepnote_toolkit.execute_post_start_hooks import execute_post_start_hooks +from deepnote_toolkit.notebook_functions import ( + cancel_notebook_function, + export_last_block_result, + run_notebook_function, +) +from deepnote_toolkit.runtime_initialization import init_deepnote_runtime +from deepnote_toolkit.session_persistence import ( + persist_notebook_session, + restore_notebook_session, +) +from deepnote_toolkit.set_integrations_env import set_integration_env +from deepnote_toolkit.set_notebook_path import set_notebook_path +from deepnote_toolkit.sql.query_preview import DeepnoteQueryPreview +from deepnote_toolkit.sql.sql_execution import ( + execute_sql, + execute_sql_with_connection_json, +) +from deepnote_toolkit.variable_explorer import ( + deepnote_export_df, + deepnote_get_data_preview_json, + get_var_list, +) + +print(f"Imported deepnote_toolkit from {deepnote_toolkit.__file__}")