@wrapt decorators and monkey patching

416 Views Asked by At

@wrapt conditional monkey patching with decorators

Wrapt has two feature

  • best practice for decorators
  • monkey patching

I'm doing both to be able to conditionally change method called. I've provided an example which is based on pandas version. While this works, I have resorted to barebones monkey patching and not using wrapt capability. How can wrapt be used to monkey patch the alternate method?

import pandas as pd
import wrapt, inspect
from distutils.version import StrictVersion
def alt_impl(alt_fn, cond):
    @wrapt.decorator
    def wrapper(wrapped, instance, args, kwargs):
        nonlocal alt_fn
        if cond():
            # @staticmethod and @classmethod need to navigate to actual function
            if not inspect.isfunction(alt_fn):
                alt_fn = alt_fn.__func__
            # class instance methods need to be bound to class instance
            if instance is not None:
                alt_fn = alt_fn.__get__(instance, instance.__class__)
            return alt_fn(*args, **kwargs)
        else:
            return wrapped(*args, **kwargs)
    return wrapper

Example usage

class alt_impl_example():
    def upgraded_pandas(self, args):
        print(f"upgraded {pd.__version__}") 

    @alt_impl(upgraded_pandas, lambda: StrictVersion(pd.__version__) >= StrictVersion("1.0.0")) 
    def pandas(self, args): 
        print(pd.__version__) 

t = alt_impl_example()
t.pandas({})
0

There are 0 best solutions below