Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to share package version with setup.py and the package?

With distutils, setuptools, etc. a package version is specified in setup.py:

# file: setup.py ... setup( name='foobar', version='1.0.0', # other attributes ) 

I would like to be able to access the same version number from within the package:

>>> import foobar >>> foobar.__version__ '1.0.0' 

I could add __version__ = '1.0.0' to my package's __init__.py, but I would also like to include additional imports in my package to create a simplified interface to the package:

# file: __init__.py  from foobar import foo from foobar.bar import Bar  __version__ = '1.0.0' 

and

# file: setup.py  from foobar import __version__ ... setup( name='foobar', version=__version__, # other attributes ) 

However, these additional imports can cause the installation of foobar to fail if they import other packages that are not yet installed. What is the correct way to share package version with setup.py and the package?

like image 541
Jace Browning Avatar asked Jul 11 '13 01:07

Jace Browning


People also ask

How do I install a package using setup py?

Installing Python Packages with Setup.py To install a package that includes a setup.py file, open a command or terminal window and: cd into the root directory where setup.py is located. Enter: python setup.py install.

What is setup py package?

setup.py is a python file, the presence of which is an indication that the module/package you are about to install has likely been packaged and distributed with Distutils, which is the standard for distributing Python Modules. This allows you to easily install Python packages.

What is version in setup py?

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.


2 Answers

Set the version in setup.py only, and read your own version with pkg_resources, effectively querying the setuptools metadata:

file: setup.py

setup(     name='foobar',     version='1.0.0',     # other attributes ) 

file: __init__.py

from pkg_resources import get_distribution  __version__ = get_distribution('foobar').version 

To make this work in all cases, where you could end up running this without having installed it, test for DistributionNotFound and the distribution location:

from pkg_resources import get_distribution, DistributionNotFound import os.path  try:     _dist = get_distribution('foobar')     # Normalize case for Windows systems     dist_loc = os.path.normcase(_dist.location)     here = os.path.normcase(__file__)     if not here.startswith(os.path.join(dist_loc, 'foobar')):         # not installed, but there is another version that *is*         raise DistributionNotFound except DistributionNotFound:     __version__ = 'Please install this project with setup.py' else:     __version__ = _dist.version 
like image 194
Martijn Pieters Avatar answered Sep 27 '22 23:09

Martijn Pieters


I don't believe there's a canonical answer to this, but my method (either directly copied or slightly tweaked from what I've seen in various other places) is as follows:

Folder heirarchy (relevant files only):

package_root/  |- main_package/  |   |- __init__.py  |   `- _version.py  `- setup.py 

main_package/_version.py:

"""Version information."""  # The following line *must* be the last in the module, exactly as formatted: __version__ = "1.0.0" 

main_package/__init__.py:

"""Something nice and descriptive."""  from main_package.some_module import some_function_or_class # ... etc. from main_package._version import __version__  __all__ = (     some_function_or_class,     # ... etc. ) 

setup.py:

from setuptools import setup  setup(     version=open("main_package/_version.py").readlines()[-1].split()[-1].strip("\"'"),     # ... etc. ) 

... which is ugly as sin ... but it works, and I've seen it or something like it in packages distributed by people who I'd expect to know a better way if there were one.

like image 27
Zero Piraeus Avatar answered Sep 27 '22 23:09

Zero Piraeus