Skip to content

Fix/from native update version#3515

Open
camriddell wants to merge 5 commits intonarwhals-dev:mainfrom
camriddell:fix/from_native-update-version
Open

Fix/from native update version#3515
camriddell wants to merge 5 commits intonarwhals-dev:mainfrom
camriddell:fix/from_native-update-version

Conversation

@camriddell
Copy link
Member

Description

Calling from_native(nw.DataFrame(…), version=…) would always return the passed DataFrame/Series object.
This ignores the version that is specified in the version argument.

Instead, for a given narwhals DataFrame/Series from_native now returns the same object if the versions match and creates a new object if the versions do not match.

Note, 2 clean up items are also added in this PR.

Before:

import narwhals as nw, narwhals.stable.v1 as nw_v1
import polars as pl

native = pl.DataFrame({"a": [1, 2, 3]})

unstable = nw.from_native(native)
stablified = nw_v1.from_native(unstable)

print(
    isinstance(stablified, nw_v1.DataFrame), # False
    isinstance(stablified, nw.DataFrame),    # True
    sep='\n'
)

stable = nw_v1.from_native(native)
unstablified = nw.from_native(unstable)

print(
    isinstance(unstablified, nw_v1.DataFrame), # False
    isinstance(unstablified, nw.DataFrame),    # True
    sep='\n'
)

After:

import narwhals as nw, narwhals.stable.v1 as nw_v1
import polars as pl

native = pl.DataFrame({"a": [1, 2, 3]})

unstable = nw.from_native(native)
stablified = nw_v1.from_native(unstable)

print(
    isinstance(stablified, nw_v1.DataFrame), # True
    isinstance(stablified, nw.DataFrame),    # True (since nw.v1.DataFrame is subclass of nw.DataFrame)
    sep='\n'
)

stable = nw_v1.from_native(native)
unstablified = nw.from_native(unstable)

print(
    isinstance(unstablified, nw_v1.DataFrame), # False
    isinstance(unstablified, nw.DataFrame),    # True
    sep='\n'
)

reported by hoxbro (Holoviews) on Discord #help channel

What type of PR is this? (check all applicable)

  • 💾 Refactor
  • ✨ Feature
  • 🐛 Bug Fix
  • 🔧 Optimization
  • 📝 Documentation
  • ✅ Test
  • 🐳 Other

Related issues

  • Related issue #<issue number>
  • Closes #<issue number>

Checklist

  • Code follows style guide (ruff)
  • Tests added
  • Documented the changes

in tests/translate/from_native_test.py
test_init_already_narwhals and test_init_already_narwhals_unstable
have the exact same source code, when the former should verify behavior
in a stable version.

This function used to test this, but seemed to have been mistakenly
edited.
from_native on a narwhals.{DataFrame,Series} would always return
the same object even if the DataFrame._version and the version
passed into from_native disagreed.

Now, if the versions mismatch we create a new narwhals object
with the appropriate version. If the versions match, we short cut
and return the same object.
@camriddell camriddell force-pushed the fix/from_native-update-version branch from 761f14c to f1cf356 Compare March 18, 2026 19:01
```
"""

_version: ClassVar[Version] = Version.MAIN
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hoping this has been an oversight and wasn't excluded for a strong reason. This change makes the DataFrame/LazyFrame api a bit more consistent internally.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah nice one, thanks @camriddell!

If you dig through the blame (I think) I added these on Series & DataFrame at the same time as the from_* constructors.

LazyFrame didn't get any new methods, so it slipped through 😅

@camriddell
Copy link
Member Author

@MarcoGorelli I believe the nightly failure isn't due to this change but perhaps something that needs to be accounted for in pandas. Shall I open up an Issue with this? Or do you believe it is relevant to this PR?

pl_frame = pl.DataFrame({"a": [1, 2, 3]}).lazy()
nw_frame = nw_v1.from_native(pl_frame)
with pytest.raises(AttributeError):
with pytest.raises(AssertionError):
Copy link
Member

@dangotbanned dangotbanned Mar 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, there may be a comment somewhere mentioning the error?

(Ignore me if this is too vague 😂)

@dangotbanned
Copy link
Member

@camriddell I should probably check what was mentioned on discord - but from reading the PR I'm a bit confused on the problem that's being solved.

(#3515 (comment)) is all good - but something seems strange to me that calling from_native changes the version 🤔

FWIW, I don't think from_native should accept narwhals-level objects, but we are where we are 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants