Skip to content

Commit

Permalink
Avoid making multiple ApproxNumpy types.
Browse files Browse the repository at this point in the history
  • Loading branch information
kalekundert committed Jul 4, 2017
1 parent 8524a57 commit c111e9d
Showing 1 changed file with 16 additions and 9 deletions.
25 changes: 16 additions & 9 deletions _pytest/python_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,9 @@ class ApproxNumpyBase(ApproxBase):
"""
Perform approximate comparisons for numpy arrays.
This class should not be used directly. Instead, it should be used to make
a subclass that also inherits from `np.ndarray`, e.g.::
import numpy as np
ApproxNumpy = type('ApproxNumpy', (ApproxNumpyBase, np.ndarray), {})
This bizarre invocation is necessary because the object doing the
This class should not be used directly. Instead, the `inherit_ndarray()`
class method should be used to make a subclass that also inherits from
`np.ndarray`. This indirection is necessary because the object doing the
approximate comparison must inherit from `np.ndarray`, or it will only work
on the left side of the `==` operator. But importing numpy is relatively
expensive, so we also want to avoid that unless we actually have a numpy
Expand All @@ -81,6 +77,18 @@ class ApproxNumpyBase(ApproxBase):
it appears on.
"""

subclass = None

@classmethod
def inherit_ndarray(cls):
import numpy as np
assert not isinstance(cls, np.ndarray)

if cls.subclass is None:
cls.subclass = type('ApproxNumpy', (ApproxNumpyBase, np.ndarray), {})

return cls.subclass

def __new__(cls, expected, rel=None, abs=None, nan_ok=False):
"""
Numpy uses __new__ (rather than __init__) to initialize objects.
Expand Down Expand Up @@ -416,8 +424,7 @@ def approx(expected, rel=None, abs=None, nan_ok=False):
if _is_numpy_array(expected):
# Create the delegate class on the fly. This allow us to inherit from
# ``np.ndarray`` while still not importing numpy unless we need to.
import numpy as np
cls = type('ApproxNumpy', (ApproxNumpyBase, np.ndarray), {})
cls = ApproxNumpyBase.inherit_ndarray()
elif isinstance(expected, Mapping):
cls = ApproxMapping
elif isinstance(expected, Sequence) and not isinstance(expected, String):
Expand Down

0 comments on commit c111e9d

Please sign in to comment.