{"id":23344383,"url":"https://github.com/rec/dek","last_synced_at":"2026-02-03T16:15:21.621Z","repository":{"id":57418059,"uuid":"277113000","full_name":"rec/dek","owner":"rec","description":"🎴 The decorator-decorator 🎴","archived":false,"fork":false,"pushed_at":"2024-03-20T18:24:54.000Z","size":666,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-24T04:04:13.036Z","etag":null,"topics":["decorators","python","tools"],"latest_commit_sha":null,"homepage":"https://rec.github.io/dek/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rec.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":"FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"rec"}},"created_at":"2020-07-04T13:15:44.000Z","updated_at":"2023-05-10T20:07:50.000Z","dependencies_parsed_at":"2023-02-18T18:01:04.744Z","dependency_job_id":"56959c55-eebf-4175-aed3-d5973044e231","html_url":"https://github.com/rec/dek","commit_stats":{"total_commits":66,"total_committers":1,"mean_commits":66.0,"dds":0.0,"last_synced_commit":"e2c18b728c93db1e688db4536e0ee7ad585fcba6"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rec%2Fdek","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rec%2Fdek/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rec%2Fdek/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rec%2Fdek/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rec","download_url":"https://codeload.github.com/rec/dek/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247792920,"owners_count":20996896,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["decorators","python","tools"],"created_at":"2024-12-21T06:26:29.868Z","updated_at":"2026-02-03T16:15:21.590Z","avatar_url":"https://github.com/rec.png","language":"Python","funding_links":["https://github.com/sponsors/rec"],"categories":[],"sub_categories":[],"readme":"🗃 `dek` - the decorator-decorator 🗃\n\n`dek` decorates your decorators to diminish defects and drudgery.\n\nWriting a Python decorator which takes no parameters isn't hard.\n\nBut writing a decorator with parameters is less easy - and more work\nif you want to decorate classes, like `unittest.mock.patch` does.\n\n`dek` is a decorator for decorators that does this deftly with a\nsingle tiny function.\n\n## Example 1: a simple decorator with dek\n\nTASK: write a decorator `before` that prints a function's name and its\narguments before it executes.\n\nWith `dek`, it's a few lines:\n\n    import dek\n\n    @dek\n    def before(pfunc):\n        print(pfunc)\n        return pfunc()\n\nDone! To use your new decorator:\n\n    @before\n    def phone(two, four=4):\n        print('Calling', two + two, four * four)\n\n    one(32, four=3)\n\n    # That prints something like:\n    #\n    # functools.partial(\u003cfunction phone at 0x7fafa8072b00\u003e, 32, four=3)\n    # Calling 64 9\n\n`pfunc` is a [`functools.partial`](\nhttps://docs.python.org/3/library/functools.html#functools.partial),\nwhich represents the function call that `dek` intercepted.  Your code\ncan call `pfunc` as often as you like, or add or change parameters.\n\n## Example 2: same, without `dek`\n\n    import functools\n\n    def before(func):\n        @functools.wraps(func)\n        def wrapped(*args, **kwargs):\n            print(func, args, kwargs)\n            return func(*args, **kwargs)\n\n        return wrapped\n\nWith `dek` it's a bit less work, but the real advantage comes when you have\na decorator with a parameter.\n\n## Example 3: a decorator with a single optional parameter\n\nWrite a decorator `before` that prints a function's name, arguments\n_and a label_ before it executes.\n\nWith `dek`, it's a trivial change from the previous solution.\n\n    import dek\n\n    @dek\n    def before(pfunc, label='dull'):\n        print(label, pfunc.func, *pfunc.args)\n        return pfunc()\n\n    @before\n    def add(x, y):\n        return x + y\n\n    @before(label='Exciting!')\n    def times(x, y):\n        return x * y\n\n    print('Result', add(2, times(2, 3)))\n\n    # Prints:\n    #   Exciting! times 2 3\n    #   dull add 2 6\n    #   Result 8\n\n\n## Example 4: same, without `dek`\n\nWithout `dek` it's actual work that's easy to get wrong.\n\n    import functools\n\n    def before(func=None, label='dull'):\n        if func is not None:\n            @functools.wraps(func)\n            def wrapped(*args, **kwargs):\n                print(label, func.__name, *args)\n                return func(*args, **kwargs)\n\n            return wrapped\n\n        return functools.partial(before, label=label)\n\n\n## Example 5: Deferred mode\n\nFor finer control over function signatures there is deferred mode, which\nlets you select what sort of signature you want to expose with a `wrapped`\nfunction that you create.\n\n    @dek(defer=True)\n    def before(func, label='debug'):\n        def wrapped(foo, bar):\n            print(label, foo, bar)\n            return func(foo, bar)\n\n        return wrapped\n\n## Example 6: Decorating a class\n\nIf you need to decorate methods on a class, there's a `methods` parameter to\nselect which methods get decorated.\n\n\n    import dek\n\n    @dek(methods='test')\n    def before(pfunc):\n        print('HERE', *pfunc.args)\n        return pfunc()\n\n    @before\n    class Class:\n        def test_one(self):\n            return 1\n\n        def test_two(self):\n            return 2\n\n        def three(self):  # This won't get decorated\n            return 1\n\n\n    # Test at the command line:\n    \u003e\u003e\u003e cl = Class()\n    \u003e\u003e\u003e cl.test_one(), cl.test_two(), cl.three()\n    HERE 1\n    HERE 2\n    (1, 2, 3)\n\nNOTES:\n\n[This article](https://medium.com/p/1277a9ed34dc/) talks more about\ndecorators that take parameters and about `dek` in general.\n\nFor your advanced decorator desires, the PyPi module\n[`decorator`](https://github.com/micheles/decorator/blob/master/docs/documentation.md) does not duplicate duties that `dek` does, but does\npretty anything else you could conceive of in a decorator library.\n\n\n### [API Documentation](https://rec.github.io/dek#dek--api-documentation)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frec%2Fdek","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frec%2Fdek","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frec%2Fdek/lists"}