1

I am using the luigi workflow library. I would like to subclass its luigi.Task class to add a few more of my own methods and parameters.

The usual object pattern would be:

class MockClassA():
    pass

class MockClassB():
    def __init__(self, foo):
        super().__init__()
        self.foo = foo

>>> MockClassB(12).foo
<<< 12

However, when I do:

class Transform(luigi.Task):
    def __init__(self, foo):
        super().__init__()
        self.foo = foo

I get:

>>> Transform(12)
<<< [...] UnknownParameterException: Transform[args=(12,), kwargs={}]: takes at most 0 parameters (1 given)

Why does this occur?

Aleksey Bilogur
  • 3,686
  • 3
  • 30
  • 57
  • it probably defines `__new__` as well – anthony sottile May 27 '17 at 21:45
  • I don't see it doing so in the [source](https://github.com/spotify/luigi/blob/master/luigi/task.py#L149). (unless the `six.add_metaclass(Register)` decorator does so; not familiar with `six`, but I highly doubt it) – Aleksey Bilogur May 27 '17 at 21:50
  • 1
    Here's the actual stacktrace: https://i.fluffy.cc/sVJCJ9Xfz8tCtWmJvkmV0jWNhPjcTrxf.html It's crashing inside `Register.__call__` (`Register` is a metaclass, added with `six.add_metaclass`) – anthony sottile May 27 '17 at 21:53
  • Yes, I was about to take it back after looking closer. Meta-programming hidden away in a compatibility library... Is it then not possible to subclass a meta-classed class? – Aleksey Bilogur May 27 '17 at 21:55

1 Answers1

4

The actual crash here is due to a metaclass running on instantiation.

From reading the luigi docs it seems you are supposed to define parameters to your class as class attributes (luigi.Parameter) and let their metaclass machinery take care of the constructor.

I believe your example would be written something like this:

class Transform(luigi.Task):
    foo = luigi.Parameter()
anthony sottile
  • 61,815
  • 15
  • 148
  • 207