Декораторы

Да, в питоне это весьма прикольная вещица как декоратор, которорая упрощает композицию функций. В ходе тестов, я начал выплевывать огромные количества данных: потому что хз что не так. И этот вывод начинает смешиваться с выводом тест-фреймворка, так еще и сами тесты между собой(хоть и идут друг за другом). Ах да, и конечно принты в самом коде. В общем получаю не читаемую пелену. Не долго думая вставил в начале и конце функции каждого теста про принту границы:

============== RUN test_calculations
// code code code
============== END test_calculations

Да, просто печатаю таких милашек. Имя теста поначалу вшивал и сразу бесился. А тут еще напечатать список транзакций в колоночку охота, но заполнять тесты for...in... что уж совсем перебор. И тут я вспоминаю про декоратор.

Границы списка

def print_borders(fn, header="=================", footer="================="):
    def wrap(*args, **kwargs):
        print("======%s=======" % header)
        fn(*args, **kwargs)
        print("======%s=======" % footer)
    return wrap

args, kwargs это мы транслируем аргументы переданные функции-wrapper’у в непосредственно функцию-исполнителя.

@print_borders
def print_list(l, header=None):
    """Show list with header + footer """
    if header:
        print(header)
    for e in l:
        print(e)

Здесь, args содержит l, а kwargs - header.

Дальше все как обычно:

print_list([1,2,3,4])
=============================
1
2
3
4
=============================

Тырим имя функции

Мета доступ и все как класс, это конечно очень круто.

def print_fn_bord(fn):
    h = " RUN %s " % fn.__name__
    f = " END %s " % fn.__name__

    def wrap(*args, **kwargs):
        fn(*args, **kwargs)
    return print_borders(fn=wrap, header=h, footer=f)

Функцию теста я теперь создаю так:

@print_fn_bord
def test_calcs(self):
	pass

Здесь, args содержит тот самый self. Были бы еще параметры у функции test_calcs - они бы были “распакованы” в параметры функции wrap.

При запуске этой функции выплевывается

======= RUN %func_name% =======
// prints
======= END %func_name% =======