Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Уведомления окончаний fabric задач, с декораторами и детальной информацией

Anna | 15.06.2014 | нет комментариев

В присутствующем плане есть долгоиграющие fab-задачки — приобретения дампов с удаленных серверов, агрегация данных, етс. Запускаешь задачу, отвлекаешься в соседнее окошко, через N минут(а то и через час) припоминаешь, проверяешь… неэффективно.
Захотелось сделать всплывающие уведомления на десктоп по заключении задачи, а здесь и статья про notify-send подвернулась. Решил сделать декоратор на fab-функции — самое ему место.

Для начала пишем примитивную функцию уведомления

from django.conf import settings as django_settings
from fabric.operations import local

def _notify(message):
    if django_settings.FAB_NOTIFY_TASK_ENDS:
        local(u'notify-send --expire-time=10000 "Fabric notify" "{}"'.format(message))

Да, у меня джанга и настройку «показывать ли подсказки» вынеcем в настройки.

Применение _notify тоже примитивное:

from fab_utils import _notify

def mongo_get_from_remote(server='', date='', collection=''):
    u"""Загрузить базы монго c удаленного сервера"""
    ...
    _notify(u"Базы загружены")

Но в всякой функции писать вызов в конце… как-то не «сухо» (DRY рулит). Напишем декоратор

def notified(wrapped):
    def internal(*args, **kwargs):
        res = wrapped(*args, **kwargs)
        params = [unicode(a) for a in args]
        params.extend([u'{}={}'.format(k, v) for k, v in kwargs.iteritems()])
        params = [_limit_str(p) for p in params]
        message = "{}({}) ended!!!".format(wrapped.__name__, ', '.join(params))
        _notify(message)
        return res
    return internal

И тогда применение такое

from fab_utils import notified

@notified
def mongo_get_from_remote(server='', date='', collection=''):
    u"""Загрузить базы монго c удаленного сервера"""
    ...

Все бы отлично, но перестала выводится справка по команде :(

wad@wad-vaio:~/aggregator (develop)$ bin/fab.sh -d mongo_get_from_remote
Displaying detailed information for task 'mongo_get_from_remote':

    No docstring provided
    Arguments:

Что же делать? нужно переопределить докстринг!

def notified(wrapped):
    def internal(*args, **kwargs):
        ...
        return res
    internal.__doc__ = wrapped.__doc__
    return internal

 

wad@wad-vaio:~/aggregator (develop!)$ bin/fab.sh -d mongo_get_from_remote
Displaying detailed information for task 'mongo_get_from_remote':

    Загрузить базы монго c удаленного сервера server='', date='', collection=''
    Arguments:

Теснее отменнее, но где же доводы? За ними пришлось лезть в кишочки fabric — как он их определяет?

В файле env/local/lib/python2.7/site-packages/fabric/main.py:466 нашлось

def display_command(name):
    """
    Print command function's docstring, then exit. Invoked with -d/--display.
    """
    ...
    if hasattr(command, '__details__'):
        task_details = command.__details__()
    else:
        task_details = get_task_details(command)
    ...

Ага, если у функции есть __details__ то он вызовется для определения доводов. Отменно!

Итоговый код декоратора таков

from fabric.tasks import get_task_details

def notified(wrapped):

    def internal(*args, **kwargs):
        res = wrapped(*args, **kwargs)
        params = [unicode(a) for a in args]
        params.extend([u'{}={}'.format(k, v) for k, v in kwargs.iteritems()])
        params = [_limit_str(p) for p in params]
        message = "{}({}) ended!!!".format(wrapped.__name__, ', '.join(params))
        _notify(message)
        return res

    def _details():
        return get_task_details(wrapped)

    internal.__doc__ = wrapped.__doc__
    internal.__details__ = _details
    return internal

И изложение fab-задачки на месте

wad@wad-vaio:~/aggregator (develop!)$ bin/fab.sh -d mongo_get_from_remote
Displaying detailed information for task 'mongo_get_from_remote':

    Загрузить базы монго c удаленного сервера server='', date='', collection=''
    Arguments: server='', date='', collection=''

Люблю python :)

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB