Использование кода из зависимости в setup.py

У меня есть небольшой веб-фреймворк, назовем его Bread, который используется для создания таких приложений, как Jam, Marmalade, PeanutButter и других начинок. Хлеб и создает, и обслуживает эти приложения.

Я пытаюсь понять, как заставить приложения работать setup.py, учитывая следующие требования:

  • Приложения зависят от Bread через install_requires в setuptool.
  • Чтобы создать приложение во время разработки, Bread считывает некоторую конфигурацию, а затем передает ресурсы (HTML, JS, CSS, изображения и т. д.) в каталог приложения output. Другими словами, bread devserver читает Jam/bread.yaml и собирает активы в Jam/output, а затем обслуживает приложение (через Flask, но это не имеет отношения к делу).
  • Чтобы создать развертываемое приложение Jam, я хочу вызвать Bread во время python setup.py install Jam для сборки Jam/output. В продакшене Jam не нужно ничего строить.
  • Я определил пользовательскую команду установки bdist_egg, где initialize_options импортирует Bread, вызывает компоновщик, затем устанавливает self.distribution.data_files с соответствующими кортежами перед вызовом базового класса. (И это было неинтересно выяснять.)
  • Прямо сейчас bdist_egg определяется в setup.py Jam. Я хочу переместить этот и другой шаблонный код в bread.setup, чтобы я мог повторно использовать его в Marmalade, PeanutButter и т. д.
  • Потенциально это означает, что теперь я импортирую код Bread до того, как Bread будет установлен. Это наверняка возникнет при чистой установке, например, при новой виртуальной среде на машине сборки.

Можно ли это сделать с помощью Distutils/setuptools/Distribute?


person George V. Reilly    schedule 29.05.2013    source источник


Ответы (1)


Я также задал этот вопрос в Distutils-SIG. Упоминание там setup_requires привело меня к https://stackoverflow.com/a/12061891/6364, что дало мне подсказка, которая мне нужна: создайте отдельный объект Distribution перед вызовом setup, который определяет записи setup_requires.

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, который использует Bread для создания output Jam. Хлеб находится в текущем каталоге.
  • 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
person George V. Reilly    schedule 30.05.2013
comment
Побочные эффекты повсюду. Ой. - person offby1; 30.05.2013