{"id":4498,"library":"decopatch","title":"decopatch Library","description":"decopatch is a Python library designed to simplify the creation of decorators. It addresses the common challenge in Python where writing decorators requires explicit handling of both with-parenthesis and without-parenthesis usages. The library is currently at version 1.4.10 and receives regular minor updates, maintaining an active development status.","status":"active","version":"1.4.10","language":"en","source_language":"en","source_url":"https://github.com/smarie/python-decopatch","tags":["decorator","function","class","utility","parenthesis"],"install":[{"cmd":"pip install decopatch","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"An optional companion library that works with decopatch to create truly signature-preserving function wrappers, solving problems that decopatch focuses on decorator syntax handling.","package":"makefun","optional":true}],"imports":[{"note":"Primary decorator factory for functions.","symbol":"function_decorator","correct":"from decopatch import function_decorator"},{"note":"Decorator factory for classes.","symbol":"class_decorator","correct":"from decopatch import class_decorator"},{"note":"Generic decorator factory for decorators that can be applied to both functions and classes. `function_decorator` and `class_decorator` are presets for this.","symbol":"decorator","correct":"from decopatch import decorator"},{"note":"Symbols used in 'double-flat mode' for more compact decorator definitions, representing the decorated item, positional arguments, and keyword arguments respectively.","symbol":"WRAPPED, F_ARGS, F_KWARGS","correct":"from decopatch import WRAPPED, F_ARGS, F_KWARGS"}],"quickstart":{"code":"from decopatch import function_decorator\n\n@function_decorator\ndef add_tag(tag='hi!'):\n    \"\"\"\n    Example decorator to add a 'tag' attribute to a function.\n    :param tag: the 'tag' value to set on the decorated function.\n    \"\"\"\n    def _apply_decorator(f):\n        \"\"\"\n        This method is called when `@add_tag` is used on a function `f`.\n        It should return a replacement for `f`.\n        \"\"\"\n        setattr(f, 'tag', tag)\n        return f\n    return _apply_decorator\n\n# Usage without parenthesis\n@add_tag\ndef foo1():\n    pass\nassert foo1.tag == 'hi!'\n\n# Usage with empty parenthesis\n@add_tag()\ndef foo2():\n    pass\nassert foo2.tag == 'hi!'\n\n# Usage with arguments\n@add_tag('hello')\ndef foo3():\n    pass\nassert foo3.tag == 'hello'\n\nprint(f\"foo1 tag: {foo1.tag}\")\nprint(f\"foo2 tag: {foo2.tag}\")\nprint(f\"foo3 tag: {foo3.tag}\")","lang":"python","description":"This quickstart demonstrates the `function_decorator` to create a decorator that seamlessly works with and without parentheses, as well as with explicit arguments. The decorator `add_tag` adds a `tag` attribute to the decorated function."},"warnings":[{"fix":"Avoid using `enable_stack_introspection=True` on Python 3.8+ or consult documentation for alternatives if introspection is critical.","message":"Enabling the experimental 'stack introspection' feature (`enable_stack_introspection=True`) now raises an explicit `NotImplementedError` on Python 3.8 and newer versions. Users relying on this beta feature on recent Python versions will encounter errors.","severity":"breaking","affected_versions":"1.4.9+"},{"fix":"Ensure `decopatch` is updated to at least version 1.4.6 to benefit from fixes related to variable-positional argument handling. Rely primarily on `decopatch`'s provided constructs for decorator creation to avoid manual signature manipulation errors.","message":"While `decopatch` significantly simplifies decorator creation, prior to version 1.4.6, there were reported bugs concerning incorrect injection of arguments, particularly when variable-positional arguments (`*args`) were present in the decorated function's signature. Although fixed, this highlights a potential 'gotcha' area for complex function signatures if not fully leveraging `decopatch`'s mechanisms or if custom wrapper logic is introduced without careful consideration.","severity":"gotcha","affected_versions":"<1.4.6"},{"fix":"Always use `decopatch`'s decorator factories (`@function_decorator`, `@class_decorator`, `@decorator`) as intended to handle the parenthesis detection automatically, rather than implementing manual checks within your decorator logic.","message":"The primary problem `decopatch` solves is enabling decorators to work with or without parentheses seamlessly. Manually attempting to detect how a decorator was called (e.g., by checking `callable(args[0])`) is a common and error-prone workaround in Python. Using `decopatch`'s `function_decorator`, `class_decorator`, or `decorator` correctly abstracts this complexity, preventing a significant footgun for decorator authors.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-12T00:00:00.000Z","next_check":"2026-07-11T00:00:00.000Z"}