Los Techies : Blogs about software and anything tech!

Adventures in Meta programming in Python: im_class, __import__, __getattribute__


With my recent work in Python win32 programming I’ve had a real need for AAA style mocking framework. Unable to find anything that I’ve been completely happy with I started my own simple mocking framework and got to learn some Python style meta programming  in the process. I’ve found out a lot about the depth of the Python 2.x object model over the last 2 weeks and here are some of the nicer things I’ve found (updated as per Chris Taveres below):

function_class = MyClass.foo.im_class

This is useful if you pass in an instance method  somewhere and you want to be able to access its attached class.  Decorators on instance methods normally use this, but I needed it to get a nicer syntax on my asserts, I wanted this:

 

assertCalled(FakeRepo.get)

 

So now when I want to track what class is passed in I just have to start with the following:

def assertCalled(method):
    classdef = method.im_class #I get the method and the class in one parameter!

module = __import__(“foomodule”)

this creates a module import by string. This becomes super powerful say if you wanted to replace functionality on a module, but didn’t know its name before hand.  In my case I wanted to be able to patch in a replacement method for mocking and then put it back when I was done, and I didn’t want to have to keep passing in the module name on resets. The only downside to it so far is it behaves a little quirky with packages and you have walk your module hierarchy to get it to do what you want

example of patching originals back into the module:

for mod, original in _originals.items():  #key is a combination of module name and methodname, value is the original function itself
    modulename = mod[0]
    methodname = mod[1]
    module = __import__(modulename)  #this is the magic. if module name has no package aka : “barmod” this will work. if its “foopackage.barmod” it’ll import the “foopackage” 
    for i in modulename.split(".")[1:]: #works down the chain 
        module = getattr(module, i) #resets the module variable with the lower hierarchy module 
    setattr(module, methodname, original) #actually pass the original function object back onto the module.

 

MyClass.__getattribute__ = interception

__getattribute__ is called when any attribute is accessed on a class including __getattribute__ itself which is a bit silly.  This was the primary engine of my mocking framework as it allowed me to record all calls to the methods on a mocked class.  Just remember when you use this to have it not call itself or you’ll be in endless recursion!

example:

class MyClass(object):

    def stuff(self):
        pass

def interceptor(self, name):
    if name == "__getattribute__": #guard condition against calling itself
        return object.__getattribute__(self, name)
        #whatever interception logic you need here

MyClass.__getattribute__ = interceptor
= MyClass()
m.stuff() #interception logic will be called here

 

I’m just starting to dip into the Python object model now and I’ll try and share what I find over the next few weeks.

Kick It on DotNetKicks.com
Posted Jan 08 2010, 12:03 AM by Ryan Svihla
Filed under:

Comments

Twitter Trackbacks for Adventures in Meta programming in Python: im_class, __import__, __getattribute__ - Polyglots R Us - Los [lostechies.com] on Topsy.com wrote Twitter Trackbacks for Adventures in Meta programming in Python: im_class, __import__, __getattribute__ - Polyglots R Us - Los [lostechies.com] on Topsy.com
on 01-08-2010 12:10 AM

Pingback from  Twitter Trackbacks for                 Adventures in Meta programming in Python: im_class, __import__, __getattribute__ - Polyglots R Us - Los         [lostechies.com]        on Topsy.com

bluehavana wrote re: Adventures in Meta programming in Python: im_class, __import__, __getattribute__
on 01-08-2010 12:23 AM

Hmm... Love the __getattribute__, its like method_missing? but not.

Chris Tavares wrote re: Adventures in Meta programming in Python: im_class, __import__, __getattribute__
on 01-08-2010 3:05 AM

Technically, __getattribute__ isn't called when a method is called, it's called when a method (or any attribute of the object) is accessed. It's original intention was to allow you to build dictionary-like objects, but turns out to be very useful for other things, as you discovered.

The net result is that if you've got a class, Foo, that implements __getattribute__, then:

o = Foo()

m = o.SomeMethod # __getattribute__ fires here

m()                          # not here

Ryan Svihla wrote re: Adventures in Meta programming in Python: im_class, __import__, __getattribute__
on 01-08-2010 8:09 AM

@bluehavana they have that too wait a blog post :)

@chris tavares  

The __call__ and __init__ methods and I figure several other special methods are not accessed.

As you said just object attributes seem to be all thats accessed.

I'll update with the correction and thanks again!

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Enter the numbers above:
Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems