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?
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
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'
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:
#:
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:
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.
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?
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
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'
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:
#:
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:
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.