Skip to main content

Update the value of args and kwargs destined for a callable.

Project description

argupdate

This package is used for updating values in the args/kwargs destined to a function. This is particularly useful for decorators that want to modify the values passed into the decorated function.

By introspecting the function the args/kwargs are destined for, it knows the names of all arguments in your args (and of course your kwargs since that is a dict). Because of this, you are able to provide updated values by name of the argument.

By accepting a special callable, we also provide a way to dynamically update the value of an argument at runtime.

simple example

The function we want to modify a value for

from typing import Optional

def foo(arg_1: int, arg_2: bool, arg_3: Optional[str] = None) -> None:
    print(arg_1, arg_2, arg_3)

Let's say for some reason we always want arg_2 to be False, no matter what the caller passes in.

import functools
from argupdate import update_parameter_value
from typing import Optional

def arg_2_always_false(func):
    # This is the new value for `arg_2`
    updated_values = {
        'arg_2': False
    }
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        # Here we update the value.
        updated_args, updated_kwargs = update_parameter_value(func, updated_values, args, kwargs)
        return func(*updated_args, **updated_kwargs)
    return wrapper

@arg_2_always_false
def foo(arg_1: int, arg_2: bool, arg_3: Optional[str] = None) -> None:
    print(arg_1, arg_2, arg_3)

Admittedly, this is a contrived example. You could've just set set the second parameter in args to False without using this library. But, even in this small, contrived example, you've gained some decoupling by using argupdate. As long as the name of the parameter stays the same, you do not have to count on it being the second parameter in the argument list.

more advanced example

You can also use a special callable as the new value. This allows you to set the new value based upon the signature of the function and other argument's values.

Here is an example taken from a real project. This project wrapped multiple other backend libraries. These libraries all had methods that took a handle argument as an int. Except one. This one library required the handle argument as a string that looked like [HANDLE:0x0000001].

Instead of repeating code everywhere checking which type of handle we should pass in, we created a decorator that did it for us.

import functools
import inspect
from typing import Any, Mapping, Sequence

from argupdate import update_parameter_value, ValueUpdater
from utils import stringify_int


def handle_stringifier(func):
    class update_handle(ValueUpdater):
        def __call__(self,
                     original_value: Any,
                     signature: inspect.Signature,
                     orig_args: Sequence[Any],
                     orig_kwargs: Mapping[str, Any]) -> Any:
            if isinstance(original_value, int):
                return stringify_int(int)

            return original_value


    updated_values = {
        # update_handle will be used to create the value for the argument
        # called `handle`
        'handle': update_handle
    }

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        updated_args, updated_kwargs = update_parameter_value(func, updated_values, args, kwargs)
        return func(*updated_args, **updated_kwargs)

    return wrapper


@handle_stringifier
def weird_handle_taker(handle: int) -> None:
    ...

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

argupdate-0.0.1.tar.gz (4.2 kB view hashes)

Uploaded Source

Built Distribution

argupdate-0.0.1-py3-none-any.whl (5.3 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page