Chilipp / docrep

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

Works on classes in different files? #10

Closed jgostick closed 5 years ago

jgostick commented 5 years ago

I've looked at the answer you gave in issues #1, and your code snippet indeed works...it even works on deeper inheritance (e.g. methods in class C can get doc strings from class A).

BUT, when I try to do it on my project, where, A, B and C are each in different files it does not work. I have confirmed this on the simple test cases in issue #1. If you put A and B in different files (called docrep_A and docrep_B), then when you do from docrep_B import B and b = B() on the command line it says: SyntaxWarning: 'A.my_method.parameters' is not a valid key! @docstrings.dedent

Do you have any thoughts on this?

Chilipp commented 5 years ago

Hi! Thank you @jgostick for your input and for your feedback on the package!

So when I got you right, you have one script

docrep_A.py ```python from docrep import DocstringProcessor docstrings = DocstringProcessor() class A(object): @docstrings.get_sectionsf('A.my_method') @docstrings.dedent def my_method(self, a): """ Do something Parameters ---------- a: int Some random number """ pass ```
and another script
docrep_B.py ```python from docrep_A import docstrings, A class B(A): @docstrings.dedent def my_method(self, a, b): """ Do something more advanced Parameters ---------- %(A.my_method.parameters)s b: int An additional number """ pass if __name__ == '__main__': print(B.my_method.__doc__) ```
And then you claim, that `B` does not inherit the docstring from `A`? For me, when I run `docrep_B.py` I get ```bash python docrep_B.py Do something more advanced Parameters ---------- a: int Some random number b: int An additional number ``` Make sure, that you use the same `DocstringProcessor` instance (namely `docstrings`) for `B` that you used for `A`! Does this help? If not, please provide a simple use case such that I can better understand your problem.
jgostick commented 5 years ago

Sorry my initial question wasn't clear....let me try again, but based on your above comment, the problem is clearly that each file has a different instance of the DocstringProcessor. So I guess my question is how to do get access to the instance created in A from the B? I tried putting in the same doc_key in each, but that doesn't seem to do it. Anyway, here is my exact example:

I have a file like this called class_A:

from docrep import DocstringProcessor

doc = DocstringProcessor(doc_key='class_A')

class A():
    @doc.get_sectionsf('A.do_something', sections=['Parameters', 'Notes'])
    def do_something(self, a):
        r"""
        A method to do something

        Parameters
        ----------
        a : object
            An argument to do something

        Notes
        -----
        This method doesn't do much, but it does it well
        """
        print('A is doing something')

Another like this called class_B

from docrep import DocstringProcessor
from class_A import A

doc = DocstringProcessor(doc_key='class_A')

class B(A):
    @doc.dedent
    def do_something(self, b):
        r"""
        A method to do something

        Parameters
        ----------
        %(A.do_something.parameters)s

        b : object
            An argument to do something

        Notes
        -----
        This method inherits from A, so does twice as much of nothing
        """
        print('A is doing something')\

Then from the command line or in another script I do this:

from class_B import B

b = B()

I get the following: SyntaxWarning: 'A.do_something.parameters' is not a valid key! @doc.dedent

Chilipp commented 5 years ago

Dear @jgostick,

so from my point of view, the only possibility to solve this problem is to import the doc you created in the class_A module. This is how I did it in the above docrep_B.py script as well with the line from docrep_A import docstrings, A

In other words: change from class_A import A in your class_B file into from class_A import doc, A. Does this work for you?


As an explanation:

Different instances of the DocstringProcessor class do not share the extracted docstrings between each other. Otherwise it would be a big mess if multiple independent python packages use docrep and then override the docstrings from each other.

Therefore, if you create a new instance doc = DocstringProcessor(doc_key='class_A') it does not know about the instance you created in the class_A module.

Giving the keyword doc_key='class_A' doesn't change anything here.

jgostick commented 5 years ago

I have actually just found a solution to the problem, but I'm not sure this is how you intended it to work, or if it would have consequences. Basically, I add doc as a class variable on A, then add it to B as well, like this:

class A():
    doc = doc

and

class B(A):
    doc = A.doc

Then is works! Can you just confirm if this is the right approach, or if you have a better way? I don't really like the idea of having to add the doc=parent.doc line to each class definition.

Chilipp commented 5 years ago

Well, as I said, just import doc from the class_A module. But your solution works as well.

jgostick commented 5 years ago

I think importing is the way to go, thanks! I LOVE this package. I was planning to write one myself, but eventually found yours while I was searching how to do decorators. BTW, you should call this package docorator! I might open more issues as I implement this in my package, but will close this now.

Chilipp commented 5 years ago

You're very welcomed to do so! I am happy it is useful for you 😃