|
24 | 24 | "NormalizedRangeError", |
25 | 25 | "PerformanceWarning", |
26 | 26 | "ReplacementWarning", |
| 27 | + "copy_dunders_unimplemented", |
27 | 28 | "warning", |
28 | 29 | "generate_uuid_from_kwargs", |
29 | 30 | "is_raspberry_pi", |
@@ -111,6 +112,55 @@ def __init__(self, var_name: str, value: float): |
111 | 112 | super().__init__(var_name, value, 0.0, 1.0) |
112 | 113 |
|
113 | 114 |
|
| 115 | +_TType = TypeVar('_TType', bound=Type) |
| 116 | + |
| 117 | +def copy_dunders_unimplemented(decorated_type: _TType) -> _TType: |
| 118 | + """Decorator stubs dunders raising :py:class:`NotImplementedError`. |
| 119 | +
|
| 120 | + Temp fixes https://github.com/pythonarcade/arcade/issues/2074 by |
| 121 | + stubbing the following instance methods: |
| 122 | +
|
| 123 | + * :py:meth:`object.__copy__` (used by :py:func:`copy.copy`) |
| 124 | + * :py:meth:`object.__deepcopy__` (used by :py:func:`copy.deepcopy`) |
| 125 | +
|
| 126 | + Example usage: |
| 127 | +
|
| 128 | + .. code-block:: python |
| 129 | +
|
| 130 | + import copy |
| 131 | + from arcade,utils import copy_dunders_unimplemented |
| 132 | + from arcade.hypothetical_module import HypotheticalNasty |
| 133 | +
|
| 134 | + # Example usage |
| 135 | + @copy_dunders_unimplemented |
| 136 | + class CantCopy: |
| 137 | + def __init__(self, nasty_state: HypotheticalNasty): |
| 138 | + self.nasty_state = nasty_state |
| 139 | +
|
| 140 | + instance = CantCopy(HypotheticalNasty()) |
| 141 | +
|
| 142 | + # These raise NotImplementedError |
| 143 | + this_line_raises = copy.deepcopy(instance) |
| 144 | + this_line_also_raises = copy.copy(instance) |
| 145 | +
|
| 146 | +
|
| 147 | + """ |
| 148 | + def __copy__(self): # noqa |
| 149 | + raise NotImplementedError( |
| 150 | + f"{self.__class__.__name__} does not implement __copy__, but" |
| 151 | + f"you may implement it on a custom subclass." |
| 152 | + ) |
| 153 | + decorated_type.__copy__ = __copy__ |
| 154 | + |
| 155 | + def __deepcopy__(self, memo): # noqa |
| 156 | + raise NotImplementedError( |
| 157 | + f"{self.__class__.__name__} does not implement __deepcopy__," |
| 158 | + f" but you may implement it on a custom subclass." |
| 159 | + ) |
| 160 | + decorated_type.__deepcopy__ = __deepcopy__ |
| 161 | + |
| 162 | + return decorated_type |
| 163 | + |
114 | 164 | class PerformanceWarning(Warning): |
115 | 165 | """Use this for issuing performance warnings.""" |
116 | 166 | pass |
|
0 commit comments