From 933c386d659e32bbbbca568dba2c8e26899dc7a9 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 29 May 2025 17:24:16 +0200 Subject: [PATCH] Backport PR #30114: Fix _is_tensorflow_array. --- lib/matplotlib/cbook.py | 78 +++++++++++++++--------------- lib/matplotlib/tests/test_cbook.py | 3 ++ 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/lib/matplotlib/cbook.py b/lib/matplotlib/cbook.py index b40f6549c945..ba61dd5e8415 100644 --- a/lib/matplotlib/cbook.py +++ b/lib/matplotlib/cbook.py @@ -2311,42 +2311,56 @@ def _picklable_class_constructor(mixin_class, fmt, attr_name, base_class): def _is_torch_array(x): - """Check if 'x' is a PyTorch Tensor.""" + """Return whether *x* is a PyTorch Tensor.""" try: - # we're intentionally not attempting to import torch. If somebody - # has created a torch array, torch should already be in sys.modules - return isinstance(x, sys.modules['torch'].Tensor) - except Exception: # TypeError, KeyError, AttributeError, maybe others? - # we're attempting to access attributes on imported modules which - # may have arbitrary user code, so we deliberately catch all exceptions - return False + # We're intentionally not attempting to import torch. If somebody + # has created a torch array, torch should already be in sys.modules. + tp = sys.modules.get("torch").Tensor + except AttributeError: + return False # Module not imported or a nonstandard module with no Tensor attr. + return (isinstance(tp, type) # Just in case it's a very nonstandard module. + and isinstance(x, tp)) def _is_jax_array(x): - """Check if 'x' is a JAX Array.""" + """Return whether *x* is a JAX Array.""" try: - # we're intentionally not attempting to import jax. If somebody - # has created a jax array, jax should already be in sys.modules - return isinstance(x, sys.modules['jax'].Array) - except Exception: # TypeError, KeyError, AttributeError, maybe others? - # we're attempting to access attributes on imported modules which - # may have arbitrary user code, so we deliberately catch all exceptions - return False + # We're intentionally not attempting to import jax. If somebody + # has created a jax array, jax should already be in sys.modules. + tp = sys.modules.get("jax").Array + except AttributeError: + return False # Module not imported or a nonstandard module with no Array attr. + return (isinstance(tp, type) # Just in case it's a very nonstandard module. + and isinstance(x, tp)) + + +def _is_pandas_dataframe(x): + """Check if *x* is a Pandas DataFrame.""" + try: + # We're intentionally not attempting to import Pandas. If somebody + # has created a Pandas DataFrame, Pandas should already be in sys.modules. + tp = sys.modules.get("pandas").DataFrame + except AttributeError: + return False # Module not imported or a nonstandard module with no Array attr. + return (isinstance(tp, type) # Just in case it's a very nonstandard module. + and isinstance(x, tp)) def _is_tensorflow_array(x): - """Check if 'x' is a TensorFlow Tensor or Variable.""" + """Return whether *x* is a TensorFlow Tensor or Variable.""" try: - # we're intentionally not attempting to import TensorFlow. If somebody - # has created a TensorFlow array, TensorFlow should already be in sys.modules - # we use `is_tensor` to not depend on the class structure of TensorFlow - # arrays, as `tf.Variables` are not instances of `tf.Tensor` - # (they both convert the same way) - return isinstance(x, sys.modules['tensorflow'].is_tensor(x)) - except Exception: # TypeError, KeyError, AttributeError, maybe others? - # we're attempting to access attributes on imported modules which - # may have arbitrary user code, so we deliberately catch all exceptions + # We're intentionally not attempting to import TensorFlow. If somebody + # has created a TensorFlow array, TensorFlow should already be in + # sys.modules we use `is_tensor` to not depend on the class structure + # of TensorFlow arrays, as `tf.Variables` are not instances of + # `tf.Tensor` (they both convert the same way). + is_tensor = sys.modules.get("tensorflow").is_tensor + except AttributeError: return False + try: + return is_tensor(x) + except Exception: + return False # Just in case it's a very nonstandard module. def _unpack_to_numpy(x): @@ -2401,15 +2415,3 @@ def _auto_format_str(fmt, value): return fmt % (value,) except (TypeError, ValueError): return fmt.format(value) - - -def _is_pandas_dataframe(x): - """Check if 'x' is a Pandas DataFrame.""" - try: - # we're intentionally not attempting to import Pandas. If somebody - # has created a Pandas DataFrame, Pandas should already be in sys.modules - return isinstance(x, sys.modules['pandas'].DataFrame) - except Exception: # TypeError, KeyError, AttributeError, maybe others? - # we're attempting to access attributes on imported modules which - # may have arbitrary user code, so we deliberately catch all exceptions - return False diff --git a/lib/matplotlib/tests/test_cbook.py b/lib/matplotlib/tests/test_cbook.py index a8faa9be3782..639563afeb4d 100644 --- a/lib/matplotlib/tests/test_cbook.py +++ b/lib/matplotlib/tests/test_cbook.py @@ -983,6 +983,7 @@ def __array__(self): torch_tensor = torch.Tensor(data) result = cbook._unpack_to_numpy(torch_tensor) + assert isinstance(result, np.ndarray) # compare results, do not check for identity: the latter would fail # if not mocked, and the implementation does not guarantee it # is the same Python object, just the same values. @@ -1011,6 +1012,7 @@ def __array__(self): jax_array = jax.Array(data) result = cbook._unpack_to_numpy(jax_array) + assert isinstance(result, np.ndarray) # compare results, do not check for identity: the latter would fail # if not mocked, and the implementation does not guarantee it # is the same Python object, just the same values. @@ -1040,6 +1042,7 @@ def __array__(self): tf_tensor = tensorflow.Tensor(data) result = cbook._unpack_to_numpy(tf_tensor) + assert isinstance(result, np.ndarray) # compare results, do not check for identity: the latter would fail # if not mocked, and the implementation does not guarantee it # is the same Python object, just the same values. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy