Команда Flask-Script, которая передает все оставшиеся аргументы носу?

Я использую простую команду для запуска тестов с помощью носа:

@manager.command
def test():
    """Run unit tests."""
    import nose
    nose.main(argv=[''])

Впрочем, нос поддерживает множество полезных аргументов, мимо которых я сейчас не мог пройти.

Есть ли способ запустить нос с помощью команды менеджера (аналогично вызову выше) и при этом иметь возможность передавать аргументы носу? Например:

python manage.py test --nose-arg1 --nose-arg2

Прямо сейчас я получаю сообщение об ошибке от Manager, что --nose-arg1 --nose-arg2 не распознаются как допустимые аргументы. Я хочу передать эти аргументы как nose.main(argv= <<< args comming after python manage.py test ... >>>)


person ddinchev    schedule 10.02.2016    source источник
comment
Если количество аргументов самого python остается постоянным, вы можете просто передать argv[3:] из sys   -  person Wombatz    schedule 10.02.2016
comment
Это была моя первая попытка, но диспетчер Flask-Script выходит с ошибкой, если видит нераспознанные аргументы, вместо того, чтобы игнорировать их. Решением моей проблемы было бы заставить его игнорировать остальные аргументы и иметь возможность принимать их так, как вы предложили.   -  person ddinchev    schedule 10.02.2016
comment
Ну, я должен прочитать вопрос более внимательно. Я нашел хакерский способ сделать то, что вы хотите. Я напишу ответ на это.   -  person Wombatz    schedule 10.02.2016


Ответы (3)


Flask-Script имеет недокументированный флаг capture_all_flags, который передаст оставшиеся аргументы методу Command.run. Это продемонстрировано в тестах.

@manager.add_command
class NoseCommand(Command):
    name = 'test'
    capture_all_args = True

    def run(self, remaining):
        nose.main(argv=remaining)
python manage.py test --nose-arg1 --nose-arg2
# will call nose.main(argv=['--nose-arg1', '--nose-arg2'])
person davidism    schedule 10.02.2016

В источниках flask_script вы можете видеть, что ошибка "too many arguments" предотвращается, когда исполняемый Command имеет атрибут capture_all_args, установленный на True, который нигде не задокументирован.

Вы можете установить этот атрибут в классе непосредственно перед запуском менеджера

if __name__ == "__main__":
    from flask.ext.script import Command
    Command.capture_all_args = True
    manager.run()

Таким образом, всегда принимаются дополнительные аргументы менеджеру.

Недостатком этого быстрого исправления является то, что вы больше не можете регистрировать параметры или аргументы для команд обычным способом.

Если вам все еще нужна эта функция, вы можете создать подкласс Manager и переопределить декоратор command следующим образом.

class MyManager(Manager):
    def command(self, capture_all=False):
        def decorator(func):
            command = Command(func)
            command.capture_all_args = capture_all
            self.add_command(func.__name__, command)

            return func
        return decorator

Затем вы можете использовать декоратор command следующим образом:

@manager.command(True)  # capture all arguments
def use_all(*args):
    print("args:", args[0])

@manager.command()  # normal way of registering arguments
def normal(name):
    print("name", name)

Обратите внимание, что по какой-то причине flask_script требует, чтобы use_all принимал varargs, но будет хранить список аргументов в args[0], что немного странно. def use_all(args): не работает и не работает с TypeError "got multiple values for argument 'args'"

person Wombatz    schedule 10.02.2016

Столкнулся с проблемой с davidism soln, когда были получены только некоторые аргументы.

Просматривая документы немного больше, задокументировано, что Nose.main автоматически подхватывает stdin

http://nose.readthedocs.io/en/latest/api/core.html

Итак, теперь мы просто используем:

@manager.add_command
class NoseCommand(Command):
    name = 'nose'
    capture_all_args = True

    def run(self, remaining):
        nose.main()
person applewood    schedule 22.11.2016