A lightweight pure-Python implementation of Go's defer
Project description
deferrable-py
A lightweight pure-Python implementation of Go's "defer"
Features
- The developers can defer operations, dubbed deferred operations.
- Only a deferrable async callable object can take both sync and async callables as deferred operations.
- The deferred operations will be run in the LIFO order.
Example
Suppose we have a deferrable function.
from deferrable import defer, deferrable
@deferrable
def do_something():
print('in-1')
defer(lambda: print('out-1'))
print('in-2')
defer(lambda: print('out-2'))
do_something()
The output would be:
in-1
in-2
out-2
out-1
Why it matters?
Suppose that you want to close a file after a chain of operations. Generally, you can do this.
def func():
with open('foo.txt', 'r') as fp:
fp.write('abcdef123456')
# NOTE: fp is now closed as the code exits the context of "open()".
# NOTE: At this point, fp is no longer useful.
# end of def
However, what if fp is still needed later in the same method.
With this library, you can simply defer fp.close() to the end of callable invocation.
from deferrable import defer, deferrable
@deferrable
def func():
fp = open('foo.txt', 'r')
defer(lambda: fp.close()) # <-- Define a deferred operation
# NOTE: You can also simply write:
#
# defer(functools.partial(lambda fp: fp.close(), fp))
#
# if you want to deal with the late binding problem right away.
fp.write('abcdef123456')
...
# NOTE: No more code here
# end of def
When the invocation of func() completes successfully or ends with error, the deferred operation will be invoked.
Please note that the deferred operation will not alter the returned value of the deferrable callable.
Example Use Cases
- Flexible cleanup for each test case
from unittest import TestCase from deferrable import defer, deferrable def create_obj(id): ... def delete_obj(id): ... class UnitTest(TestCase): @deferrable def test_happy_path(self): o = create_obj('alpha') # <-- create a test obj defer(lambda: delete_obj('alpha')) # <-- defer the test obj deletion to the end ... # <-- the rest of the test
Some test frameworks provide this mechanism. This is all about being framework-agnostic.
- Handle the data temporarily.
from os import unlink from typing import Iterator from deferrable import defer, deferrable def load_blob(url) -> Iterator[bytes]: ... def upload_blob(local_file_path): ... @deferrable def transfer(source_url, destination_url): tmp_file_path = ... with open(tmp_file_path, 'wb') as f: for b in load_blob(source_url): f.write(b) defer(lambda: unlink(tmp_file_path)) upload_blob(tmp_file_path)
API Reference
Decorator deferrable.deferrable(func: Callable)
Make the wrapped callable capable of having deferred operations.
The func parameter must be callable.
from deferrable import deferrable
@deferrable
def func_a():
...
@deferrable
async def func_b():
...
Function deferrable.defer(op: Callable[[], None]|Callable[[], Awaitable[None]])
Defer the given operation to be executed at the end of the callable invocation,i.e., on the call exit.
The op parameter must be a callable which takes no parameters. Any returning values will be disregarded.
from deferrable import deferrable, defer
@deferrable
def func_a():
...
defer(lambda: ...)
@deferrable
def func_b():
...
defer(lambda: ...) # A normal function can be used as a deferred operation.
defer(lambda: ...) # A normal function can be used as a deferred operation.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file deferrable_py-0.1.0.tar.gz.
File metadata
- Download URL: deferrable_py-0.1.0.tar.gz
- Upload date:
- Size: 8.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef4ce4340a58f0fa9caaf855a50af3a0503d03eb269897eac9ecc9dec283d15b
|
|
| MD5 |
86a27d5942e0b96bad9782902954a75f
|
|
| BLAKE2b-256 |
3800c61161f446938179e60346efd4d5b5749dc4a2033d00e3298cbf7e3a7e56
|
Provenance
The following attestation bundles were made for deferrable_py-0.1.0.tar.gz:
Publisher:
package-release.yml on shiroyuki/deferrable-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deferrable_py-0.1.0.tar.gz -
Subject digest:
ef4ce4340a58f0fa9caaf855a50af3a0503d03eb269897eac9ecc9dec283d15b - Sigstore transparency entry: 230282629
- Sigstore integration time:
-
Permalink:
shiroyuki/deferrable-py@800f63884e706c5d37e078f768b9ff8290b72146 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/shiroyuki
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
package-release.yml@800f63884e706c5d37e078f768b9ff8290b72146 -
Trigger Event:
push
-
Statement type:
File details
Details for the file deferrable_py-0.1.0-py3-none-any.whl.
File metadata
- Download URL: deferrable_py-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
87da40db91d906ed3c73329dfcf239ef3a04765ef55a62765304366be6302bcd
|
|
| MD5 |
63e811b71d81f6bc102199c3af2e2b74
|
|
| BLAKE2b-256 |
ec21ddfb164420f624e70b9e15cd449770f18940ee23597a27fcbfd909943a19
|
Provenance
The following attestation bundles were made for deferrable_py-0.1.0-py3-none-any.whl:
Publisher:
package-release.yml on shiroyuki/deferrable-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
deferrable_py-0.1.0-py3-none-any.whl -
Subject digest:
87da40db91d906ed3c73329dfcf239ef3a04765ef55a62765304366be6302bcd - Sigstore transparency entry: 230282634
- Sigstore integration time:
-
Permalink:
shiroyuki/deferrable-py@800f63884e706c5d37e078f768b9ff8290b72146 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/shiroyuki
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
package-release.yml@800f63884e706c5d37e078f768b9ff8290b72146 -
Trigger Event:
push
-
Statement type: