Chilipp / docrep

A Python Module for intelligent reuse of docstrings
Apache License 2.0
30 stars 4 forks source link

Feature requests #16

Open jgostick opened 4 years ago

jgostick commented 4 years ago

Hi Philipp We have started using docrep 'officially' in our project (OpenPNM). It's now merged into dev and will be release to master by the end of March.

I have it working pretty well, but there are two behaviors/features I wish it had. I apologize for being demanding, but here they are:

  1. It would be great if individual parameters in subclasses over-rode those from the parent automatically. For instance, if I have the following method on a parent or abstract class:
def some_awesome_method(self, param1):
    r"""
    Parameters
    ------------
    param1 : int
         This parameters controls blah and it's default is None
    """

And I subclass this method on a child class:

def some_awesome_method(self, param1):
    r"""
    Parameters
    ------------
    param1 : int
         This parameters controls the size of the timestep and it's default is **10**
    """

In the above method I have indicated a different default value for the child class, and might also want to be more specific in the text, for instance. It would be REALLY helpful is the child class method just overwrote the parent class one, without me having to think about it. I know you have functionality for removing items from the parameter list, but this requires too much knowledge of docrep on the part of developers.

  1. I understand that you only support 'numpydoc' valid headings (i.e. Parameters), but would it be possible to allow users to put arbitrary headings in? I use Spyder to for developing and Sphinx for doc generation, and both do not seem to mind having arbitrary headings (i.e. Transient Parameters, Reaction Parameters). This would allow me to breakup the parameter sections in the parent classes and then pick & choose which sections I show in subclasses.

Request 1 is far more important that 2.

Chilipp commented 4 years ago

hey @jgostick! Great, I am happy to hear that this package is useful :)

I apologize for being demanding

There is absolutely no need to apologize :wink: I am always happy to implement new features if I can. And in your case, I think it's actually not too difficult.


Let me start with the easy one: point 2. I think this is actually already answered in https://github.com/Chilipp/docrep/issues/4#issuecomment-366548209, but please let me know if not. Unfortunately, I cannot think of a fully automated solution at the moment as I have to treat Parameters-type sections, Returns-type sections and text sections differently. An automated support for unknown sections would not a priori know whether the unknown section should be treated like a Parameters section, or Returns section, or text section.


Point 1 is a bit more tricky, but should be feasible indeed. The workaround you mention in https://github.com/Chilipp/docrep/issues/16#ref-issue-466953964 has the problem that it does not maintain the order of parameters (which often is important for the documentation). I could imagine the following strategy:

  1. Read the existing parameter list (for this, I have to remove all '%(...)s'-like parts in the section).
  2. insert the new parameters (i.e. replace the '%(...)s'-like parts in the section as it is currently done with dedent)
  3. load the parameters and check for duplicates. The parameters identified in step 1. should then be inserted at the positions of step 2.

As an example, let's look at this two methods:

@docstrings.get_sectionsf('method')
def some_awesome_method(self, param1, param2, param3):
    r"""
    Parameters
    ------------
    param1 : int
         This parameters controls blah and it's default is None
    param2 : int
         This second parameters controls blah and it's default is None
    param3 : int
         This third parameters controls blah and it's default is None
    """

@docstrings.dedent
def some_other_awesome_method(self, param1, param2, param3):
    r"""
    Parameters
    ------------
    %(method.parameters)s
    param2 : int
         This second parameters controls the size of the timestep and it's default is **10**
    """

Here, it is important that the doc of param2 needs to apear before param3 (therefore step 3.). In other words, the parameters section of some_other_awesome_method should look like

    Parameters
    ------------
    param1 : int
         This parameters controls blah and it's default is None
    param2 : int
         This second parameters controls the size of the timestep and it's default is **10**
    param3 : int
         This third parameters controls blah and it's default is None

and not like

    Parameters
    ------------
    param1 : int
         ...
    param3 : int
         ...
    param2 : int
         ...

Is this, what you are looking for?

jgostick commented 4 years ago

I would actually not mind if the parameters were in the wrong order, if it meant having the ability to override parent class docs. It's a trade-off I'd be willing to make. In other words, the order of parameters is secondary information (i.e. relays information about each parameters' relative importance) compared to the actual content of the docstring. But I must admit that I did imagine the added parameter overwriting the existing one, not appending onto the list.

Chilipp commented 4 years ago

Alright! Thanks for the feedback @jgostick :smiley: This requires a bit of work. At the moment I am not looking what parameters, etc. exist, at all. Instead, keep_params, for instance, just substitutes the parameters that you specify using a regular expression. However, for the stuff I am planning in #17, we need something to read and process the docstring, rather than just substituting the contents.