Articles with the tag setuptools

Getting package version from code without importing


Posted on 2015-04-07


I use this code for getting version info from package code without importing it, as it has to be installed to be imported and it can't be installed without version number. Classic 'Chicken or the egg' dilema.

I'm using ast module from Python stdlib to parse file from package code. In example I'm using __init__.py but one can use any other file.

It's works with module level variables (only string or number) and it's alternative to using eval() or exec().

setup.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# coding=utf-8
import os
import ast
from setuptools import setup, find_packages


def get_info(filename):
    info = {}
    with open(filename) as _file:
        data = ast.parse(_file.read())
        for node in data.body:
            if type(node) != ast.Assign:
                continue
            if type(node.value) not in [ast.Str, ast.Num]:
                continue
            name = None
            for target in node.targets:
                name = target.id
            if type(node.value) == ast.Str:
                info[name] = node.value.s
            elif type(node.value) == ast.Num:
                info[name] = node.value.n
    return info

file_with_packageinfo = "packagename/__init__.py"
info = get_info(file_with_packageinfo)

here = os.path.abspath(os.path.dirname(__file__))
# README = open(os.path.join(here, 'README.txt')).read()
# CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()


requires = [
]

setup(name='packagename',
      version=info.get('__version__', '0.0.0'),
      description='Package description',
      # long_description=README + '\n\n' + CHANGES,
      classifiers=[
          "Programming Language :: Python ",
      ],
      author=info.get('__author__', 'Łukasz Bołdys'),
      author_email='[email protected]',
      url='http://dev.utek.pl',
      keywords='',
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='packagename',
      install_requires=requires,
      entry_points="""\
      [console_scripts]
          ddd = packagename.scripts.analyze:main
      """,
      )

packagename/__init__.py

1
2
3
4
# coding=utf-8

__version__ = "0.5.1"
__author__ = "Łukasz Bołdys"

Leave a comment

Extending setup.py install commands


Posted on 2015-03-11


Lately one of my associates asked if there is a way to use different install_requires lists in setup.py depending on way of installing.

If you are doing python setup.py install you would get one set of requires and doing python setup.pl develop would give you another set of requires (either extended or totally different).

Here's my solution:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/env python
# coding=utf-8

from setuptools import setup, find_packages
from setuptools.command.develop import develop

requires = [
    'fabric',
    'pelican'
]


class ExtendedDevel(develop):
    ''' Adding ipython to requirements '''
    def run(self):
        requires.append('ipython')
        develop.run(self)


setup(name='lalala',
      version='0.0.1',
      description='That\'s stupid',
      long_description='DESCRIPTION',
      classifiers=[
      ],
      author='Łukasz Bołdys',
      author_email='[email protected]',
      url='',
      keywords='',
      license='LICENSE',
      packages=find_packages(),
      include_package_data=True,
      zip_safe=False,
      test_suite='test',
      install_requires=requires,
      cmdclass={'develop': ExtendedDevel}
      )

Using this code in setup.py will install fabric, pelican and ipython when doing python setup.py develop but will only install fabric and pelican if installing via python setup.py install.

If you don't want to change default behavior of develop you can add new command with changing cmdclass={'develop': ExtendedDevel} to cmdclass={'newcommand': ExtendedDevel}.

Edit 2015-04-22 10:47:20:

As I first needed method explained above to add some lib to development enviroment that was not needed in production enviroment. But there is better method to do it.

You can pass 'extras_require' argument to setup(). 'extras_require' is and dictionary of 'targets' as key and list of additional requirements as value. See documentation for more info.

Leave a comment

Categories

Tags

Links