使用setup.py中依赖项的代码

时间:2013-05-29 19:35:24

标签: python setuptools

我有一个小的Web框架,我们称之为Bread,这是习惯的 构建Jam,Marmalade,PeanutButter等应用程序 浇头。将版本都包含在这些应用程序中。

我正在试图弄清楚如何制作应用程序setup.py 工作,给出以下要求:

  • 应用程序依赖于Bread,via setuptool's install_requires
  • 要在开发时构建应用程序,Bread会读取一些配置 然后将资产(HTML,JS,CSS,图像等)发布到 应用程序的output目录。换句话说,bread devserver 然后读取Jam/bread.yaml并在Jam/output中汇编资产 提供应用程序(通过Flask,但这不相关)。
  • 为了构建可部署的 Jam应用程序,我想调用 在python setup.py install Jam期间面包,构建 Jam/output。在制作中,Jam不需要构建任何东西。
  • 我已经定义了一个自定义bdist_egg设置命令 initialize_options导入Bread,调用构建器,然后设置 self.distribution.data_files之前有适当的元组 调用基类。 ( 很难搞清楚。)
  • 现在,bdist_egg在Jam的setup.py中定义。我想要 将此和其他样板代码移动到bread.setup,以便我 可以在Marmalade,PeanutButter等中重复使用它。
  • 这可能意味着我现在正在导入面包代码 面包已经安装。这肯定会在干净的安装中出现, 例如在构建机器上使用新的virtualenv。

可以使用Distutils / setuptools / Distribute吗?

1 个答案:

答案 0 :(得分:0)

我也在Distutils-SIG中提出了这个问题。 那里提到的setup_requires引导我 https://stackoverflow.com/a/12061891/6364,它给了我一些提示 我需要:在调用Distribution之前创建一个单独的setup对象 它定义了setup_requires条目。

Jam的setup.py现在看起来像:

from setuptools import setup, dist

dist.Distribution(dict(setup_requires='Bread'))

from bread.setup_topping import *

setup(
    name='Jam',
    version='0.2',
    long_description=open('README.md').read(),
    **topping_setup_options
)

# Remove *.egg left by bootstrapping Bread
cleanup_bread_bootstrap()

编辑:需要更好地解释Jam setup.py中发生的事情:

  • 最初Distribution(setup_requires='Bread')正在使用easy_install当前目录中安装Bread及其依赖项。
  • setup()的调用会触发下面的bdist_egg,它会使用面包 建立Jam的output。面包可以在当前目录中找到。
  • setup()稍后安装Jam,Bread和所有依赖项, 在正确的位置。
  • cleanup_bread_bootstrap()的调用删除了所有的鸡蛋 由最初的Distribution
  • 放在当前目录中

bread/setup_topping.py看起来像:

from setuptools.command.bdist_egg import bdist_egg as _bdist_egg
import os, fnmatch, glob, shutil

def recursive_data_files(treeroot, pattern):
    results = []
    for base, dirs, files in os.walk(treeroot):
        goodfiles = fnmatch.filter(files, pattern)
        if goodfiles:
            results.append((base, [os.path.join(base, f) for f in goodfiles]))
    return results

def make_data_files(output='output'):
    return (
        [('', ['bread.yaml'])]
        + recursive_data_files(output, '*')
    )

class bdist_egg(_bdist_egg):
    def initialize_options(self):
        bake_bread()    # build files to './output'
        self.distribution.data_files = make_data_files()
        _bdist_egg.initialize_options(self)

topping_setup_options = dict(
    cmdclass={
        'bdist_egg': bdist_egg,
    },
    install_requires=[
        'Bread',
    ],
    zip_safe=False,
)

def cleanup_bread_bootstrap(root='.'):
    for f in glob.glob(os.path.join(os.path.abspath(root), '*.egg')):
        if os.path.isdir(f):
            shutil.rmtree(f)  # Egg directory
        else:
            os.remove(f)      # Zipped Egg