2016-01-28 5 views
3

В проектах JavaScript, я могу указать следующее в моих package.json:Как я могу легко создать свои собственные команды setup.py?

{ 
    "name": "dredd", 
    "version": "1.0.4", 
    "description": "API Blueprint testing tool", 
    "main": "lib/dredd.js", 
    "bin": { 
    "dredd": "bin/dredd" 
    }, 
    "scripts": { 
    "lint": "coffeelint ./src", 
    "pretest": "npm run lint", 
    "test": "find ./test/ -name '*-test.coffee' | xargs mocha --compilers 'coffee:coffee-script/register' --reporter spec --timeout 120000 --recursive", 
    ... 
    "coveralls": "./scripts/coveralls.sh", 
    ... 
    }, 
    "dependencies": { 
    ... 

Смотрите раздел scripts. Я могу определить любой «скрипт» любого имени и любой реализации. Тогда я могу запустить его как npm run <name> (и некоторые специальные, я могу даже запустить непосредственно как npm <name>, например npm test). Реализация «скрипта» может быть только одной командой или строкой, которая работает так же, как и в моей оболочке (в то время как переносимость - это то, что мне нужно для достижения самостоятельно, npm не помогает мне в этом, но это ОК). npm правильно передает любые заданные аргументы, а также коды выхода. Таким образом, чтобы подвести итог, я могу:

  • определить пользовательские команды
  • определяют pre<name> команды, которые будут выполняться всегда перед <name> команда получает вызывается
  • эти команды могут быть в основном все, что иначе работать в моем терминале
  • они правильно размножать аргументы и коды выхода, из коробки
  • в идеале, родительская команда может список доступных сценариев

Так что это что-то вроде rake, , grunt, gulp и т. Д., Но встроенный и очень простой, очень простой в управлении. Я пропущу что-то подобное в проектах Python. Я чувствую, что setup.py - это файл, который изначально имел в виду единственная точка входа в проекты Python, и мне нравится идея, и я хотел бы ее охватить. В идеале я хотел бы иметь что-то вроде:

python setup.py test 
python setup.py lint 
python setup.py <my command> 

Я хочу одну точку входа, потому что я хочу, чтобы мой проект был интуитивным. Люди не должны быть вынуждены читать документацию или .travis.yml для запуска linter, тестов и т. Д. Для моего проекта. Им не нужно заботиться о том, использую ли я nosetests или py.test для тестирования или flake8 для литья. Это детализация реализации.

Однако этого, по-видимому, нелегко достичь. Например. Я бы хотел, чтобы моя команда lint содержала flake8 и, возможно, другие материалы. Затем я хочу, чтобы моя команда test также всегда запускала lint, прежде чем она запустится сама.

Я видел некоторые способы реализации пользовательских команд путем подкласса Command и имеющий объявление такой команды в setup(...) в setup.py, но я не нашел красивой официальной документации. Кроме того, многие статьи старые, и очень сложно понять текущее состояние дел и современную передовую практику в 2016 году, поскольку существует исторически множество проектов, связанных с упаковкой (distutils, setuptools, pip, easy_install, ...). Даже если я смогу реализовать класс и вызвать его, и у вас есть команда, указанная в python setup.py --help, мне все равно придется реализовать себе часть подпроцесса, код выхода, stdin, stderr и перенаправление аргументов. Это слишком сложно для моего сценария, я хочу, чтобы мой проект был прост и сосредоточен на его собственной цели.

Тестовые фреймворки обычно идут путем реализации некоторых специальных команд тяжелого веса, которые могут быть установлены как замена для python setup.py test.Реализация выполняется на сотнях строк, и если я хочу добавить что-то к команде (например, если я хочу, чтобы flake8 && pytest tests каждый раз, когда я вызываю python setup.py test), это кажется едва достижимым.

Я видел много людей, чтобы уйти от правильного проектирования команд, как они слишком трудно писать, и они just do following:

# setup.py 
if sys.argv[0] == 'test': 
    # do something 

if sys.argv[0] == 'publish': 
    # do something 

setup(... 

Это просто, но это не интегрирована в существующую setup.py инфраструктуру и I все равно нужно выполнить всю работу подпроцесса, если я хочу просто вызвать команду оболочки. Кроме того, я не уверен, что можно легко вызвать исходную команду (например, я хочу обернуть python setup.py test чем-то, поэтому я напишу блок if sys.argv[0] == 'test': и сделаю что-то обычай, но как я могу продолжить тестирование после этого? docs для этого ...).

Ни один из вышеперечисленных вариантов не прост в написании или обслуживании. Тем не менее, я не верю, что нет ничего похожего на то, что я ищу в экосистеме Python. Я думаю, что я должен что-то упустить. Может ли кто-нибудь указать мне хотя бы на правильное направление? По крайней мере, объясните мне ситуацию с setuptools и distutils и где я могу найти всю соответствующую документацию?

ответ

1

Супер простые баребоны подход. Требуется, чтобы в вашей системе было установлено flake8.

class Flake8(Command): 
    def initialize_options(self): 
     pass 

    def finalize_options(self): 
     pass 

    def run(self): 
     errno = os.system("flake8 <dir-needing-linting>") 
     sys.exit(errno) 
Смежные вопросы