55from  functools  import  wraps 
66from  typing  import  TYPE_CHECKING , Any , Callable , Literal , TypeVar , overload 
77
8+ from  narwhals  import  plugins 
89from  narwhals ._constants  import  EPOCH , MS_PER_SECOND 
910from  narwhals ._native  import  (
1011    is_native_arrow ,
1112    is_native_pandas_like ,
1213    is_native_polars ,
1314    is_native_spark_like ,
1415)
15- from  narwhals ._utils  import  Implementation , Version , has_native_namespace 
16+ from  narwhals ._utils  import  (
17+     Implementation ,
18+     Version ,
19+     has_native_namespace ,
20+     is_compliant_dataframe ,
21+     is_compliant_lazyframe ,
22+     is_compliant_series ,
23+ )
1624from  narwhals .dependencies  import  (
1725    get_dask_expr ,
1826    get_numpy ,
@@ -314,23 +322,65 @@ def from_native(  # noqa: D417
314322    )
315323
316324
325+ def  _translate_if_compliant (  # noqa: C901,PLR0911 
326+     compliant_object : Any ,
327+     * ,
328+     pass_through : bool  =  False ,
329+     eager_only : bool  =  False ,
330+     # Interchange-level was removed after v1 
331+     eager_or_interchange_only : bool ,
332+     series_only : bool ,
333+     allow_series : bool  |  None ,
334+     version : Version ,
335+ ) ->  Any :
336+     if  is_compliant_dataframe (compliant_object ):
337+         if  series_only :
338+             if  not  pass_through :
339+                 msg  =  "Cannot only use `series_only` with dataframe" 
340+                 raise  TypeError (msg )
341+             return  compliant_object 
342+         return  version .dataframe (
343+             compliant_object .__narwhals_dataframe__ ()._with_version (version ), level = "full" 
344+         )
345+     if  is_compliant_lazyframe (compliant_object ):
346+         if  series_only :
347+             if  not  pass_through :
348+                 msg  =  "Cannot only use `series_only` with lazyframe" 
349+                 raise  TypeError (msg )
350+             return  compliant_object 
351+         if  eager_only  or  eager_or_interchange_only :
352+             if  not  pass_through :
353+                 msg  =  "Cannot only use `eager_only` or `eager_or_interchange_only` with lazyframe" 
354+                 raise  TypeError (msg )
355+             return  compliant_object 
356+         return  version .lazyframe (
357+             compliant_object .__narwhals_lazyframe__ ()._with_version (version ), level = "full" 
358+         )
359+     if  is_compliant_series (compliant_object ):
360+         if  not  allow_series :
361+             if  not  pass_through :
362+                 msg  =  "Please set `allow_series=True` or `series_only=True`" 
363+                 raise  TypeError (msg )
364+             return  compliant_object 
365+         return  version .series (
366+             compliant_object .__narwhals_series__ ()._with_version (version ), level = "full" 
367+         )
368+     # Object wasn't compliant, can't translate here. 
369+     return  None 
370+ 
371+ 
317372def  _from_native_impl (  # noqa: C901, PLR0911, PLR0912, PLR0915 
318373    native_object : Any ,
319374    * ,
320375    pass_through : bool  =  False ,
321376    eager_only : bool  =  False ,
322377    # Interchange-level was removed after v1 
323-     eager_or_interchange_only : bool   =   False ,
324-     series_only : bool   =   False ,
325-     allow_series : bool  |  None   =   None ,
378+     eager_or_interchange_only : bool ,
379+     series_only : bool ,
380+     allow_series : bool  |  None ,
326381    version : Version ,
327382) ->  Any :
328383    from  narwhals ._interchange .dataframe  import  supports_dataframe_interchange 
329-     from  narwhals ._utils  import  (
330-         is_compliant_dataframe ,
331-         is_compliant_lazyframe ,
332-         is_compliant_series ,
333-     )
334384    from  narwhals .dataframe  import  DataFrame , LazyFrame 
335385    from  narwhals .series  import  Series 
336386
@@ -350,38 +400,18 @@ def _from_native_impl(  # noqa: C901, PLR0911, PLR0912, PLR0915
350400        raise  ValueError (msg )
351401
352402    # Extensions 
353-     if  is_compliant_dataframe (native_object ):
354-         if  series_only :
355-             if  not  pass_through :
356-                 msg  =  "Cannot only use `series_only` with dataframe" 
357-                 raise  TypeError (msg )
358-             return  native_object 
359-         return  version .dataframe (
360-             native_object .__narwhals_dataframe__ ()._with_version (version ), level = "full" 
361-         )
362-     if  is_compliant_lazyframe (native_object ):
363-         if  series_only :
364-             if  not  pass_through :
365-                 msg  =  "Cannot only use `series_only` with lazyframe" 
366-                 raise  TypeError (msg )
367-             return  native_object 
368-         if  eager_only  or  eager_or_interchange_only :
369-             if  not  pass_through :
370-                 msg  =  "Cannot only use `eager_only` or `eager_or_interchange_only` with lazyframe" 
371-                 raise  TypeError (msg )
372-             return  native_object 
373-         return  version .lazyframe (
374-             native_object .__narwhals_lazyframe__ ()._with_version (version ), level = "full" 
375-         )
376-     if  is_compliant_series (native_object ):
377-         if  not  allow_series :
378-             if  not  pass_through :
379-                 msg  =  "Please set `allow_series=True` or `series_only=True`" 
380-                 raise  TypeError (msg )
381-             return  native_object 
382-         return  version .series (
383-             native_object .__narwhals_series__ ()._with_version (version ), level = "full" 
403+     if  (
404+         translated  :=  _translate_if_compliant (
405+             native_object ,
406+             pass_through = pass_through ,
407+             eager_only = eager_only ,
408+             eager_or_interchange_only = eager_or_interchange_only ,
409+             series_only = series_only ,
410+             allow_series = allow_series ,
411+             version = version ,
384412        )
413+     ) is  not   None :
414+         return  translated 
385415
386416    # Polars 
387417    if  is_native_polars (native_object ):
@@ -534,6 +564,18 @@ def _from_native_impl(  # noqa: C901, PLR0911, PLR0912, PLR0915
534564            raise  TypeError (msg )
535565        return  Version .V1 .dataframe (InterchangeFrame (native_object ), level = "interchange" )
536566
567+     compliant_object  =  plugins .from_native (native_object , version )
568+     if  compliant_object  is  not   None :
569+         return  _translate_if_compliant (
570+             compliant_object ,
571+             pass_through = pass_through ,
572+             eager_only = eager_only ,
573+             eager_or_interchange_only = eager_or_interchange_only ,
574+             series_only = series_only ,
575+             allow_series = allow_series ,
576+             version = version ,
577+         )
578+ 
537579    if  not  pass_through :
538580        msg  =  f"Expected pandas-like dataframe, Polars dataframe, or Polars lazyframe, got: { type (native_object )}  " 
539581        raise  TypeError (msg )
0 commit comments