Skip to main content

Attach Me

Travis Coveralls github PyPI PyPI - Wheel PyPI - Python Version PyPI - License

A library for attaching additional functionality around existing functions, such as before or after execution, or given a raised exception or specific return value.

@attach(on_before=lambda: print('Initializing connection'),
        on_after=lambda: print('Connect successfully established'),
        on_error=lambda x: print('Erred establishing connection: %s' % x),
        on_return=lambda x: print('Returned connection: %s' % x))
def connection(conn_str, params):
    conn = db(conn_str, params)
    return db.open()

Installation

The latest version of attach.me is available via pip:

pip install attach.me

Alternatively, you can download and install from source:

python setup.py install

Getting Started

The attach function contains the following signature:

@attach(on_before=None, on_after=None, on_error=None, on_return=None,
        override_error=False, override_return=False, before_has_kwargs=False)
def func(...)
    ...

It serves as both a function decorator, and a runnable wrapper and is configurable through it’s dynamic parameters. Most of which are function callbacks which allow the user to highly configure the additional behavior.

Before / After Execution

Either prior to the wrapped function being executed, or afterwards, another function can be called. The most simplistic use case for this is logging the beginning and ending of execution of a function.

@attach(on_before=lambda: logging.info('Execution began'), on_after=lambda: logging.info('Execution ended'))
def func():
    ...

If an exception is raised by the wrapped function (or the on_before function), the on_after function isn’t called.

More complex usage comes from digesting the parameters meant for the wrapped function and transforming them in some way. This is accomplished by simply returning an object from the on_before function and the values will be used instead of the ones passed in.

def sanitize(string):
    # Do some stuff
    return new_string

@attach(on_before=lambda x: sanitize(x))
def func(string):
    ...

If an iterable is returned, it is used as the args of the wrapped function. The before_with_kwargs argument can be set to True to specify that the return value be used as the kwargs of the wrapped function (which means it should be a dictionary. If an iterable is returned and this parameter is set, the last value is used as the kwargs, and the rest as the args.

def sanitize(string):
    # Do some stuff
    return new_string

@attach(on_before=lambda x: sanitize(x), {'use_ssl': True})
def func(string):
    ...

Error Handling

The on_error can be used to execute a function if an exception is raised. By default, the original exception is still raised after the on_error callback is called. This can be changed by setting override_error to True. This can be used to instead return a value or raise a different exception.

def on_error(e):
    print('Caught error: ' + str(e))
    if isinstance(e, TypeError):
        return -1
    raise

@attach(on_error=on_error, override_error=True)
def func():
    raise TypeError

# -1 is returned instead of raising TypeError

Return Value Handling

Like raised exception, return values can consumed by a on_return function in a similar manner. By default, the original return value is still returned after the on_return callback is called. This can be changed by setting override_return to True. A common use case for this is when interacting with functions that yield a return value that indicates a failed state (like -1 or None), while other values indicate a successful state (like 0 or an object). This behavior can be transformed into a simple bool True or False return value instead.

def on_return(val):
    if val in (-1, None):
        return False
    return True

@attach(on_return=on_return, override_return=True)
def func()
    return -1

# False is returned instead of -1

If an exception is raised by the wrapped function (or the on_before or on_after functions), the on_return function isn’t called.

Advanced Usage

Instead of using as a decorator, attach can be used as an instead for wrapping an arbitrary number of function calls. This can be achieved via the run method.

def func_a():
    ...

def func_b():
    ...

attacher = attach(on_before=..., on_after=..., on_error=..., on_return=...)

# Using same configured attach instance
attach.run(func_a, args, kwargs)
attach.run(func_b, args, kwargs)

Besides using the provided run method, like any decorator functions can be locally wrapped, passed around, and executed.

def func():
    ...

attacher = attach(on_before=..., on_after=..., on_error=..., on_return=...)
attach_func = attacher(func)
attach_func(args, kwargs)

# Or as a one-off like so
attach(...)(func)(args, kwargs)

Each of the function parameters that can be passed into attach, can actually be configured to accepts different number of parameters depending on the function. They can each either accept 0 parameters, the parameters that would be typically passed in, or the wrapped function’s args and kwargs in addition to the parameters typically given.

Optionally passing in the args and kwargs allows for building more complex callback functions. Each of the possible function variations are shown below.

def on_before(): ...
def on_before(*args, **kwargs): ...

def on_after(): ...
def on_after(*args, **kwargs): ...

def on_error(): ...
def on_error(error): ...
def on_error(error, *args, **kwargs): ...

def on_return(): ...
def on_return(value): ...
def on_return(value, *args, **kwargs): ...

Contribution

Contributions or suggestions are welcome! Feel free to open an issue if a bug is found or an enhancement is desired, or even a pull request.

Changelog

All changes and versioning information can be found in the CHANGELOG.

License

Copyright (c) 2018 Jared Gillespie. See LICENSE for details.

Metadata

Release files for attach.me 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for attach.me 0.1.1
File Size Uploaded Provenance
attach.me-0.1.1.tar.gz 7.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for attach.me 0.1.1
File Interpreter ABI Platform
attach.me-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 14.5 kB

Release files / attach.me-0.1.1.tar.gz

Download URL attach.me-0.1.1.tar.gz
Size 7.2 kB
Tags Source
SHA-256 checksum
How to use checksums
84ed03b95ddeec38f2f3111a43a192a6aff7b492a5bfd52b478bf6dc907e2c6d
BLAKE2b-256 checksum
How to use checksums
2757b4792161ca3e7e403e1c112cbf5970d0fa98b6886c4c99fb2509d0a9c5cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / attach.me-0.1.1-py3-none-any.whl

Download URL attach.me-0.1.1-py3-none-any.whl
Size 7.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
84f155a1be4de633be600756964c007ea125dca6064313a2c223a07ca8c5a223
BLAKE2b-256 checksum
How to use checksums
184a35b1dc6d434cff75db1ad141d2dfc8584b189d39ea640a170eaa7cb118a8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Security for attach.me 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page