开发者

Python 2.x metaclass generated wrappers break inspect

开发者 https://www.devze.com 2023-04-12 04:50 出处:网络
I\'m having an issue where I have wrapped some class methods using a metaclass, but now if I use the help() built-in the methods are displayed as the wrapper instead of the original method.

I'm having an issue where I have wrapped some class methods using a metaclass, but now if I use the help() built-in the methods are displayed as the wrapper instead of the original method.

# Example:

class MetaBuilderModule(type):

    @staticmethod
    def time_method(method):
        @functools.wraps(method)
        def __wrapper(self, *args, **kwargs):
            if self.__timingstatus__[method.__name__]:
                return method(self, *args, **kwargs)

            else:
                # Set the timing status of the method to True so that we don't
                # time any inherited methods.
                self.__timingstatus__[method.__name__] = True

                start = time.time()
                finish = None
                result = None

                # Put the result behind a try / except so that if we get an error
                # within the method we can still reset the timing status.
                try:
                    result = method(self, *args, **kwargs)
                except Exception:
                    exc_type, exc_value, exc_traceback = sys.exc_info()
                    traceback.print_exception(exc_type, exc_value, exc_traceback)
                    self.__timingstatus__[method.__name__] = False
                    return False

                finish = time.time()

                sys.stdout.write('Instance method \'%s\' of BuilderModule class'
                    ' took %0.3fs to execute.\n' %(method.__name__, (finish - start)))

                # Reset the timing status.
                self.__timingstatus__[method.__name__] = False
                return result

        return __wrapper


    def __new__(cls, name, bases, attrs):
        # Create the __timingstatus__ dictionary that helps stop timers being
        # triggered by inherited methods.
        attrs['__timingstatus__'] = dict()

        for attr in ['__init__', 'run']:
            attrs['__timingstatus__'][attr] = False

            if not attr in attrs:
                continue

            attrs[attr] = cls.time_method(attrs[attr])

        return super(MetaBuilderModule, cls).__new__(cls, name, bases, attrs)

As you can see I have added the @functools.wraps decorator to the __wrapper method so that at least I get the proper method name, but I still don't get the proper arguments.

Example:

 |  Methods defined here:
 |  
 |  开发者_JAVA技巧  __init__(self, *args, **kwargs)

I've seen some articles suggesting monkey patching inspect.getargspec but I can't see this being a practical solution.

Anyone have any other black magic they could suggest?

Cheers,

CB

0

精彩评论

暂无评论...
验证码 换一张
取 消