Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to perform custom build steps in setup.py?

The distutils module allows to include and install resource files together with Python modules. How to properly include them if resource files should be generated during a building process?

For example, the project is a web application which contains CoffeeScript sources that should be compiled into JavaScript and included in a Python package then. Is there a way to integrate this into a normal sdist/bdist process?

like image 373
eigenein Avatar asked Jan 21 '13 15:01

eigenein


People also ask

What does setup py build do?

The setup.py is a Python script typically included with Python-written libraries or apps. Its objective is to ensure that the program is installed correctly. With the aid of pip , we can use the setup.py to install any module without having to call setup.py directly. The setup.py is a standard Python file.

What is Package_dir in setup py?

package_dir = {'': 'lib'} in your setup script. The keys to this dictionary are package names, and an empty package name stands for the root package. The values are directory names relative to your distribution root.


2 Answers

I spent a fair while figuring this out, the various suggestions out there are broken in various ways - they break installation of dependencies, or they don't work in pip, etc. Here's my solution:

in setup.py:

from setuptools import setup, find_packages
from setuptools.command.install import install
from distutils.command.install import install as _install

class install_(install):
    # inject your own code into this func as you see fit
    def run(self):
        ret = None
        if self.old_and_unmanageable or self.single_version_externally_managed:
            ret = _install.run(self)
        else:
            caller = sys._getframe(2)
            caller_module = caller.f_globals.get('__name__','')
            caller_name = caller.f_code.co_name

            if caller_module != 'distutils.dist' or caller_name!='run_commands':
                _install.run(self)
            else:
                self.do_egg_install()

        # This is just an example, a post-install hook
        # It's a nice way to get at your installed module though
        import site
        site.addsitedir(self.install_lib)
        sys.path.insert(0, self.install_lib)
        from mymodule import install_hooks
        install_hooks.post_install()
        return ret

Then, in your call to the setup function, pass the arg:

cmdclass={'install': install_}

You could use the same idea for build as opposed to install, write yourself a decorator to make it easier, etc. This has been tested via pip, and direct 'python setup.py install' invocation.

like image 57
nerdvegas Avatar answered Sep 21 '22 03:09

nerdvegas


The best way would be to write a custom build_coffeescript command and make it a subcommand of build. More details are given in other replies to similar/duplicate questions, for example this one:

https://stackoverflow.com/a/1321345/150999

like image 31
merwok Avatar answered Sep 22 '22 03:09

merwok