| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,6 +31,7 @@ | |||
| 31 | 31 | from typing_extensions import NamedTuple | |
| 32 | 32 | from typing_extensions import override, deprecated | |
| 33 | 33 | from _typed_dict_test_helper import Foo, FooGeneric | |
| 34 | + import warnings | ||
| 34 | 35 | ||
| 35 | 36 | # Flags used to mark tests that only apply after a specific | |
| 36 | 37 | # version of the typing module. | |
@@ -203,7 +204,7 @@ def static_method_bad_order(): | |||
| 203 | 204 | ||
| 204 | 205 | ||
| 205 | 206 | class DeprecatedTests(BaseTestCase): | |
| 206 | - def test_deprecated(self): | ||
| 207 | + def test_dunder_deprecated(self): | ||
| 207 | 208 | @deprecated("A will go away soon") | |
| 208 | 209 | class A: | |
| 209 | 210 | pass | |
@@ -230,6 +231,123 @@ def h(x): | |||
| 230 | 231 | self.assertEqual(len(overloads), 2) | |
| 231 | 232 | self.assertEqual(overloads[0].__deprecated__, "no more ints") | |
| 232 | 233 | ||
| 234 | + def test_class(self): | ||
| 235 | + @deprecated("A will go away soon") | ||
| 236 | + class A: | ||
| 237 | + pass | ||
| 238 | + | ||
| 239 | + with self.assertWarnsRegex(DeprecationWarning, "A will go away soon"): | ||
| 240 | + A() | ||
| 241 | + with self.assertRaises(TypeError): | ||
| 242 | + A(42) | ||
| 243 | + | ||
| 244 | + @deprecated("HasInit will go away soon") | ||
| 245 | + class HasInit: | ||
| 246 | + def __init__(self, x): | ||
| 247 | + self.x = x | ||
| 248 | + | ||
| 249 | + with self.assertWarnsRegex(DeprecationWarning, "HasInit will go away soon"): | ||
| 250 | + instance = HasInit(42) | ||
| 251 | + self.assertEqual(instance.x, 42) | ||
| 252 | + | ||
| 253 | + has_new_called = False | ||
| 254 | + | ||
| 255 | + @deprecated("HasNew will go away soon") | ||
| 256 | + class HasNew: | ||
| 257 | + def __new__(cls, x): | ||
| 258 | + nonlocal has_new_called | ||
| 259 | + has_new_called = True | ||
| 260 | + return super().__new__(cls) | ||
| 261 | + | ||
| 262 | + def __init__(self, x) -> None: | ||
| 263 | + self.x = x | ||
| 264 | + | ||
| 265 | + with self.assertWarnsRegex(DeprecationWarning, "HasNew will go away soon"): | ||
| 266 | + instance = HasNew(42) | ||
| 267 | + self.assertEqual(instance.x, 42) | ||
| 268 | + self.assertTrue(has_new_called) | ||
| 269 | + new_base_called = False | ||
| 270 | + | ||
| 271 | + class NewBase: | ||
| 272 | + def __new__(cls, x): | ||
| 273 | + nonlocal new_base_called | ||
| 274 | + new_base_called = True | ||
| 275 | + return super().__new__(cls) | ||
| 276 | + | ||
| 277 | + def __init__(self, x) -> None: | ||
| 278 | + self.x = x | ||
| 279 | + | ||
| 280 | + @deprecated("HasInheritedNew will go away soon") | ||
| 281 | + class HasInheritedNew(NewBase): | ||
| 282 | + pass | ||
| 283 | + | ||
| 284 | + with self.assertWarnsRegex(DeprecationWarning, "HasInheritedNew will go away soon"): | ||
| 285 | + instance = HasInheritedNew(42) | ||
| 286 | + self.assertEqual(instance.x, 42) | ||
| 287 | + self.assertTrue(new_base_called) | ||
| 288 | + | ||
| 289 | + def test_function(self): | ||
| 290 | + @deprecated("b will go away soon") | ||
| 291 | + def b(): | ||
| 292 | + pass | ||
| 293 | + | ||
| 294 | + with self.assertWarnsRegex(DeprecationWarning, "b will go away soon"): | ||
| 295 | + b() | ||
| 296 | + | ||
| 297 | + def test_method(self): | ||
| 298 | + class Capybara: | ||
| 299 | + @deprecated("x will go away soon") | ||
| 300 | + def x(self): | ||
| 301 | + pass | ||
| 302 | + | ||
| 303 | + instance = Capybara() | ||
| 304 | + with self.assertWarnsRegex(DeprecationWarning, "x will go away soon"): | ||
| 305 | + instance.x() | ||
| 306 | + | ||
| 307 | + def test_property(self): | ||
| 308 | + class Capybara: | ||
| 309 | + @property | ||
| 310 | + @deprecated("x will go away soon") | ||
| 311 | + def x(self): | ||
| 312 | + pass | ||
| 313 | + | ||
| 314 | + @property | ||
| 315 | + def no_more_setting(self): | ||
| 316 | + return 42 | ||
| 317 | + | ||
| 318 | + @no_more_setting.setter | ||
| 319 | + @deprecated("no more setting") | ||
| 320 | + def no_more_setting(self, value): | ||
| 321 | + pass | ||
| 322 | + | ||
| 323 | + instance = Capybara() | ||
| 324 | + with self.assertWarnsRegex(DeprecationWarning, "x will go away soon"): | ||
| 325 | + instance.x | ||
| 326 | + | ||
| 327 | + with warnings.catch_warnings(): | ||
| 328 | + warnings.simplefilter("error") | ||
| 329 | + self.assertEqual(instance.no_more_setting, 42) | ||
| 330 | + | ||
| 331 | + with self.assertWarnsRegex(DeprecationWarning, "no more setting"): | ||
| 332 | + instance.no_more_setting = 42 | ||
| 333 | + | ||
| 334 | + def test_category(self): | ||
| 335 | + @deprecated("c will go away soon", category=RuntimeWarning) | ||
| 336 | + def c(): | ||
| 337 | + pass | ||
| 338 | + | ||
| 339 | + with self.assertWarnsRegex(RuntimeWarning, "c will go away soon"): | ||
| 340 | + c() | ||
| 341 | + | ||
| 342 | + def test_turn_off_warnings(self): | ||
| 343 | + @deprecated("d will go away soon", category=None) | ||
| 344 | + def d(): | ||
| 345 | + pass | ||
| 346 | + | ||
| 347 | + with warnings.catch_warnings(): | ||
| 348 | + warnings.simplefilter("error") | ||
| 349 | + d() | ||
| 350 | + | ||
| 233 | 351 | ||
| 234 | 352 | class AnyTests(BaseTestCase): | |
| 235 | 353 | def test_can_subclass(self): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -7,6 +7,7 @@ | |||
| 7 | 7 | import sys | |
| 8 | 8 | import types as _types | |
| 9 | 9 | import typing | |
| 10 | + import warnings | ||
| 10 | 11 | ||
| 11 | 12 | ||
| 12 | 13 | __all__ = [ | |
@@ -2135,7 +2136,12 @@ def method(self) -> None: | |||
| 2135 | 2136 | else: | |
| 2136 | 2137 | _T = typing.TypeVar("_T") | |
| 2137 | 2138 | ||
| 2138 | - def deprecated(__msg: str) -> typing.Callable[[_T], _T]: | ||
| 2139 | + def deprecated( | ||
| 2140 | + __msg: str, | ||
| 2141 | + *, | ||
| 2142 | + category: typing.Optional[typing.Type[Warning]] = DeprecationWarning, | ||
| 2143 | + stacklevel: int = 1, | ||
| 2144 | + ) -> typing.Callable[[_T], _T]: | ||
| 2139 | 2145 | """Indicate that a class, function or overload is deprecated. | |
| 2140 | 2146 | ||
| 2141 | 2147 | Usage: | |
@@ -2167,8 +2173,40 @@ def g(x: str) -> int: ... | |||
| 2167 | 2173 | ||
| 2168 | 2174 | """ | |
| 2169 | 2175 | def decorator(__arg: _T) -> _T: | |
| 2170 | - __arg.__deprecated__ = __msg | ||
| 2171 | - return __arg | ||
| 2176 | + if category is None: | ||
| 2177 | + __arg.__deprecated__ = __msg | ||
| 2178 | + return __arg | ||
| 2179 | + elif isinstance(__arg, type): | ||
| 2180 | + original_new = __arg.__new__ | ||
| 2181 | + has_init = __arg.__init__ is not object.__init__ | ||
| 2182 | + | ||
| 2183 | + @functools.wraps(original_new) | ||
| 2184 | + def __new__(cls, *args, **kwargs): | ||
| 2185 | + warnings.warn(__msg, category=category, stacklevel=stacklevel + 1) | ||
| 2186 | + # Mirrors a similar check in object.__new__. | ||
| 2187 | + if not has_init and (args or kwargs): | ||
| 2188 | + raise TypeError(f"{cls.__name__}() takes no arguments") | ||
| 2189 | + if original_new is not object.__new__: | ||
| 2190 | + return original_new(cls, *args, **kwargs) | ||
| 2191 | + else: | ||
| 2192 | + return original_new(cls) | ||
| 2193 | + | ||
| 2194 | + __arg.__new__ = staticmethod(__new__) | ||
| 2195 | + __arg.__deprecated__ = __new__.__deprecated__ = __msg | ||
| 2196 | + return __arg | ||
| 2197 | + elif callable(__arg): | ||
| 2198 | + @functools.wraps(__arg) | ||
| 2199 | + def wrapper(*args, **kwargs): | ||
| 2200 | + warnings.warn(__msg, category=category, stacklevel=stacklevel + 1) | ||
| 2201 | + return __arg(*args, **kwargs) | ||
| 2202 | + | ||
| 2203 | + __arg.__deprecated__ = wrapper.__deprecated__ = __msg | ||
| 2204 | + return wrapper | ||
| 2205 | + else: | ||
| 2206 | + raise TypeError( | ||
| 2207 | + "@deprecated decorator with non-None category must be applied to " | ||
| 2208 | + f"a class or callable, not {__arg!r}" | ||
| 2209 | + ) | ||
| 2172 | 2210 | ||
| 2173 | 2211 | return decorator | |
| 2174 | 2212 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments