Layout and media

Python

Add a python panel when SQL cannot express the compute: a statistics routine, a custom transform, or a chart matplotlib can draw and ECharts cannot.

What you can do

  • code is Python that defines def main(session, <params…>); dvt runs it on your Snowflake warehouse as an anonymous Snowpark procedure under the connection's own identity (the viewer's rights under caller's rights, the shared service identity on a service connection), never owner's rights, so it grants no privilege a SQL panel on that connection lacks.
  • params declare string, number, or boolean arguments, bound by name from filter and drill values exactly like a SQL panel's data.params, one CALL argument each in declared order; a python panel accepts no onClick but can be a filter or drill target through its own params.
  • packages is a closed allow-list (pandas, numpy, matplotlib, scipy, pyarrow, openpyxl); snowflake-snowpark-python is implicit. code is capped at 1 MiB of UTF-8 bytes and may not contain $$.
  • output is table (default, a DataFrame), value (a scalar), or image (a base64 PNG); presentation reuses the existing table-column and KPI-tile vocabulary and adds no keys of its own.
  • Authoring needs the python:author capability and a Snowflake data.sourceId; viewing needs only dashboard:read. Execution sits behind the pythonPanels deployment switch, on in every edition as an operator kill switch, with a floor of roughly four to six seconds per run.

Applies to a python panel on a Snowflake source only. POST /v1/data/query executes the code and returns a real table, value, or image result today; the in-app renderer and code editor land with DVT-4260, so until then a python panel shows nothing on the SPA, exports, and renders.

Spec

View spec
{
  "id": "revenue-by-category",
  "type": "python",
  "title": "Revenue by category, orders over the floor",
  "data": {
    "sourceId": "snowflake_db"
  },
  "spec": {
    "code": "def main(session, min_amount): return session.sql('SELECT category, SUM(amount) AS revenue FROM analytics.public.orders WHERE amount >= ? GROUP BY 1 ORDER BY 2 DESC', params=[min_amount]).to_pandas()",
    "params": {
      "min_amount": {
        "type": "number"
      }
    },
    "packages": [
      "pandas"
    ],
    "output": "table"
  }
}

main takes session first and then one argument per declared params key; min_amount arrives as a CALL argument, so the SQL inside uses a ? bind rather than string formatting.

Build it in dvt

Every block on this page is a few lines of the same declarative JSON spec. Read the full spec format, or connect an AI agent to your warehouse and build one live in the quickstart.

Follow the build

dvt is in founding research. Leave your email and we'll reach out when there's something to see — no newsletters, no noise.

No spam. We use this to reach out directly, nothing else.