_globals.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """
  2. Module defining global singleton classes.
  3. This module raises a RuntimeError if an attempt to reload it is made. In that
  4. way the identities of the classes defined here are fixed and will remain so
  5. even if numpy itself is reloaded. In particular, a function like the following
  6. will still work correctly after numpy is reloaded::
  7. def foo(arg=np._NoValue):
  8. if arg is np._NoValue:
  9. ...
  10. That was not the case when the singleton classes were defined in the numpy
  11. ``__init__.py`` file. See gh-7844 for a discussion of the reload problem that
  12. motivated this module.
  13. """
  14. import enum
  15. from ._utils import set_module as _set_module
  16. __all__ = ['_NoValue', '_CopyMode']
  17. # Disallow reloading this module so as to preserve the identities of the
  18. # classes defined here.
  19. if '_is_loaded' in globals():
  20. raise RuntimeError('Reloading numpy._globals is not allowed')
  21. _is_loaded = True
  22. class _NoValueType:
  23. """Special keyword value.
  24. The instance of this class may be used as the default value assigned to a
  25. keyword if no other obvious default (e.g., `None`) is suitable,
  26. Common reasons for using this keyword are:
  27. - A new keyword is added to a function, and that function forwards its
  28. inputs to another function or method which can be defined outside of
  29. NumPy. For example, ``np.std(x)`` calls ``x.std``, so when a ``keepdims``
  30. keyword was added that could only be forwarded if the user explicitly
  31. specified ``keepdims``; downstream array libraries may not have added
  32. the same keyword, so adding ``x.std(..., keepdims=keepdims)``
  33. unconditionally could have broken previously working code.
  34. - A keyword is being deprecated, and a deprecation warning must only be
  35. emitted when the keyword is used.
  36. """
  37. __instance = None
  38. def __new__(cls):
  39. # ensure that only one instance exists
  40. if not cls.__instance:
  41. cls.__instance = super().__new__(cls)
  42. return cls.__instance
  43. def __repr__(self):
  44. return "<no value>"
  45. _NoValue = _NoValueType()
  46. @_set_module("numpy")
  47. class _CopyMode(enum.Enum):
  48. """
  49. An enumeration for the copy modes supported
  50. by numpy.copy() and numpy.array(). The following three modes are supported,
  51. - ALWAYS: This means that a deep copy of the input
  52. array will always be taken.
  53. - IF_NEEDED: This means that a deep copy of the input
  54. array will be taken only if necessary.
  55. - NEVER: This means that the deep copy will never be taken.
  56. If a copy cannot be avoided then a `ValueError` will be
  57. raised.
  58. Note that the buffer-protocol could in theory do copies. NumPy currently
  59. assumes an object exporting the buffer protocol will never do this.
  60. """
  61. ALWAYS = True
  62. IF_NEEDED = False
  63. NEVER = 2
  64. def __bool__(self):
  65. # For backwards compatibility
  66. if self == _CopyMode.ALWAYS:
  67. return True
  68. if self == _CopyMode.IF_NEEDED:
  69. return False
  70. raise ValueError(f"{self} is neither True nor False.")