quasiyoke
quasiyoke

Reputation: 719

Running custom setuptools build during install

I've tried to implement Compass compiling during setuptools' build, but the following code runs compilation during explicit build command and doesn't runs during install.

#!/usr/bin/env python

import os
import setuptools
from distutils.command.build import build


SETUP_DIR = os.path.dirname(os.path.abspath(__file__))


class BuildCSS(setuptools.Command):
    description = 'build CSS from SCSS'

    user_options = []

    def initialize_options(self):
        pass

    def run(self):
        os.chdir(os.path.join(SETUP_DIR, 'django_project_dir', 'compass_project_dir'))
        import platform
        if 'Windows' == platform.system():
            command = 'compass.bat compile'
        else:
            command = 'compass compile'
        import subprocess
        try:
            subprocess.check_call(command.split())
        except (subprocess.CalledProcessError, OSError):
            print 'ERROR: problems with compiling Sass. Is Compass installed?'
            raise SystemExit
        os.chdir(SETUP_DIR)

    def finalize_options(self):
        pass


class Build(build):
    sub_commands = build.sub_commands + [('build_css', None)]


setuptools.setup(
    # Custom attrs here.
    cmdclass={
        'build': Build,
        'build_css': BuildCSS,
    },
)

Any custom instructions at Build.run (e.g. some printing) doesn't apply during install too, but dist instance contains in commands attribute only my build command implementation instances. Incredible! But I think the trouble is in complex relations between setuptools and distutils. Does anybody knows how to make custom building run during install on Python 2.7?

Update: Found that install definitely doesn't calls build command, but it calls bdist_egg which runs build_ext. Seems like I should implement "Compass" build extension.

Upvotes: 9

Views: 5707

Answers (1)

quasiyoke
quasiyoke

Reputation: 719

Unfortunatelly, I haven't found the answer. Seems like the ability to run post-install scripts correctly there's only at Distutils 2. Now you can use this work-around:

Update: Because of setuptools' stack checks, we should override install.do_egg_install, not run method:

from setuptools.command.install import install

class Install(install):
    def do_egg_install(self):
        self.run_command('build_css')
        install.do_egg_install(self)

Update2: easy_install runs exactly bdist_egg command which is used by install too, so the most correct way (espetially if you want to make easy_install work) is to override bdist_egg command. Whole code:

#!/usr/bin/env python

import setuptools
from distutils.command.build import build as _build
from setuptools.command.bdist_egg import bdist_egg as _bdist_egg


class bdist_egg(_bdist_egg):
    def run(self):
        self.run_command('build_css')
        _bdist_egg.run(self)


class build_css(setuptools.Command):
    description = 'build CSS from SCSS'

    user_options = []

    def initialize_options(self):
        pass

    def finalize_options(self):
        pass

    def run(self):
        pass # Here goes CSS compilation.


class build(_build):
    sub_commands = _build.sub_commands + [('build_css', None)]


setuptools.setup(

    # Here your setup args.

    cmdclass={
        'bdist_egg': bdist_egg,
        'build': build,
        'build_css': build_css,
    },
)

You may see how I've used this here.

Upvotes: 8

Related Questions