How to choose format of reST docstring stubs in PyCharm? - python

In JetBrain's example for docstring in Pycharm, it is mentioned that:
Note that for reStructuredText it's possible to specify types in two formats:
:param param_type param_name: parameter description (type description is on the same line as the parameter description).
:type param_name: param_type (type description is on a separate line)
I want to make my pycharm autogenerate the second variant, not the first one?
Currently, it is even not even adding the type
def foo(a: str, b: int = 1) -> str:
"""
:param a:
:param b:
:return:
"""
return a + str(b)
a related question is: How to customize docstring generation in pycharm and share the template through git?

Currently, in spite of the documentation mentioning both formats, it appears it is not possible to switch between the two styles. https://youtrack.jetbrains.com/issue/PY-12327
You can enable the second style (which I think you want) by checking the following option:
Editor - General - Smart Keys - Python check Insert type placeholders in the documentation comment stub. (or use the Settings search and search for comment stub)
Very unintuitive and many people have been requesting improvements to this functionality in PyCharm. Ideally, you'd want to be able to provide a custom sphinx.mustache docstring template of this style:
{{! Sphinx Docstring Template }}
{{summaryPlaceholder}}
{{extendedSummaryPlaceholder}}
{{#args}}
:param {{var}}: {{descriptionPlaceholder}}
{{/args}}
{{#kwargs}}
:param {{var}}: {{descriptionPlaceholder}}
{{/kwargs}}
{{#exceptions}}
:raises {{type}}: {{descriptionPlaceholder}}
{{/exceptions}}
{{#returns}}
:return: {{descriptionPlaceholder}}
{{/returns}}
{{#yields}}
:yield: {{descriptionPlaceholder}}
{{/yields}}
(example taken from here https://github.com/executablebooks/markdown-it-py/blob/master/docstring.fmt.mustache)
But again, that is currently not supported in PyCharm - feel free to comment and vote on the linked issue, and perhaps it gets some attention.

Related

VS Code: add return type annotations automatically in Python function definitions

What I have:
def get_candy():
return "candy"
What I want VS Code to automatically do:
def get_candy() -> str:
return "candy"
When I later call get_candy() the annotation box automatically includes -> str: anyhow, but it would be nice if it was included in the source code as well.
The annotation extensions I checked do not do this either, the just add the """ comments - ...""" stuff.
When you see the return type of functions that don't explicitly show a return type, that is most likely pylance. While pylance does guess at return types, (1) it's not perfect, especially for complicated functions, and (2) I have never seen (nor can I find) anything about making it automatically add return types.
Assuming you are using pylance, you can always make a feature request on pylance's issue repo.

How to find an intersphinx mapping for wx.CheckBoxState

for my project documentation I use the intersphinx mapping to the wxpython documentation. That works fine so far but I don't succeed to get a link to wx.CheckBoxState. I tried to find information about that here and in other forums, but didn't find anything.
Here my code:
def my_meth( self, value, aStr ):
"""
:param int value: This is my value
:param str aStr: This is another value
Description using
- :py:class:`wx.CheckBoxState`
- :py:class:`wx.CheckBoxState.enumeration`
- :py:class:`wx.Validator`
"""
self.my_var = value
self.my_str = aStr
Running Sphinx produces
As you see links to "int", "str", "wx.Validator" work fine, but both attempts to find a link to wx.CheckBoxState didn't succeed.
There is still the hard coded way (a direct link to the page), but I would prefer the smart one (:py:class:...).
Can anybody help?
Thanks in advance
Humbalan
By the way: I work with sphinx 1.7.5, python 3.7 and wxpython 4.0.1
Depending on your intersphinx mapping configuration, you might need to adjust it. Assuming it looks like this:
intersphinx_mapping = {
'wx': ('https://docs.wxpython.org/', None),
}
You would then do this:
def my_meth( self, value, aStr ):
"""
:param int value: This is my value
:param str aStr: This is another value
Description using
- :ref:`wx.CheckBoxState`
- :py:class:`wx.Validator`
"""
self.my_var = value
self.my_str = aStr
I assumed that :py:obj: would work as an object of unspecified type for wx.CheckBoxState and wx.CheckBoxState.enumeration, but it didn't. I fell back to using :ref:, which worked for wx.CheckBoxState but not wx.CheckBoxState.enumeration, so I removed the latter. They seem to be the same target in the docs to me.
The style may be different, but I think that's the best you can hope for with the wxPython documentation out of the box.
You could try modifying your checkout of wxPython, modify the docs and possibly their source code until you get it to generate the link you want, then submit a pull request to them.

Can sphinx validate documentation against the actual implementation

I'm adding sphinx documentation to a couple of projects, but I'm concerned that down the line future developers aren't going to be rigorous in updating documentation when the method interface changes. Is there a way to have sphinx validate the list of arguments being described against what is actually specified in the method definition?
For example, let's say I set up sphinx using sphinx-quickstart, added autodoc, and am trying to build the following "module":
def product(arg_one, arg_two):
'''
:param arg_one: an object to be multiplied by arg_two
:type arg_one: Object
:param arg_two: an integer which defines the number of arg_one to return
:type arg_two: integer
:returns: The product of arg_one and arg_two
:raises: TypeError
'''
return arg_one * arg_two
And, a week from now, Bob Doe updates product as follows:
def product(value, number, catch_errors=False):
'''
:param arg_one: an object to be multiplied by arg_two
:type arg_one: Object
:param arg_two: an integer which defines the number of arg_one to return
:type arg_two: integer
:returns: The product of arg_one and arg_two
:raises: TypeError
'''
try:
return value * number
except TypeError as exc:
if catch_errors:
return None
raise
Now, the sphinx documentation isn't correct - it's missing the new catch_errors field and the variables have been renamed. But, running
sphinx-build . ./_build
a second time doesn't catch the problems - it just reports
Running Sphinx v1.6.5
loading pickled environment... done
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 0 source files that are out of date
updating environment: 0 added, 0 changed, 0 removed
looking for now-outdated files... none found
no targets are out of date.
build succeeded.
I would expect (or hope) that Sphinx is capable of validating the docstring against the actual code of the method, and failing (or at least indicating in some way) when the documentation and the implementation aren't in-sync.
If sphinx isn't capable of this, is there an alternative which is? I know there's function annotations in Python 3, but we're currently supporting both Python 2 and Python 3, so this isn't an option.
After some looking, I think the closest tool I could find easily is darglint but it was recently put into archive-mode on Github (December 2022) so long term support is not guaranteed or even likely.
One option, inspired by this discussion from torchvision is to use Sphinx-Napoleon and pydocstyle with almost everything turned off, except D417 which is a check for missing arguments in the docstring.
So pydocstyle can check for missing arguments but it cannot currently check for extra arguments.
Edit: seems pylint can do this with an extension https://pylint.pycqa.org/en/latest/user_guide/checkers/extensions.html#pylint-extensions-docparams but there is some functional overlap between the various linters and style checkers so you might need to just pick which ones you go with.
For catching re-named arguments, you could also enforce 100% coverage in your tests, but that wouldn't catch refactors to non-keyword arguments.
Of some other packages available:
doctest is good for checking if your docstring examples run correctly, but it doesn't do any signature validation. So if you set a default parameter like the example in the question, it will still pass doctest. If you used keyword arguments for all your examples, you could use this as a check, but it's a bit verbose.
interrogate is capable of checking docstring coverage, but not much else (as far as I can tell?) I'm not sure whether other tools actually check coverage though, so this is potentially a good tool to use in tandem.

Return type for docstring

While documenting code, I like to put in the types of inputs and outputs. Currently I list methods inputs in the docstrings as so:
:param some_input: The method input.
:type some_input: str
Which compiles nicely to:
Parameters: some_input (str) – The method input.
In the above, 'str' actually links automatically to https://docs.python.org/2/library/functions.html#str. I would like to have the same thing for my returns as well, with the type listed and hopefully linked to documentation of the class. Following the tags on the sphinx site: http://www.sphinx-doc.org/en/stable/domains.html, I have tried:
:return: The methods output.
:rtype: int
However this compiles to:
Returns: The methods output.
Return type: int
rather than listing the return name and type on one line. Is there a nice way to achieve the same result as for the param?
Sphinx is v1.6.4 and the theme is alabaster

How can I tell PyCharm what type a parameter is expected to be?

When it comes to constructors, and assignments, and method calls, the PyCharm IDE is pretty good at analyzing my source code and figuring out what type each variable should be. I like it when it's right, because it gives me good code-completion and parameter info, and it gives me warnings if I try to access an attribute that doesn't exist.
But when it comes to parameters, it knows nothing. The code-completion dropdowns can't show anything, because they don't know what type the parameter will be. The code analysis can't look for warnings.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
peasant = Person("Dennis", 37)
# PyCharm knows that the "peasant" variable is of type Person
peasant.dig_filth() # shows warning -- Person doesn't have a dig_filth method
class King:
def repress(self, peasant):
# PyCharm has no idea what type the "peasant" parameter should be
peasant.knock_over() # no warning even though knock_over doesn't exist
King().repress(peasant)
# Even if I call the method once with a Person instance, PyCharm doesn't
# consider that to mean that the "peasant" parameter should always be a Person
This makes a certain amount of sense. Other call sites could pass anything for that parameter. But if my method expects a parameter to be of type, say, pygame.Surface, I'd like to be able to indicate that to PyCharm somehow, so it can show me all of Surface's attributes in its code-completion dropdown, and highlight warnings if I call the wrong method, and so on.
Is there a way I can give PyCharm a hint, and say "psst, this parameter is supposed to be of type X"? (Or perhaps, in the spirit of dynamic languages, "this parameter is supposed to quack like an X"? I'd be fine with that.)
EDIT: CrazyCoder's answer, below, does the trick. For any newcomers like me who want the quick summary, here it is:
class King:
def repress(self, peasant):
"""
Exploit the workers by hanging on to outdated imperialist dogma which
perpetuates the economic and social differences in our society.
#type peasant: Person
#param peasant: Person to repress.
"""
peasant.knock_over() # Shows a warning. And there was much rejoicing.
The relevant part is the #type peasant: Person line of the docstring.
If you also go to File > Settings > Python Integrated Tools and set "Docstring format" to "Epytext", then PyCharm's View > Quick Documentation Lookup will pretty-print the parameter information instead of just printing all the #-lines as-is.
Yes, you can use special documentation format for methods and their parameters so that PyCharm can know the type. Recent PyCharm version supports most common doc formats.
For example, PyCharm extracts types from #param style comments.
See also reStructuredText and docstring conventions (PEP 257).
Another option is Python 3 annotations.
Please refer to the PyCharm documentation section for more details and samples.
If you are using Python 3.0 or later, you can also use annotations on functions and parameters. PyCharm will interpret these as the type the arguments or return values are expected to have:
class King:
def repress(self, peasant: Person) -> bool:
peasant.knock_over() # Shows a warning. And there was much rejoicing.
return peasant.badly_hurt() # Lets say, its not known from here that this method will always return a bool
Sometimes this is useful for non-public methods, that do not need a docstring. As an added benefit, those annotations can be accessed by code:
>>> King.repress.__annotations__
{'peasant': <class '__main__.Person'>, 'return': <class 'bool'>}
Update: As of PEP 484, which has been accepted for Python 3.5, it is also the official convention to specify argument and return types using annotations.
PyCharm extracts types from a #type pydoc string. See PyCharm docs here and here, and Epydoc docs. It's in the 'legacy' section of PyCharm, perhaps it lacks some functionality.
class King:
def repress(self, peasant):
"""
Exploit the workers by hanging on to outdated imperialist dogma which
perpetuates the economic and social differences in our society.
#type peasant: Person
#param peasant: Person to repress.
"""
peasant.knock_over() # Shows a warning. And there was much rejoicing.
The relevant part is the #type peasant: Person line of the docstring.
My intention is not to steal points from CrazyCoder or the original questioner, by all means give them their points. I just thought the simple answer should be in an 'answer' slot.
I'm using PyCharm Professional 2016.1 writing py2.6-2.7 code, and I found that using reStructuredText I can express types in a more succint way:
class Replicant(object):
pass
class Hunter(object):
def retire(self, replicant):
""" Retire the rogue or non-functional replicant.
:param Replicant replicant: the replicant to retire.
"""
replicant.knock_over() # Shows a warning.
See: https://www.jetbrains.com/help/pycharm/2016.1/type-hinting-in-pycharm.html#legacy
You can also assert for a type and Pycharm will infer it:
def my_function(an_int):
assert isinstance(an_int, int)
# Pycharm now knows that an_int is of type int
pass

Categories