heavenshell / vim-pydocstring

Generate Python docstring to your Python source code.
BSD 3-Clause "New" or "Revised" License
337 stars 53 forks source link

List raised exceptions #52

Closed JPFrancoia closed 4 years ago

JPFrancoia commented 6 years ago

Hi again,

I'm testing this plugin at the moment and I think it's really great. I however noted something is missing. Is it possible to list all the exceptions that can be raised in a function/method?

Something like that:

def module_level_function(param1, param2=None, *args, **kwargs):
    """This is an example of a module level function.

    Function parameters should be documented in the ``Args`` section. The name
    of each parameter is required. The type and description of each parameter
    is optional, but should be included if not obvious.

    Args:
        param1 (int): The first parameter.
        param2 (:obj:`str`, optional): The second parameter. Defaults to None.
            Second line of description should be indented.
        *args: Variable length argument list.
        **kwargs: Arbitrary keyword arguments.

    Returns:
        bool: True if successful, False otherwise.

        The return type is optional and may be specified at the beginning of
        the ``Returns`` section followed by a colon.

        The ``Returns`` section may span multiple lines and paragraphs.
        Following lines should be indented to match the first line.

        The ``Returns`` section supports any reStructuredText formatting,
        including literal blocks::

            {
                'param1': param1,
                'param2': param2
            }

    Raises:
        AttributeError: The ``Raises`` section is a list of all exceptions
            that are relevant to the interface.
        ValueError: If `param2` is equal to `param1`.

That's an example I took from here:

http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html

heavenshell commented 6 years ago

@JPFrancoia Hi. Thank you for being interested in my plugin.

Is it possible to list all the exceptions that can be raised in a function/method?

Sorry no. Because pydocstring.vim generate docstring from class|method|function signature. Python class|method|function does not have any information about exception.

JPFrancoia commented 6 years ago

Yes I understand that, but can you access the function (I mean the text of the function)? For example, you could parse the indented block of the function.

Then you could simply parse all the lines of the function, and look for "raise SomethingException".

I'm not good enough with vimscript to do that, but it must be possible.

heavenshell commented 6 years ago

@JPFrancoia

OK, I understood what you meant 👍 Currenlty I have no plan to do this, but let's consider about this.

Then you could simply parse all the lines of the function, and look for "raise SomethingException".

  1. Parsing Python's code from Vim script takes lot of cost and it's too complecated. How to find end of function? Pick def keyword? how about inner functon, etc.

  2. See following example,

def foo() -> str:
    # foo's logic
    def bar(arg):
        # bar's logic
        if error:
            raise SomeError()
        return 'bar'
     ret = ''
     try:
        ret = bar('baz')
     except:
        pass
     return ret

If cursor is on at foo() line and pick exception from foo's function. This foo function catch exception and nothing to do. Do you want generate?

e.g.

def foo() -> str:
    """foo

    :raise: SomeError
    :rtype: str
    """"
JPFrancoia commented 6 years ago

How to find end of function?

This is an easy one I think. You just need to find the end of the indented block. i.e: next line that has an indention level smaller of equal to the function you're trying to docstring.

And yes, the generated docstring you propose seems good to me. bar raises an exception and it bubbles to foo.

heavenshell commented 6 years ago

This is an easy one I think. You just need to find the end of the indented block. i.e: next line that has an indention level smaller of equal to the function you're trying to docstring.

Hum. That are not easy. BTW, PRs are welcome 😉

And yes, the generated docstring you propose seems good to me. bar raises an exception and it bubbles to foo.

If I write my code to use foo() function with referring docstring.

def main():
     try:
         foo()
     except SomeError:
         logger.error('Some error')

But, foo() never raises SomeError, because, foo() stop bubble exception.

Do you really want list exceptions to docstring?

JPFrancoia commented 6 years ago

I'd PR it if I knew vimscript, really. If the plugin was written in Python, I'd do it as well.

But it's your plugin, so you're free to do it or not, obviously.

I just think it's a nice feature to have, because when you make the doc for a python project, you can mention the exceptions raised by a function.

I'd personally be ok with that:

def foo() -> str:
    """foo

    :raise: SomeError
    :rtype: str
    """"

From this example:

    # foo's logic
    def bar(arg):
        # bar's logic
        if error:
            raise SomeError()
        return 'bar'
     ret = ''
     try:
        ret = bar('baz')
     except:
        pass
     return ret

If you don't think that SomeError should be in foo's docstring, you could also stop parsing function foo as soon as you meet a line defining a new function.

Actually, I think it's the way to go: parse a function looking for raise, unless you reach a block with a lower level of indentation or a new function