77from typing import TYPE_CHECKING
88from typing import Any
99from typing import Callable
10+ from typing import Literal
1011from typing import Sequence
1112from typing import Sized
1213from typing import TypeVar
1314
1415import pandas as pd
1516
1617from narwhals ._compliant .series import EagerSeriesNamespace
17- from narwhals .dtypes import _DelayedCategories
1818from narwhals .exceptions import ColumnNotFoundError
1919from narwhals .exceptions import DuplicateError
2020from narwhals .exceptions import ShapeError
2121from narwhals .utils import Implementation
2222from narwhals .utils import Version
23+ from narwhals .utils import _DeferredIterable
2324from narwhals .utils import isinstance_or_issubclass
2425
2526T = TypeVar ("T" , bound = Sized )
@@ -255,9 +256,7 @@ def non_object_native_to_narwhals_dtype(native_dtype: Any, version: Version) ->
255256 if dtype .startswith ("dictionary<" ):
256257 return dtypes .Categorical ()
257258 if dtype == "category" :
258- return native_categorical_to_narwhals_dtype (
259- native_dtype , version , lambda : tuple (native_dtype .categories )
260- )
259+ return native_categorical_to_narwhals_dtype (native_dtype , version )
261260 if (match_ := PATTERN_PD_DATETIME .match (dtype )) or (
262261 match_ := PATTERN_PA_DATETIME .match (dtype )
263262 ):
@@ -305,20 +304,33 @@ def object_native_to_narwhals_dtype(
305304def native_categorical_to_narwhals_dtype (
306305 native_dtype : pd .CategoricalDtype ,
307306 version : Version ,
308- get_categories : Callable [[], tuple [ str , ...]] ,
307+ implementation : Literal [ Implementation . CUDF ] | None = None ,
309308) -> DType :
310309 dtypes = version .dtypes
311310 if version is Version .V1 :
312311 return dtypes .Categorical ()
313312 if native_dtype .ordered :
314- return dtypes .Enum (_DelayedCategories (get_categories ))
313+ into_iter = (
314+ _cudf_categorical_to_list (native_dtype )
315+ if implementation is Implementation .CUDF
316+ else native_dtype .categories .to_list
317+ )
318+ return dtypes .Enum (_DeferredIterable (into_iter ))
315319 return dtypes .Categorical ()
316320
317321
318- def native_to_narwhals_dtype (
322+ def _cudf_categorical_to_list (
319323 native_dtype : Any ,
320- version : Version ,
321- implementation : Implementation ,
324+ ) -> Callable [[], list [Any ]]: # pragma: no cover
325+ # NOTE: https://docs.rapids.ai/api/cudf/stable/user_guide/api_docs/api/cudf.core.dtypes.categoricaldtype/#cudf.core.dtypes.CategoricalDtype
326+ def fn () -> list [Any ]:
327+ return native_dtype .categories .to_arrow ().to_pylist ()
328+
329+ return fn
330+
331+
332+ def native_to_narwhals_dtype (
333+ native_dtype : Any , version : Version , implementation : Implementation
322334) -> DType :
323335 str_dtype = str (native_dtype )
324336
@@ -333,8 +345,9 @@ def native_to_narwhals_dtype(
333345 return arrow_native_to_narwhals_dtype (native_dtype .pyarrow_dtype , version )
334346 if str_dtype == "category" and implementation .is_cudf ():
335347 # https://github.com/rapidsai/cudf/issues/18536
348+ # https://github.com/rapidsai/cudf/issues/14027
336349 return native_categorical_to_narwhals_dtype (
337- native_dtype , version , lambda : tuple ( native_dtype . categories . to_pandas ())
350+ native_dtype , version , Implementation . CUDF
338351 )
339352 if str_dtype != "object" :
340353 return non_object_native_to_narwhals_dtype (native_dtype , version )
0 commit comments