Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion narwhals/_pandas_like/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from narwhals._pandas_like.series import PANDAS_TO_NUMPY_DTYPE_MISSING, PandasLikeSeries
from narwhals._pandas_like.utils import (
align_and_extract_native,
check_column_names_are_unique,
get_dtype_backend,
native_to_narwhals_dtype,
object_native_to_narwhals_dtype,
Expand All @@ -22,6 +21,7 @@
Implementation,
_into_arrow_table,
_remap_full_join_keys,
check_column_names_are_unique,
exclude_column_names,
generate_temporary_column_name,
parse_columns_to_drop,
Expand Down
21 changes: 1 addition & 20 deletions narwhals/_pandas_like/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
check_columns_exist,
isinstance_or_issubclass,
)
from narwhals.exceptions import DuplicateError, ShapeError
from narwhals.exceptions import ShapeError

if TYPE_CHECKING:
from pandas._typing import Dtype as PandasDtype
Expand Down Expand Up @@ -592,25 +592,6 @@ def select_columns_by_name(
raise


def check_column_names_are_unique(columns: pd.Index[str]) -> None:
try:
len_unique_columns = len(columns.drop_duplicates())
except Exception: # noqa: BLE001 # pragma: no cover
msg = f"Expected hashable (e.g. str or int) column names, got: {columns}"
raise ValueError(msg) from None

if len(columns) != len_unique_columns:
from collections import Counter

counter = Counter(columns)
msg = ""
for key, value in counter.items():
if value > 1:
msg += f"\n- '{key}' {value} times"
msg = f"Expected unique column names, got:{msg}"
raise DuplicateError(msg)


def is_non_nullable_boolean(s: PandasLikeSeries) -> bool:
# cuDF booleans are nullable but the native dtype is still 'bool'.
return (
Expand Down
7 changes: 6 additions & 1 deletion narwhals/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,12 @@ def check_columns_exist(


def check_column_names_are_unique(columns: Collection[str]) -> None:
len_unique_columns = len(set(columns))
try:
len_unique_columns = len(set(columns))
except TypeError as exc: # pragma: no cover

@FBruzzesi FBruzzesi Jun 28, 2025

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Set on unhashable type raises a TypeError:

set(([1], [2]))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[1], line 1
----> 1 set(([1], [2]))

TypeError: unhashable type: 'list'

Should we raise a ValueError as before instead?

@dangotbanned dangotbanned Jun 28, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you give an example of how we'd get columns like that in the places the function is currently used?

import pandas as pd

>>> pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=([1], [2], [3]))
TypeError: unhashable type: 'list'

AFAIK, pandas only supports Hashable column "names" - so I'm a little confused πŸ€”

We're checking an existing NativeFrame.columns - so I would have thought that condition is not reachable

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it is, there's a test which gets there

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it is, there's a test which gets there

Is there?

Why do we have a # pragma: no cover?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If this is a pandas version-specific thing - then a comment explaining the no cover would help

I made the suggestion in (#2511 (comment)) based on the fact this appears unreachable

msg = f"Expected hashable (e.g. str or int) column names, got: {columns}"
raise TypeError(msg) from exc

if len(columns) != len_unique_columns:
from collections import Counter

Expand Down
Loading