| 6538 | |
| 6539 | |
| 6540 | class MaskedConstant(MaskedArray): |
| 6541 | # the lone np.ma.masked instance |
| 6542 | __singleton = None |
| 6543 | |
| 6544 | @classmethod |
| 6545 | def __has_singleton(cls): |
| 6546 | # second case ensures `cls.__singleton` is not just a view on the |
| 6547 | # superclass singleton |
| 6548 | return cls.__singleton is not None and type(cls.__singleton) is cls |
| 6549 | |
| 6550 | def __new__(cls): |
| 6551 | if not cls.__has_singleton(): |
| 6552 | # We define the masked singleton as a float for higher precedence. |
| 6553 | # Note that it can be tricky sometimes w/ type comparison |
| 6554 | data = np.array(0.) |
| 6555 | mask = np.array(True) |
| 6556 | |
| 6557 | # prevent any modifications |
| 6558 | data.flags.writeable = False |
| 6559 | mask.flags.writeable = False |
| 6560 | |
| 6561 | # don't fall back on MaskedArray.__new__(MaskedConstant), since |
| 6562 | # that might confuse it - this way, the construction is entirely |
| 6563 | # within our control |
| 6564 | cls.__singleton = MaskedArray(data, mask=mask).view(cls) |
| 6565 | |
| 6566 | return cls.__singleton |
| 6567 | |
| 6568 | def __array_finalize__(self, obj): |
| 6569 | if not self.__has_singleton(): |
| 6570 | # this handles the `.view` in __new__, which we want to copy across |
| 6571 | # properties normally |
| 6572 | return super().__array_finalize__(obj) |
| 6573 | elif self is self.__singleton: |
| 6574 | # not clear how this can happen, play it safe |
| 6575 | pass |
| 6576 | else: |
| 6577 | # everywhere else, we want to downcast to MaskedArray, to prevent a |
| 6578 | # duplicate maskedconstant. |
| 6579 | self.__class__ = MaskedArray |
| 6580 | MaskedArray.__array_finalize__(self, obj) |
| 6581 | |
| 6582 | def __array_prepare__(self, obj, context=None): |
| 6583 | return self.view(MaskedArray).__array_prepare__(obj, context) |
| 6584 | |
| 6585 | def __array_wrap__(self, obj, context=None): |
| 6586 | return self.view(MaskedArray).__array_wrap__(obj, context) |
| 6587 | |
| 6588 | def __str__(self): |
| 6589 | return str(masked_print_option._display) |
| 6590 | |
| 6591 | def __repr__(self): |
| 6592 | if self is MaskedConstant.__singleton: |
| 6593 | return 'masked' |
| 6594 | else: |
| 6595 | # it's a subclass, or something is wrong, make it obvious |
| 6596 | return object.__repr__(self) |
| 6597 | |