glotzerlab / signac-flow

Workflow management for signac-managed data spaces.
https://signac.io/
BSD 3-Clause "New" or "Revised" License
48 stars 37 forks source link

FlowProject.operation documentation doesn't show up in signac-flow API docs home page #664

Open kidrahahjo opened 2 years ago

kidrahahjo commented 2 years ago

Description

The "description" of FlowProject.operation doesn't show up in https://docs.signac.io/projects/flow/en/latest/api.html. Is there a reason for this?

cbkerr commented 2 years ago

It's pulling the information from OperationRegister, but I'm not sure why.

vyasr commented 2 years ago

I can explain why this is probably happening, but I'm not immediately sure how to fix it (Sphinx at this level of complexity is always a bit of trial and error for me):

  1. The FlowProject has a custom metaclass called FlowProjectClass that defines a bunch of attributes on every subclass of FlowProject. The metaclass is necessary because we define workflows as subclasses of FlowProject rather than instances of FlowProject. In other words, we need the metaclasses so that e.g. operations registered to one project don't get registered to all subclasses of FlowProject:
    
    class Project1(FlowProject):
    pass

class Project2(FlowProject): pass

We don't want op1 in Project2

@Project1.operation def op1(job): pass

We don't want op2 in Project1

@Project2.operation def op2(job): pass


2. Specifically, the pre- and postcondition decorators as well as the `operation` decorator are [created once for each subclass](https://github.com/glotzerlab/signac-flow/blob/master/flow/project.py#L1237) so that the conditions/operations are registered to the appropriate subclass.
3. While the `pre` and `post` decorators are classes (for example, [the precondition setup function returns the locally defined `pre` class](https://github.com/glotzerlab/signac-flow/blob/master/flow/project.py#L1343)), the `operation` decorator is also defining a class locally but [it then returns an _instance_ of that class](https://github.com/glotzerlab/signac-flow/blob/master/flow/project.py#L1544).

My guess is that item (3) is the problem: since `FlowProject.operation` is an instance of the `OperationRegister` rather than the class itself, Sphinx's autosummary plugin is having trouble pulling the docstring. The class vs instance difference arises because of differences in how we use the decorators: pre- and postconditions always have an argument (the condition), so we always instantiate the class, whereas the operation decorator's argument (which allows the user to specify a different name for the operation) is only used sparingly. In principle we could probably rework the implementation to bring the conditions/operations into greater alignment, but hopefully there is a simpler solution to getting the docstring to show up.