Name | dek JSON |
Version |
1.4.2
JSON |
| download |
home_page | https://github.com/rec/dek |
Summary | 🎴 The decorator-decorator 🎴 |
upload_time | 2024-01-25 11:37:10 |
maintainer | |
docs_url | None |
author | Tom Ritchford |
requires_python | >=3.8 |
license | MIT |
keywords |
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
|
coveralls test coverage |
No coveralls.
|
🗃 `dek` - the decorator-decorator 🗃
`dek` decorates your decorators to diminish defects and drudgery.
Writing a Python decorator which takes no parameters isn't hard.
But writing a decorator with parameters is less easy - and more work
if you want to decorate classes, like `unittest.mock.patch` does.
`dek` is a decorator for decorators that does this deftly with a
single tiny function.
## Example 1: a simple decorator with dek
TASK: write a decorator `before` that prints a function's name and its
arguments before it executes.
With `dek`, it's a few lines:
import dek
@dek
def before(pfunc):
print(pfunc)
return pfunc()
Done! To use your new decorator:
@before
def phone(two, four=4):
print('Calling', two + two, four * four)
one(32, four=3)
# That prints something like:
#
# functools.partial(<function phone at 0x7fafa8072b00>, 32, four=3)
# Calling 64 9
`pfunc` is a [`functools.partial`](
https://docs.python.org/3/library/functools.html#functools.partial),
which represents the function call that `dek` intercepted. Your code
can call `pfunc` as often as you like, or add or change parameters.
## Example 2: same, without `dek`
import functools
def before(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print(func, args, kwargs)
return func(*args, **kwargs)
return wrapped
With `dek` it's a bit less work, but the real advantage comes when you have
a decorator with a parameter.
## Example 3: a decorator with a single optional parameter
Write a decorator `before` that prints a function's name, arguments
_and a label_ before it executes.
With `dek`, it's a trivial change from the previous solution.
import dek
@dek
def before(pfunc, label='dull'):
print(label, pfunc.func, *pfunc.args)
return pfunc()
@before
def add(x, y):
return x + y
@before(label='Exciting!')
def times(x, y):
return x * y
print('Result', add(2, times(2, 3)))
# Prints:
# Exciting! times 2 3
# dull add 2 6
# Result 8
## Example 4: same, without `dek`
Without `dek` it's actual work that's easy to get wrong.
import functools
def before(func=None, label='dull'):
if func is not None:
@functools.wraps(func)
def wrapped(*args, **kwargs):
print(label, func.__name, *args)
return func(*args, **kwargs)
return wrapped
return functools.partial(before, label=label)
## Example 5: Deferred mode
For finer control over function signatures there is deferred mode, which
lets you select what sort of signature you want to expose with a `wrapped`
function that you create.
@dek(defer=True)
def before(func, label='debug'):
def wrapped(foo, bar):
print(label, foo, bar)
return func(foo, bar)
return wrapped
## Example 6: Decorating a class
If you need to decorate methods on a class, there's a `methods` parameter to
select which methods get decorated.
import dek
@dek(methods='test')
def before(pfunc):
print('HERE', *pfunc.args)
return pfunc()
@before
class Class:
def test_one(self):
return 1
def test_two(self):
return 2
def three(self): # This won't get decorated
return 1
# Test at the command line:
>>> cl = Class()
>>> cl.test_one(), cl.test_two(), cl.three()
HERE 1
HERE 2
(1, 2, 3)
NOTES:
[This article](https://medium.com/p/1277a9ed34dc/) talks more about
decorators that take parameters and about `dek` in general.
For your advanced decorator desires, the PyPi module
[`decorator`](https://github.com/micheles/decorator/blob/master/docs/documentation.md) does not duplicate duties that `dek` does, but does
pretty anything else you could conceive of in a decorator library.
### [API Documentation](https://rec.github.io/dek#dek--api-documentation)
Raw data
{
"_id": null,
"home_page": "https://github.com/rec/dek",
"name": "dek",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "",
"author": "Tom Ritchford",
"author_email": "tom@swirly.com",
"download_url": "https://files.pythonhosted.org/packages/67/a2/185c123cc86bbe2f70c15e7624bc4e3a89b1c1ceff2836316b3aab89fbb9/dek-1.4.2.tar.gz",
"platform": null,
"description": "\ud83d\uddc3 `dek` - the decorator-decorator \ud83d\uddc3\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(<function phone at 0x7fafa8072b00>, 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 >>> cl = Class()\n >>> 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",
"bugtrack_url": null,
"license": "MIT",
"summary": "\ud83c\udfb4 The decorator-decorator \ud83c\udfb4",
"version": "1.4.2",
"project_urls": {
"Documentation": "https://rec.github.io/dek",
"Homepage": "https://github.com/rec/dek",
"Repository": "https://github.com/rec/dek"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "65e761891051cf9abdbdcdb89aaeb910372f646136643537e4a211bf74a4ec01",
"md5": "2fdc3ea7992fc69b969cf404b595fb0e",
"sha256": "4324b9fc90d9d5f6e8957dd208c09f95d23cbfc7d488db0d1eb86d830e055f50"
},
"downloads": -1,
"filename": "dek-1.4.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "2fdc3ea7992fc69b969cf404b595fb0e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 6411,
"upload_time": "2024-01-25T11:37:09",
"upload_time_iso_8601": "2024-01-25T11:37:09.075090Z",
"url": "https://files.pythonhosted.org/packages/65/e7/61891051cf9abdbdcdb89aaeb910372f646136643537e4a211bf74a4ec01/dek-1.4.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "67a2185c123cc86bbe2f70c15e7624bc4e3a89b1c1ceff2836316b3aab89fbb9",
"md5": "995d3eb046fcc819953fcb453526c317",
"sha256": "9c1fe968538d773e2f13bd27241941b6af73b70a898afb0e06d24054b9f4fad9"
},
"downloads": -1,
"filename": "dek-1.4.2.tar.gz",
"has_sig": false,
"md5_digest": "995d3eb046fcc819953fcb453526c317",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 4756,
"upload_time": "2024-01-25T11:37:10",
"upload_time_iso_8601": "2024-01-25T11:37:10.931031Z",
"url": "https://files.pythonhosted.org/packages/67/a2/185c123cc86bbe2f70c15e7624bc4e3a89b1c1ceff2836316b3aab89fbb9/dek-1.4.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-01-25 11:37:10",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "rec",
"github_project": "dek",
"travis_ci": true,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "dek"
}