1

Following http://www.artima.com/weblogs/viewpost.jsp?thread=240845, I've written the decorator extend_to_separated_input:

class extend_to_separated_input(object):
    def __init__(self, separator):
        assert isinstance(separator, str), "The separator must be a string."
        self.separator = separator

    def __call__(self, parse_function):
        def wrapped_function(raw_conditions, *args, **kwargs):
            raw_conditions = raw_conditions.split(self.separator)
            return [parse_function(raw_condition, *args, **kwargs) for raw_condition in raw_conditions]
        return wrapped_function 

This decorator works for globally defined functions, for example,

import parse
fmt = "{word1} {word2}"
@extend_to_separated_input(separator="&&")
def _parse(string):
    return parse.parse(fmt, string).named

string = "foo bar && hello world"
print _parse(string)

prints the result

[{'word1': 'foo', 'word2': 'bar '}, {'word1': ' hello', 'word2': 'world'}]

which is what I would expect. (Here I've used the parse module). In my actual use case, however, the _parse method is a class method, not a global method. However, if I try to do this:

class TwoWords(object):
    fmt = "{word1} {word2}"

    @classmethod
    @extend_to_separated_input(separator="&&")
    def _parse(cls, raw_condition):
        return parse.parse(cls.fmt, raw_condition).named

string = "foo bar && hello world"
print TwoWords._parse(string)

I get an

AttributeError: type object 'TwoWords' has no attribute 'split'

The problem is that it is picking up the class as the first argument. I've tried to adapt the definition to def wrapped_function(cls, raw_conditions, *args, **kwargs), but this leads to a TypeError because of insufficient arguments.

How I adapt the decorator so that it works for class methods?

Kurt Peek
  • 52,165
  • 91
  • 301
  • 526
  • 1
    You are not handling the `self` argument correctly; it's the first argument passed into a bound function. – Martijn Pieters Mar 16 '17 at 16:40
  • 1
    By the time I had figured out a solution the question was closed. For reference, the wrapper can be made to work for class methods by in addition to `def wrapped_function(cls, raw_conditions, *args, **kwargs)` adapting the call of `parse_function` to `parse_function(cls, raw_condition, *args, **kwargs)`. – Kurt Peek Mar 16 '17 at 17:09

0 Answers0