Files
vercel__workflow/workbench/python/pyproject.toml
Fantix King 09b299a03e [e2e] Add Python e2e Test (#3369)
Turns `packages/core/e2e/e2e.test.ts` into a cross-language conformance
suite and adds `workbench/python` as its first non-JavaScript subject.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 16:56:05 -04:00

92 lines
4.9 KiB
TOML

[project]
name = "workflow-example-python"
version = "0.0.0"
description = "Python conformance target for the @workflow/core e2e suite"
requires-python = ">=3.10"
dependencies = [
# The only thing imported here is `vercel.workflow`, which as of vercel-py#299
# is its own `vercel-workflow` distribution — but depending on *that* directly
# is what takes the Vercel lane down. `@vercel/python` picks queue mode over
# workers mode by looking for the literal name `vercel` in this list
# (`hasExplicitVercelSdkDependency`) and then probing
# `importlib.metadata.version("vercel")`; neither has heard of the split, up
# to and including 6.56.2. With no match it silently serves workflows through
# vercel-workers: the trigger becomes `__wkf_*` / consumer `app_registry`
# instead of `__wkf_workflow_*` / consumer `default`, so nothing the
# TypeScript driver enqueues is ever delivered and every run times out having
# logged zero requests. Depend on the umbrella package and let it pull the
# runtime (it requires `vercel-workflow>=0.9.0,<1.1.0`) until the builder
# learns the new name.
#
# `cryptography` now comes along outright rather than behind the `encryption`
# extra this app used to have to ask for. It is not optional either way: on
# Vercel the run input is written by the TypeScript driver and
# `@workflow/world-vercel` encrypts it whenever it can resolve a per-run key,
# which on a deployment it always can, with no opt-out.
"vercel",
# vercel-py carries uvicorn as a dev-only dependency, so declare it here.
"uvicorn>=0.30",
]
# Pinned to a vercel-py commit rather than a release: this app tracks the
# Python SDK's `main` so the conformance suite reports on what is actually
# being built. Bump `rev` deliberately, and re-run the suite when you do.
#
# `subdirectory` is required — the vercel-py repo root is a uv workspace whose
# build backend raises, so only the leaf packages are installable on their own.
#
# One entry, and note what it does *not* cover. A `[tool.uv.sources]` entry
# applies only to a package this project requires directly, so every sibling —
# `vercel-workflow` included, which is where all the code this app exercises
# now lives — resolves from PyPI at whatever the last release was, regardless
# of the rev above. At this rev that is harmless: PyPI's `vercel-workflow`
# 0.9.0 is byte-identical to `src/vercel-workflow` at `4814d61f`, because #299
# created the package and the release was cut from it. It will stop being
# harmless the moment main moves ahead of the release.
#
# So when bumping the rev, diff the runtime you actually got against the rev
# you asked for, and git-pin `vercel-workflow` here *and* in `dependencies`
# above if they differ — a source alone does nothing:
#
# rm uv.lock && uv lock --no-config
# grep -c 'source = { git' uv.lock # 1 per git-pinned package
# uv sync --locked --no-config
# git -C <vercel-py> archive <rev>:src/vercel-workflow/vercel | tar x -C /tmp/wf
# diff -rq /tmp/wf .venv/lib/python*/site-packages/vercel | grep -v '^Only in .venv'
#
# Two traps, each of which fails quietly:
#
# - Relocking *in place* keeps the old lock as preferences and can hold a
# package at its old version. Hence the `rm`. `uv lock` on a
# self-consistent lock is also a no-op ("Resolved 34 packages in 5ms"), so
# without the `rm` a bad lock survives untouched.
# - `--no-config` keeps a personal `~/.config/uv/uv.toml` (an `exclude-newer`,
# say) from being recorded as an `[options]` block that CI and the Vercel
# builder then reject under `--locked`. `uv run` re-locks too, which is why
# the `dev` script passes it as well.
[tool.uv.sources]
vercel = { git = "https://github.com/vercel/vercel-py", rev = "4814d61fa2ac1074ea5d67aede8f159ba1daae9b", subdirectory = "src/vercel" }
# How `@vercel/python` builds this app. Reached only because `vercel.json`
# declares `pyproject.toml` as the build src, which puts the builder in
# "declared-only" mode: filename-based entrypoint detection never runs, and
# `[[tool.vercel.workflows]]` is honoured. Without that src the two keys below
# are silently ignored — a bare ASGI app is not a recognised Python framework,
# and the builder only attaches workflows to frameworks or declared builds.
[tool.vercel]
# The web function. It serves `manifest.json`, which is the only route the e2e
# driver calls over HTTP on Vercel — runs are delivered through the queue, not
# through `/flow`.
entrypoint = "app:app"
# The workflow function. The builder imports this module at build time, reads
# `vercel.queue.get_subscriptions()`, and emits one `queue/v2beta` trigger per
# subscription onto a generated `vercel.queue.asgi_app()` handler. Importing
# `app` is what registers them, because `app.py` calls `workflow_entrypoint()`
# at import.
#
# Only one entry is allowed: every workflow consumer receives every `__wkf_*`
# message, so a second one would fail on runs registered only in the first.
[[tool.vercel.workflows]]
entrypoint = "app:registry"