Skip to content

How to use adapter factory to change signature depending on instance #263

@antonymilne

Description

@antonymilne

Hello and thank you for you this amazing library! I started using wrapt because I wanted access to the instance inside my decorator. I'd now like to take this a bit further to use instance in the adapter but not sure if it's possible.

I know that adapter factories can be used to alter a signature at runtime based on wrapped, but is it possible to somehow use instance also? Or am trying to do something that's just too weird here?

Possibly related: #232.

Here's some code to illustrate what I'm trying to do. Thank you very much!

import inspect
import wrapt

def adapter(self, a, b):
    pass

def different_adapter(self, c, d):
    pass

# This works great.
# You can also input a factory here but it only has access to wrapped, not instance.
# Is it possible to make an adapter factory where the adapter depends on instance?
@wrapt.decorator(adapter=adapter)
def change_signature(wrapped, instance, args, kwargs):
    pass

# Something like this maybe? But it's not right:
@wrapt.decorator
def change_signature_custom(wrapped, instance, args, kwargs):
    @wrapt.decorator(adapter=instance.adapter)
    def change_signature(wrapped, instance, args, kwargs):
        pass
    return change_signature(wrapped)


class Class:
    def __init__(self, adapter=None):
        self.adapter = adapter

    @change_signature
    def f(self):
        pass

    @change_signature_custom
    def g(self):
        pass


print(f"{inspect.getfullargspec(Class().f)=}") 
print(f"{inspect.signature(Class().f)=}\n")
# Works as expected and correctly gives:
# inspect.getfullargspec(Class().f)=FullArgSpec(args=['self', 'a', 'b'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
# inspect.signature(Class().f)=<Signature (a, b)>

print(f"{inspect.getfullargspec(Class(adapter=different_adapter).g)=}")
print(f"{inspect.signature(Class(adapter=different_adapter).g)=}\n")
# I'd like this to use the different_adapter but not sure how to get that working? Currently gives
# inspect.getfullargspec(Class(adapter=different_adapter).g)=FullArgSpec(args=['self'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})
# inspect.signature(Class(adapter=different_adapter).g)=<Signature ()>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions