(value: Any)
| 57 | |
| 58 | |
| 59 | def is_data_primitive(value: Any) -> bool: |
| 60 | if is_primitive(value): |
| 61 | return True |
| 62 | |
| 63 | if inspect.isclass(value): |
| 64 | return False |
| 65 | |
| 66 | if not ( |
| 67 | hasattr(value, "__array__") |
| 68 | or hasattr(value, "toarray") |
| 69 | or hasattr(value, "__array_interface__") |
| 70 | ): |
| 71 | return False |
| 72 | |
| 73 | # Handle cross device tensors particular to torch |
| 74 | # Transfer may be expensive, so non-cpu tensors are considered |
| 75 | # unhashable. |
| 76 | if is_instance_by_name(value, "torch.Tensor"): |
| 77 | return str(value.device) == "cpu" |
| 78 | |
| 79 | # If a numpy like array, ensure that it's not an object array. |
| 80 | if hasattr(value, "dtype"): |
| 81 | return not ( |
| 82 | value.dtype is None |
| 83 | or (hasattr(value.dtype, "hasobject") and value.dtype.hasobject) |
| 84 | ) |
| 85 | elif hasattr(value, "dtypes"): |
| 86 | # Bit of discrepancy between objects like polars and pandas, so use |
| 87 | # narwhals to normalize the dataframe. |
| 88 | import narwhals.stable.v2 as nw |
| 89 | |
| 90 | try: |
| 91 | return bool( |
| 92 | all( |
| 93 | dtype.is_numeric() |
| 94 | for dtype in nw.from_native(value) |
| 95 | .collect_schema() |
| 96 | .dtypes() |
| 97 | ) |
| 98 | ) |
| 99 | except Exception: |
| 100 | return False |
| 101 | # Otherwise may be a closely related array object |
| 102 | return True |
| 103 | |
| 104 | |
| 105 | def _is_primitive_container( |
searching dependent graphs…