This is an extension of Dynamically decorate a function inside a class in Python3
@MisterMyagi properly answered my question that you can dynamically decorate a class using this logic:
class MyTaskSequence(TaskSequence):
pass
def add_sequence(cls, order, path):
@seq_task(order)
def sequence(self):
self.client.get(path)
sequence.__name__ = "sequence%d" % order
setattr(cls, sequence.__name__, sequence)
add_sequence(MyTaskSequence, 1, "/devops/")
add_sequence(MyTaskSequence, 2, "/blog/")
My question is: How do you ensure that the function which is generated can be used as standalone function and as a method of the class at the same time?
eg: Static function definition:
class MyTaskSequence(TaskSequence):
@seq_task(1)
def sequence1(self):
self.client.get("/devops/")
@seq_task(2)
def sequence2(self):
self.client.get("/blog/")
pprint(vars(MyTaskSequence))
>>>>
mappingproxy({'__doc__': None,
'__module__': 'run-loadtest.index',
'sequence1': <function start.<locals>.MyTaskSequence.sequence1 at 0x10d759c20>,
'sequence2': <function start.<locals>.MyTaskSequence.sequence2 at 0x10d759f80>,
'tasks': [<function start.<locals>.MyTaskSequence.sequence1 at 0x10d759c20>,
<function start.<locals>.MyTaskSequence.sequence2 at 0x10d759f80>]})
What I tried:
class MyTaskSequence(TaskSequence):
pass
def add_sequence(cls, order, path):
@seq_task(order)
def sequence(self):
self.client.get(path)
sequence.__name__ = "sequence%d" % order
setattr(cls, sequence.__name__, sequence)
add_sequence(MyTaskSequence, 1, "/devops/")
add_sequence(MyTaskSequence, 2, "/blog/")
pprint(vars(MyTaskSequence))
>>>>
mappingproxy({'__doc__': None,
'__module__': 'run-loadtest.index',
'sequence1': <function start.<locals>.add_sequence.<locals>.sequence at 0x10590bc20>,
'sequence2': <function start.<locals>.add_sequence.<locals>.sequence at 0x10590bf80>,
'tasks': []})
Notice that the resulting object is a bit "different".
Now, I understand that this is caused by the library that I am using, but I am currently under the impression that it is basically caused by the fact that the generated "sequence%d" function is just a standalone function and not also a method of the class.
You can check that by comparing the resulting "definition" of the 2 prints:
'sequence1': <function start.<locals>.MyTaskSequence.sequence1 at 0x10d759c20>,
VERSUS
'sequence1': <function start.<locals>.add_sequence.<locals>.sequence at 0x10590bc20>,
PS: Notice the missing class name in its definition.