{"record":{"id":"821253c48a12bc0a","repo":"python/cpython","slug":"deprecated-decorator-with-non-none-category-must","errorCode":null,"errorMessage":"@deprecated decorator with non-None category must be applied to a class or callable, not {arg!r}","messagePattern":"@deprecated decorator with non-None category must be applied to a class or callable, not (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_py_warnings.py","lineNumber":867,"sourceCode":"            arg.__deprecated__ = __new__.__deprecated__ = msg\n            __init_subclass__.__deprecated__ = msg\n            return arg\n        elif callable(arg):\n            import functools\n            import inspect\n\n            @functools.wraps(arg)\n            def wrapper(*args, **kwargs):\n                _wm.warn(msg, category=category, stacklevel=stacklevel + 1)\n                return arg(*args, **kwargs)\n\n            if inspect.iscoroutinefunction(arg):\n                wrapper = inspect.markcoroutinefunction(wrapper)\n\n            arg.__deprecated__ = wrapper.__deprecated__ = msg\n            return wrapper\n        else:\n            raise TypeError(\n                \"@deprecated decorator with non-None category must be applied to \"\n                f\"a class or callable, not {arg!r}\"\n            )\n\n\n_DEPRECATED_MSG = \"{name!r} is deprecated and slated for removal in Python {remove}\"\n\n\ndef _deprecated(name, message=_DEPRECATED_MSG, *, remove, _version=sys.version_info):\n    \"\"\"Warn that *name* is deprecated or should be removed.\n\n    RuntimeError is raised if *remove* specifies a major/minor tuple older than\n    the current Python version or the same version but past the alpha.\n\n    The *message* argument is formatted with *name* and *remove* as a Python\n    version tuple (e.g. (3, 11)).\n\n    \"\"\"","sourceCodeStart":849,"sourceCodeEnd":885,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_py_warnings.py#L849-L885","documentation":"warnings.deprecated(category=None) can wrap anything (it is a no-op passthrough used for static typing), but with a non-None category it must install a runtime wrapper that emits a warning on call or instantiation. That is only possible for classes and callables, so decorating any other object (an int, module, instance, property object) raises TypeError at decoration time.","triggerScenarios":"@warnings.deprecated('msg') applied to a module-level variable (e.g. an int constant), an imported module object, a dataclass field/property, or the result of another decorator that returned a non-callable; assigning the decorator to an instance attribute.","commonSituations":"Trying to deprecate a constant or module rather than its accessor function; decorating a property getter inside a class body; stacking decorators in the wrong order so deprecated receives a non-callable intermediate value.","solutions":["Deprecate a getter function that returns the constant, and warn there","If the target is a module, deprecate its public functions/classes individually, or emit warnings.warn at module import in a wrapper module","If you only need static-analysis marking with no runtime warning, call deprecated with category=None on a suitable target, or set __deprecated__ manually on the object"],"exampleFix":"// before\nLIMIT = 1000\nLIMIT = warnings.deprecated('use LIMIT_V2')(LIMIT)  # TypeError\n\n# after\ndef get_limit():\n    warnings.warn('LIMIT is deprecated; use LIMIT_V2', DeprecationWarning, stacklevel=2)\n    return 1000","handlingStrategy":"type-guard","validationCode":"import typing\ndef deprecated_or_identity(obj):\n    return warnings.deprecated('use something else')(obj) if callable(obj) else obj","typeGuard":"def is_decoratable(obj: object) -> bool:\n    import inspect\n    return inspect.isclass(obj) or callable(obj)","tryCatchPattern":null,"preventionTips":["Only decorate functions, methods, and classes with category set","To deprecate a constant, wrap access in a deprecated getter function","Run the test suite after adding decorators: misapplication fails at import"],"tags":["warnings","deprecated","typeerror","decorator","stdlib"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}