Fail environment validation when standalone pyspark collides with databricks-connect - #6277
Fail environment validation when standalone pyspark collides with databricks-connect#6277rugpanov wants to merge 2 commits into
Conversation
Waiting for approvalCould not determine reviewers from git history. Eligible reviewers: Suggestions based on git history. See OWNERS for ownership rules. |
Integration test reportCommit: 550e991
8 interesting tests: 4 SKIP, 3 KNOWN, 1 RECOVERED
Top 6 slowest tests (at least 2 minutes):
|
|
Reviewed as part of the three-PR stack (#6276, this, and databricks/databricks-vscode#2121). Not approving yet — one finding below is, I think, worth settling before this merges, since this is the PR that converts a warning into a hard error. What I verifiedThe mechanism is sound. Against a genuinely collided venv the probe reports exactly what the PR claims: and that venv is genuinely broken ( Finding 1 — this hard-fails a working environmentThe load-bearing claim is "the two cannot coexist." That is install-order dependent, and I have a counterexample. Installing standalone
The version mismatch is the tell:
Worth considering: confirm the collision is live before failing — compare Finding 2 — gating disagrees with #6276This fails on venv contents ( No warning at merge, then an unexplained hard failure at validate — and since Testing
The interface change to I could not run the Go suites here: the repo requires Go 1.26, the local toolchain is 1.24, and the module proxy is blocked in my environment. I verified the logic by reading it and by reproducing the package behaviour directly in Python, not by executing the tests. Taking the reported Note on sequencingThis is stacked on #6276, which I've approved. If #6276's gating changes per Finding 2, this will need a rebase. |
|
Follow-up: I found a working PyPI mirror ( Both cases reproduced through genuine
|
| discriminator | Case A (broken) | Case B (functional) |
|---|---|---|
metadata.version("pyspark") vs pyspark.__version__ |
4.2.0 == 4.2.0 → fail |
4.2.0 != 4.1.0 → don't fail |
attempt from databricks.connect import DatabricksSession |
ImportError → fail |
OK → don't fail |
Either one separates the cases cleanly. The import probe is the more direct test of the property you actually care about ("can this environment start a session"), and it needs no assumption about how the shadowing manifests; the version comparison is cheaper and avoids importing Spark during validate.
One caveat I still can't close: I couldn't confirm Case B builds a live SparkSession end-to-end, since that needs workspace connectivity this sandbox doesn't have. So the strict claim is "imports cleanly and is not the failure mode this PR describes" — the import is where the collision actually surfaces, per the traceback above. If dbconnect turns out to fail later at session time in Case B too, that would argue for keeping the fail, and the version comparison would then be the wrong discriminator while the message would still need fixing (it reports 4.2.0, which is not the importable version).
Everything else in my original review stands, including the Finding 2 gating mismatch with #6276.
*Why* The validate phase read only the Python and databricks-connect versions, so a venv with a standalone pyspark installed on top of databricks-connect passed validation and setup reported "environment ready" — even though the two share the pyspark namespace, overwrite each other, and the environment then cannot start a session. Users hit this later as an opaque Java or protobuf gencode error with no link back to setup. Validation should reject an environment it knows cannot run. *What* - PackageManager.Validate now also returns the standalone pyspark version. It reads distribution metadata: databricks-connect vendors pyspark without registering a pyspark distribution, so a non-empty value means a separate pyspark was installed on top of it — the collision. - pipeline validate fails with E_VALIDATE, and actionable guidance, when both databricks-connect and a standalone pyspark are present. Keyed on both being installed in the venv, not on the run mode. - uvManager.Validate probes pyspark alongside databricks-connect; mocks and the interface updated to the new signature. *Verification* - go test ./libs/localenv/ passes (new TestPipelineValidateRejectsStandalonePyspark plus the existing suite). - go vet ./libs/localenv/ clean. Co-authored-by: Isaac
3e3276d to
fbbb5b5
Compare
*Why*
Review feedback (Finding 1): the metadata-only check hard-failed a *working*
environment. If standalone pyspark is installed before databricks-connect (or
`uv sync` audits without reinstalling), databricks-connect's vendored files win
the overwrite and the env imports fine — but an orphaned pyspark-*.dist-info is
left behind. Reading only `importlib.metadata.version("pyspark")` then reports a
pyspark version that is not the importable one and fails an environment that
runs. Reproduced with real `uv sync`.
*What*
- The validate probe now also attempts `import databricks.connect`; a live
collision raises there, a stale dist-info does not.
- Validate returns a VenvInfo struct (python minor, databricks-connect version,
pyspark version, and the databricks-connect import error) instead of a growing
tuple.
- The hard fail now requires databricks-connect present AND standalone pyspark
present AND the databricks-connect import failing — so a functional env with a
leftover pyspark dist-info is no longer rejected. The message reports the import
error and the colliding versions.
*Verification*
- go test ./libs/localenv/ passes, including a new
TestPipelineValidateAllowsStalePysparkDistInfo (functional env → no fail) and
the updated live-collision test.
- Probe validated against a real databricks-connect 18/17 venv (imports clean →
no fail) and the reproduced collision (ImportError → fail).
- go vet ./libs/localenv/ clean.
Co-authored-by: Isaac
fbbb5b5 to
550e991
Compare
|
Thanks for the thorough review — especially reproducing Finding 1 through a real Finding 1 — hard-failing a working environment. You're right: the metadata-only probe read an orphaned
Finding 2 — gating disagreement with #6276. Aligned on the venv-based reasoning: #6276's warning now fires whenever databricks-connect is present by any route (mode or a user-pinned databricks-connect kept in constraints-only mode), matching this PR's Testing gaps. Added Rebased onto the updated #6276. |
Problem
The validate phase read only the Python and
databricks-connectversions, so a venvwith a standalone
pysparkinstalled on top ofdatabricks-connectpassed validationand
setup-localreported "environment ready" — even though the two share thepysparknamespace, overwrite each other, and the environment then cannot start asession. Users hit this later as an opaque Java or protobuf gencode error with no link
back to setup.
What
PackageManager.Validatenow also returns the standalonepysparkversion. It readsdistribution metadata:
databricks-connectvendorspysparkwithout registering apysparkdistribution, so a non-empty value means a separatepysparkwas installedon top of it — the collision.
E_VALIDATE, and actionable guidance, whenboth
databricks-connectand a standalonepysparkare present. Keyed on both beinginstalled in the venv, not on the run mode.
uvManager.Validateprobespysparkalongsidedatabricks-connect; the interfaceand mocks are updated to the new signature.
Compatibility note
This is a behaviour change: environments that today report "ready" with both packages
installed will now fail validation. That is the intended correction — the previous
"ready" was misleading — but it is worth a conscious sign-off.
Testing
go test ./libs/localenv/(newTestPipelineValidateRejectsStandalonePysparkplusthe existing suite).
go vet ./libs/localenv/.This pull request and its description were written by Isaac.