What is the difference between var, cvar and ivar in python's sphinx?

Question:

I was reading through the sphinx documentation pages and ironically found that the documentation on the difference between var, ivar, and cvar very lacking. I was wondering if someone could explain the difference between each of the different name spaces in inline code.

Example:

class foo(object):
    """
      :var str first:
      :ivar str last:
      :cvar str middle:
    """

How are each of these sphinx tags different from each other and how do I know which one is the correct one to use correctly as designed?

Asked By: Rusty Weber

||

Answers:

Maybe don’t worry about the distinction between thesr specific tags and simply stick to using ‘var’ if you need to use it at all, since the documentation indicates that:

There are many other Info fields but they may be redundant:
…(including)…
var, ivar, cvar: Description of a variable.

See:

http://thomas-cokelaer.info/tutorials/sphinx/docstring_python.html

Answered By: Chris Halcrow

var is a generic variable, of course. Use this when you don’t care to make any further distinction about the variable you are documenting.

ivar is an “instance variable”, or a variable that is set on an instance object (an instance of a class). Typically these would be defined (in Python) inside of an __init__ method.

cvar is a “class variable”, or a variable that is set on a class object directly. Typically, this would be set inside a class statement, but outside of any particular method in the class.

Here’s an example:

class SomeClass(object):

    cvar = 'I am a class variable'

    def __init__(self):
        self.ivar = 'I am an instance variable'
Answered By: Kevin Horn

Documentation

https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#info-field-lists as of Sphinx==6.1.3 says they all render exactly the same for now, which is a shame:

In current release, all var, ivar and cvar are represented as “Variable”. There is no difference at all.

:ivar: vs :cvar minimal runnable example

Here’s a minimal runnable example showing how they are likely meant to be used, and how the output looks like. As there is no rendering difference as of Sphinx==6.1.3 it is just a semantic thing for the source reader for the time being, but worth doing anyways.

Not showing :var: because I’m not sure when that is meant to be used! Maybe module level variables would be the best? How to document a module constant in Python? But it doesn’t work there from the module docstring.

main.py

class MyOtherClass:
    """
    This class does that.
    """
    pass

class MyClass:
    """
    Description for class.

    :ivar var1: Doc for var1
    :ivar var2: Doc for var2.
      Another line!
    :cvar class_var: Syntax also works for class variables.
    """

    class_var: int

    def __init__(self, par1: int, par2: MyOtherClass):
        self.var1: int = par1

        self.var2: MyOtherClass = par2

    def method(self):
        """
        My favorite method.
        """
        pass

    @classmethod
    def cmethod():
        """
        My favorite class method.
        """
        pass

build.sh

sphinx-build . out

conf.py

import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = [ 'sphinx.ext.autodoc' ]
autodoc_default_options = {
    'members': True,
}
autodoc_typehints = "description"

index.rst

.. automodule:: main

requirements.txt

Sphinx==6.1.3

After ./build.sh the output under out/index.html looks like:
enter image description here

#: doc comments

This is another way to document instance and class variables.

There are currently tradeoffs between both methods, it is a shame that there isn’t one clearly superior method.

Downsides:

  • the "Variables:" grouping looks cleaner, TODO link to feature request

Upsides:

  • you have to type the attribute names again
  • types are gone, TODO link to feature request

Both could be better:

  • clearly show that class_var is a class variable? TODO link to feature request

Besides the self.var1 = par1 # Doc for var1 syntax you can also:

main.py

class MyClass:
    """
    Description for class.
    """

    #: Syntax also works for class variables.
    class_var: int = 1

    def __init__(self, par1: int, par2: MyOtherClass):
        #: Doc for var1
        self.var1: int = par1

        #: Doc for var2.
        #: Another line!
        self.var2: MyOtherClass = par2

    def method(self):
        """
        My favorite method.
        """
        pass

    @classmethod
    def cmethod():
        """
        My favorite class method.
        """
        pass

produces:

enter image description here

The #: syntax is documented at: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#directive-autoproperty

Tested on Python 3.10, Ubuntu 22.10.

Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.