Skip to content

fix: reject eager_only with an already-narwhals LazyFrame#3677

Open
gaoflow wants to merge 2 commits into
narwhals-dev:mainfrom
gaoflow:fix/3226-from-native-narwhals-lazy-eager-only
Open

fix: reject eager_only with an already-narwhals LazyFrame#3677
gaoflow wants to merge 2 commits into
narwhals-dev:mainfrom
gaoflow:fix/3226-from-native-narwhals-lazy-eager-only

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Closes #3226.

from_native has an early-return for an object that is already a narwhals DataFrame/LazyFrame, returning it before the eager_only / eager_or_interchange_only validation runs (_translate_if_compliant enforces it, but the early return skips that path). So a native pl.LazyFrame was correctly rejected:

nw.from_native(pl.LazyFrame(), eager_only=True)  # TypeError ✅

but an already-narwhals one slipped through and was returned unchanged:

lf = nw.from_native(pl.LazyFrame())
nw.from_native(lf, eager_only=True)  # returned the LazyFrame ❌ (should raise)

This adds the same guard in the early-return path: a narwhals LazyFrame with eager_only/eager_or_interchange_only now raises (or is returned unchanged under pass_through=True), while a narwhals DataFrame (which is eager) is still accepted. Regression test added (fails on main).

One note: narwhals.stable.v1.from_native has the same early-return short-circuit (before it calls _from_native_impl), so the v1 entrypoint still passes a narwhals LazyFrame through. I left v1 untouched since it's the frozen stable API and the fix there needs the pass_through resolution moved above the early return — happy to apply the same guard there if you'd like.

gaoflow added 2 commits June 10, 2026 12:00
`from_native` short-circuits when given an object that is already a narwhals
DataFrame/LazyFrame, returning it before the `eager_only` /
`eager_or_interchange_only` validation runs. A native polars LazyFrame is
correctly rejected, but an already-narwhals one slipped through. Enforce the
same check in the early-return path.

Closes narwhals-dev#3226
@gaoflow

gaoflow commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

Pushed dbdc2f24 to fix the typing failure: the nw.from_native(lf, eager_only=True) call in the runtime negative test is intentionally rejected by the overloads, so it now has the same # type: ignore[call-overload] treatment used elsewhere in this file.

Local verification:

  • uv run --extra polars pytest tests/translate/from_native_test.py::test_init_already_narwhals_lazy_eager_only -q -> 1 passed
  • uv run --extra polars pytest tests/translate/from_native_test.py -q -> 77 passed, 4 skipped
  • make typing -> pyright, mypy, and pyrefly all pass
  • uv run ruff check tests/translate/from_native_test.py -> all checks passed

Remote typing (3.12, ubuntu-latest) is now green. The remaining fairlearn failure is happening before Narwhals is installed or tested: the downstream job fails in install-deps with File not found: requirements.txt after cd fairlearn, and both install-narwhals-dev and run-pytest are skipped.

@dangotbanned dangotbanned added the suggest close Closing requires a second opinion label Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

suggest close Closing requires a second opinion

Projects

None yet

Development

Successfully merging this pull request may close these issues.

from_native(nw.LazyFrame, eager_only=True) returns nw.LazyFrame

2 participants