+ 3.2_10
This commit is contained in:
parent
4a67ceca43
commit
fb4a932136
79
mod_oop/3.2_10_request_handler.py
Normal file
79
mod_oop/3.2_10_request_handler.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
"""
|
||||||
|
https://stepik.org/lesson/701987/step/4?unit=702088
|
||||||
|
|
||||||
|
Необходимо объявить класс-декоратор с именем Handler, который можно было бы применять к функциям следующим образом:
|
||||||
|
|
||||||
|
@Handler(methods=('GET', 'POST')) # по умолчанию methods = ('GET',)
|
||||||
|
def contact(request):
|
||||||
|
return "Сергей Балакирев"
|
||||||
|
Здесь аргумент methods декоратора Handler содержит список разрешенных запросов для обработки. Сама декорированная функция вызывается по аналогии с предыдущим подвигом:
|
||||||
|
|
||||||
|
res = contact({"method": "POST", "url": "contact.html"})
|
||||||
|
В результате функция contact должна возвращать строку в формате:
|
||||||
|
|
||||||
|
"<метод>: <данные из функции>"
|
||||||
|
|
||||||
|
В нашем примере - это будет:
|
||||||
|
|
||||||
|
"POST: Сергей Балакирев"
|
||||||
|
|
||||||
|
>>> @Handler(methods=('GET', 'POST')) # по умолчанию methods = ('GET',)
|
||||||
|
... def contact(request):
|
||||||
|
... return "Сергей Балакирев"
|
||||||
|
>>> contact({"method": "POST", "url": "contact.html"})
|
||||||
|
'POST: Сергей Балакирев'
|
||||||
|
|
||||||
|
|
||||||
|
Если ключ method в словаре request отсутствует, то по умолчанию подразумевается GET-запрос. Если ключ method принимает значение отсутствующее в списке methods декоратора Handler, например, "PUT", то декорированная функция contact должна возвращать значение None.
|
||||||
|
|
||||||
|
Для имитации GET и POST-запросов в классе Handler необходимо объявить два вспомогательных метода с сигнатурами:
|
||||||
|
|
||||||
|
def get(self, func, request, *args, **kwargs) - для имитации обработки GET-запроса
|
||||||
|
def post(self, func, request, *args, **kwargs) - для имитации обработки POST-запроса
|
||||||
|
|
||||||
|
В зависимости от типа запроса должен вызываться соответствующий метод (его выбор в классе можно реализовать методом __getattribute__()). На выходе эти методы должны формировать строки в заданном формате.
|
||||||
|
|
||||||
|
P.S. В программе достаточно объявить только класс. Ничего на экран выводить не нужно.
|
||||||
|
|
||||||
|
Небольшая справка
|
||||||
|
Для реализации декоратора с параметрами на уровне класса в инициализаторе __init__(self, methods) прописываем параметр для декоратора, а магический метод __call__() объявляем как полноценный декоратор на уровне функции, например:
|
||||||
|
|
||||||
|
class Handler:
|
||||||
|
def __init__(self, methods):
|
||||||
|
# здесь нужные строчки
|
||||||
|
|
||||||
|
def __call__(self, func):
|
||||||
|
def wrapper(request, *args, **kwargs):
|
||||||
|
# здесь нужные строчки
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
Handler=[(setattr(a,"get",0),setattr(a,"post",0),a)[2]for a in[lambda **b:lambda c:lambda d,*e,**f:[h in(g or["GET"])and f"{h}: {c(d,*e,**f)}"or None for g in[b["methods"]]for h in[d.get("method",g and g[0]or"GET")]][0]]][0]
|
||||||
|
|
||||||
|
|
||||||
|
def tests():
|
||||||
|
assert hasattr(Handler, 'get') and hasattr(Handler, 'post'), "класс Handler должен содержать методы get и post"
|
||||||
|
|
||||||
|
@Handler(methods=('GET', 'POST'))
|
||||||
|
def contact2(request):
|
||||||
|
return "контакты"
|
||||||
|
|
||||||
|
assert contact2({"method": "POST"}) == "POST: контакты", "декорированная функция вернула неверные данные"
|
||||||
|
assert contact2({"method": "GET"}) == "GET: контакты", "декорированная функция вернула неверные данные"
|
||||||
|
assert contact2({"method": "DELETE"}) is None, "декорированная функция вернула неверные данные"
|
||||||
|
assert contact2({}) == "GET: контакты", "декорированная функция вернула неверные данные при указании пустого словаря"
|
||||||
|
|
||||||
|
@Handler(methods=('POST'))
|
||||||
|
def index(request):
|
||||||
|
return "index"
|
||||||
|
|
||||||
|
assert index({"method": "POST"}) == "POST: index", "декорированная функция вернула неверные данные"
|
||||||
|
assert index({"method": "GET"}) is None, "декорированная функция вернула неверные данные"
|
||||||
|
assert index({"method": "DELETE"}) is None, "декорированная функция вернула неверные данные"
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
||||||
|
tests()
|
Loading…
Reference in New Issue
Block a user