If I do sphinx-quickstart
I get asked about the version of the project.
I want to avoid to have two places for the version of my project.
How to do this in the python packing world?
The best technique is to define __version__ in your product code, then import it into setup.py from there. This gives you a value you can read in your running module, and have only one place to define it. The values in setup.py are not installed, and setup.py doesn't stick around after installation.
The easiest (and probably cleanest) way is to define __version__
for the __init__.py
of your top-level package, and then import that package and read the version in both setup.py
and your Sphinx project's conf.py
.
So lets say your project is called myproject
.
Move your current version out of setup.py
, and make it a variable in myproject/__init__.py
instead:
myproject/__init__.py
:
# import foo
# ...
__version__ = '1.5'
Import myproject
in your project's setup.py
, and replace the hardcoded version with myproject.__version__
:
setup.py
:
from setuptools import setup
from myproject import __version__
project = "myproject"
setup(
name=project,
version=__version__,
# ...
)
In your Sphinx project's conf.py
, do the same. So edit the generated conf.py
along these lines:
docs/conf.py
:
from myproject import __version__
# ...
# The short X.Y version.
version = __version__
# The full version, including alpha/beta/rc tags.
release = version
For an example of a library that does this pretty much exactly like this, have a look at the requests
module (__init__.py
| setup.py
| conf.py
).
This will take care of the auto-generated texts where the project version is used (like the links to the front page of the documentation). If you want to use your version in specific custom places, you can use the rst_epilog
directive to dynamically insert configuration values defined in conf.py
.
Maybe an even cleaner option is to actually build sphinx from the setup.py
command as described in http://www.sphinx-doc.org/en/master/setuptools.html:
setup.py
# this is only necessary when not using setuptools/distribute
from sphinx.setup_command import BuildDoc
cmdclass = {'build_sphinx': BuildDoc}
name = 'My project'
version = '1.2'
release = '1.2.0'
setup(
name=name,
author='Bernard Montgomery',
version=release,
cmdclass=cmdclass,
# these are optional and override conf.py settings
command_options={
'build_sphinx': {
'project': ('setup.py', name),
'version': ('setup.py', version),
'release': ('setup.py', release),
'source_dir': ('setup.py', 'doc')}},
)
Then build documentation using
$ python setup.py build_sphinx
Benefits:
setup.py
the single source of version numberYou could have a look at bumpversion
module:
"A small command line tool to simplify releasing software by updating all version strings in your source code by the correct increment"
You may use a configuration file .bumpversion.cfg
for complex multi-file operations.
Another way is integrating setuptools_scm
in your project. This way you can
from setuptools_scm import get_version
version = get_version()
in your conf.py
Here is a straightforward solution, ironically from the setuptools_scm PyPI page:
# contents of docs/conf.py
from importlib.metadata import version
release = version('myproject')
# for example take major/minor
version = '.'.join(release.split('.')[:2])
Here is their explanation why it is discouraged to use their package from Sphinx:
The underlying reason is, that services like Read the Docs sometimes change the working directory for good reasons and using the installed metadata prevents using needless volatile data there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With