mk a écrit :

I'm trying to get print_internal_date become a static method AND to refer to it in a class attribute 'tagdata' dict.

class PYFileInfo(FileInfo):
    'python file properties'

    @staticmethod
    def print_internal_date(filename):
        f = open(filename + 'c', "rb")
        data = f.read(8)
        mtime = struct.unpack("<i", data[4:])
        return time.asctime(time.gmtime(mtime[0]))

    tagdata = {'compiled_fname': lambda x: x + 'c',
                'size': os.path.getsize,
                'internal_date': print_internal_date
            }
(snip)

    def __get_props(self, value):
        py_compile.compile(value)
        for tag, fun in PYFileInfo.tagdata.items():
            self[tag] = fun(value)

But:

c:/Python26/pythonw.exe -u  "C:/mp3i/finfo2.py"
Traceback (most recent call last):
(snip)
  File "C:/mp3i/finfo2.py", line 79, in __get_props
    self[tag] = fun(value)
TypeError: 'staticmethod' object is not callable


I think I know where the problem is: what resides in tagdata is a static method 'wrapper', not the function itself, according to:

Indeed. Sorry, I'm afraid I gave you bad advice wrt/ using a staticmethod here - I should know better :( (well, OTHO staticmethods are not something I use that often).

Anyway: here are a simplified version of your problem, a possible solution that _won't_ statisfy your other constraints, 2 ugly hacks that could work but that I don't really like, and what's possibly the "less worse" solution if you really need a staticmethod here.

###
class Foo1(object):
    """ simplified version of mk's code - test() fails """
    @staticmethod
    def bar(baaz):
        print baaz

    tagada = {'bar': bar}

    def test(self, baaz):
        self.tagada['bar'](baaz)


class Foo2(object):
    """ naive solution : kinda work, BUT will fail
        with the real code that has  plain functions
        in 'tagada'
    """
    @staticmethod
    def bar(baaz):
        print baaz

    tagada = {'bar': bar}

    def test(self, baaz):
        self.tagada['bar'].__get__(self)(baaz)


class Foo3(object):
    """ working solution 1 : defer the wrapping
        of 'bar' as a staticmethod
    """
    def bar(baaz):
        print baaz

    tagada = {'bar': bar}

    bar = staticmethod(bar)

    def test(self, baaz):
        self.tagada['bar'](baaz)


class Foo4(object):
    """ working solution 2 : use a lambda """
    @staticmethod
    def bar(baaz):
        print baaz

    tagada = {'bar': lambda x : Foo4.bar(x)}

    def test(self, baaz):
        self.tagada['bar'](baaz)


""" and as a "less worse" solution """

def foo5bar(baaz):
   print baaz

class Foo5(object):
    tagada = {'bar': foo5bar}

    bar = staticmethod(foo5bar)

    def test(self, baaz):
        self.tagada['bar'](baaz)


###

Another "solution" might be to write an alternate callable implementation of 'staticmethod' - which I'll leave as an exercise to the reader (...) - but that's possibly a bit overkill !-)


http://docs.python.org/reference/datamodel.html

So, how do I get out the wrapped function out of static method without class call or instance call? (to be called in self[tag] = fun(value))

cf above. None of the solutions I could came with really statisfy me, but well, at least 3 of them might be "good enough" depending on the context. As far as I'm concerned, I'd first try the last one, but YMMV

Yes, I do know that if I just get rid of @staticmethod, this works without a hitch.

But then you can't use print_internal_date as a method !-)

HTH
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to