Home Home > 2009 > 04 > 29
Sign up | Login

Deprecation notice: openSUSE Lizards user blog platform is deprecated, and will remain read only for the time being. Learn more...

Archive for April 29th, 2009

Ruby style method injection in Python

April 29th, 2009 by

Ruby has a nice, but very dangerous feature called open classes. That means you can extend any class definition if you want it.

This example shows it

#!/usr/bin/ruby
class Foo
    def do_foo
        return "foo"
    end
end

aFoo = Foo.new()

puts aFoo.do_foo()

class Foo
    def do_bar
        return "bar"
    end
end

puts aFoo.do_bar()

That means you dynamically extend the definition of Foo class, so the last line prints “bar”.

Python behavior is different, because it does not allows this extending. Python just redefines a class Foo, so new instance of Foo will have a do_bar method only. But this not affected an existing ones, like Ruby does.

class Foo:

    def do_foo(self):
        return "foo"

aFoo1 = Foo()

class Bar(Foo):

    def do_nothing(self):
        pass

print issubclass(Bar, Foo)
print isinstance(aFoo1, Foo)

class Foo:
    
    def do_bar(self):
        return "bar"

aFoo2 = Foo()
aBar  = Bar()

print issubclass(Bar, Foo)
print isinstance(aFoo1, Foo)
print isinstance(aFoo2, Foo)

print dir(aFoo1)
print dir(aFoo2)
print dir(aBar)

But what about method injection? My solution is based on ideas of Recipe 81732: Dynamically added methods to a class.

import types

def funcToMethod(func, instance, method_name=None):
    cls = instance.__class__ if type(instance) != types.TypeType else instance
    setattr(cls, \
            method_name or func.__name__, \
            types.MethodType(func, instance, cls))

And that’s all. The funcToMethod bounds func to instances’s class and allows under method_name (default name is a same as a function one). So lets do some testing.

class Foo(object):

    def list(self):

        return [meth for meth in dir(self) if meth[:3] == 'do_' and type(getattr(self, meth)) == types.MethodType]

    def do_bar(self):
        
        return "bar"

def do_foo(inst):

    return "foo"

class Bar(Foo):

    def do_nothing(self):
        pass

aBar = Bar()

aFoo1 = Foo()
print aFoo1.list()
# calling it with class instead of instance is also possible and is equivalent
#funcToMethod(do_foo, Foo, "do_foo")
funcToMethod(do_foo, aFoo1, "do_foo")

aFoo2 = Foo()
print aFoo1.list()
print aFoo2.list()

print aFoo1.do_foo()
print aFoo2.do_foo()

print aBar.list()
print aBar.do_foo()

When you run the code, you will see that funcToMethod adds a new method to Foo class and this changes both existing and new instances as Ruby does too. And subclassing is not a problem, they are be affected too.

OpenOffice_org 3.1 beta6 and missing localizations

April 29th, 2009 by

Urgh, the OpenOffice_org 3.1 beta6 packages are currently available only for 5 localizations: English(American), German, Japanese, Czech, Hungarian. I forgot to enable all localizations in the final build (bnc#498906). I have just triggered the full rebuild but it will take one or two days until the packages are available.

I am really sorry for the inconvenience.