Class inheritance
process0 opened this issue · 7 comments
It would be useful to have class inheritance on Workflow/WorkflowTemplates objects so that common components could be reused. This may not be as big of a requirement if #18 is implemented as those components could be referenced.
Ideas?
I've inherited from the Workflow class and run the inheriting workflows without problems.
`
argo 2.11.7
python 3.8.5
argo-workflows==4.0.1
argo-workflows-dsl==0.4.0
`
Inheritance doesn't solve #18 though, and handles a completely different use case. Referencing templates/workflows is one thing, and a whole different thing is using inheritance to more succinctly and correctly define them in code.
I've now come upon your problem as well - you can't inherit @template
s... So this still stands.
I think I've located the problem - in WorkflowMeta
, the code collects the props
just from the current class and not from all bases of the current class. Changing this to collecting all of them will probably yield a good result.
I've ran into a similar problem that may be worth considering- I didn't want to inherit templates, but I wanted use the scope decorator on functions in the parent class and make them available to closures on the child classes. I am currently using a custom metaclass.
That's really interesting, how did you do that? Can you share the code?
About metaclasses - I'd like to steer clear of changing the metaclass or in fact writing any metaclass code if possible...
And about templating inherited methods - I think the better approach would be to override the parent's method and declare your override as a closure, even if it's just calling the parent. Unlike templates, closures are ad-hoc compiled so explicitly overriding provides clearer resolution for the code AND brevity IMO.
Come to think of it... The order in which templates are defined on a class defines the order of steps in the workflow - and the order they appear in the child class if inherited from the parent is deterministic, so this is not a bad idea at all. It's 100% implicit, but deterministic. The problem is what happens when you mix and match things with DAGs - then you'd have to override the parent class' methods and redefine the ordering yourself using template declarations.
Looking back at my code, it is not generalizable- it is using a metaclass on the parent to dynamically call scope() on preset functions on the base class when the child class is created. I agree, your solution of overriding the parent methods would probably be clearer.
I've tried reusing methods in a class hierarchy, and it seemed that whatever I tag with @template
runs only once. Upon investigation of the
Spec
, which is compiled once (see argo-python-dsl/argo/workflows/dsl/_base.py
Line 134 in 36369be
model
property is handled in Workflow
at the source code level, as it uses self.__compiled_model
under the hood.
I've overcome all this by dynamically generating a new class inheriting form the class I actually wanted to use every time I want to submit a new instance of the workflow. I had to redeclare things like entrypoint
and service_account_name
in the dynamically generated class too. At least there's a workaround!