«Где моя кнопка? Почему она неактивна?» Как часто программист может слышать эти слова от пользователей своего продукта? Скорее всего, более чем очень часто для того, чтобы задуматься, а может быть продукт сам должен отвечать на этот вопрос пользователей.
Вот приблизительно так выглядит обычная неактивная кнопка, которая, по какой-либо причине, в данный момент не доступна пользователю:

Она безмолвна, не интерактивна и не представляет пользователю ни малейшей информации о том, почему она находится в этом состоянии и при каких условиях станет активной. А вот как могла бы выглядеть «облагороженная», более информативная неактивная кнопка:

В чем же соль, спросите вы? А вот о том, как можно описывать правила на языке программирования Python, чтобы эти правила одновременно вычисляли статус активности кнопки и предоставляли отчет о причине в случае если кнопка должна быть деактивирована, я бы и хотел рассказать в этой статье.
Используя библиотеку собственного изготовления можно описать следующее правило на языке программирования Python:
Классы логических операций принимают операнды, обернутые в
Тогда использовать это правило, например в шаблоне Mako, можно следующим образом:
Как видно из примера, объект
В арсенале библиотеки доступны операции
В результате поиска в сети мне не удалось обнаружить что-либо похожее, поэтому пришлось написать свою библиотеку. Первая версия была выпущена совсем недавно. Мне будет очень интересно узнать о вашем опыте решения этой маленькой, но иногда довольно актуальной, задачи.
Вот приблизительно так выглядит обычная неактивная кнопка, которая, по какой-либо причине, в данный момент не доступна пользователю:

Она безмолвна, не интерактивна и не представляет пользователю ни малейшей информации о том, почему она находится в этом состоянии и при каких условиях станет активной. А вот как могла бы выглядеть «облагороженная», более информативная неактивная кнопка:

В чем же соль, спросите вы? А вот о том, как можно описывать правила на языке программирования Python, чтобы эти правила одновременно вычисляли статус активности кнопки и предоставляли отчет о причине в случае если кнопка должна быть деактивирована, я бы и хотел рассказать в этой статье.
Используя библиотеку собственного изготовления можно описать следующее правило на языке программирования Python:
from rules import _and_, _or_
# The rule
def can_user_add_comment(user, topic):
return _and_(
lambda: (user, “Вы не авторизованы”),
lambda: (user.is_status_active(), “Ваша учетная запись заблокирована”),
lambda: _or_(
lambda: (user.is_in_admin_group(), “Вы не администратор”),
lambda: _and_(
lambda: (topic.is_status_open(), “тема закрыта”),
lambda: (user.has_enough_karma_to_add_comment(), “у Вас не достаточно кармы для комментирования”),
lambda: (user.is_below_comments_per_minute_quota(), “Вы комментируете слишком интенсивно, повторите попытку через пару минут”),
),
),
)
Классы логических операций принимают операнды, обернутые в
lambda, которые будут вызваны для вычисления значений при необходимости. Т.е. вычисления происходят по «укороченной схеме», например, _and_ вычисляет значения своих аргументов до первого False, _or_ — до первого True. Каждый операнд состоит из собственно тестируемого значения (первый элемент кортежа) и сообщения (второй элемент кортежа), которое используется когда тестируемое значение приняло значение False. Так же, при необходимости, можно опускать сообщения для не значимых частей правила (операндов) с точки зрения информирования пользователя.Тогда использовать это правило, например в шаблоне Mako, можно следующим образом:
<%
user = get_authenticated_user()
granted = can_user_add_comment(user, current_topic)
%>
<input
type=”button”
value=”Добавить комментарий”
title=”${”Добавить комментарий” if granted else unicode(granted)}”
${“disabled” if not granted else “”}
/>
Как видно из примера, объект
granted, полученный в результате вызова функции can_user_add_comment(), в булевом контексте сообщает статус активности кнопки, а в строковом контексте сообщает причину, если в булевом контексте он вернул значение False. Причина неактивности кнопки записывается в ее title и извлекается пользователем при наведении на нее курсора мыши. По умолчанию в отчет попадают только конкретные сообщения, результат вычисления правил которых оказался False. Но так же возможно сгенерировать полный древовидный отчет о том, какие логические ветки всего правила вернули значение False. Для этого надо вызвать granted.build_report() или granted.build_html_report().В арсенале библиотеки доступны операции
_and_, _or_, _not_ и _true_.В результате поиска в сети мне не удалось обнаружить что-либо похожее, поэтому пришлось написать свою библиотеку. Первая версия была выпущена совсем недавно. Мне будет очень интересно узнать о вашем опыте решения этой маленькой, но иногда довольно актуальной, задачи.