Last active
May 24, 2016 09:31
-
-
Save myarik/b1acebf33dcc0eeecf8d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import functools | |
def float_args_and_return(function): | |
@functools.wraps(function) | |
def wrapper(*args, **kwargs): | |
args = [float(arg) for arg in args] | |
return float(function(*args, **kwargs)) | |
return wrapper | |
@float_args_and_return | |
def mean(first, second, *rest): | |
numbers = (first, second) + rest | |
return sum(numbers)/len(numbers) | |
def statically_typed(return_type = None, *types): | |
def decorator(function): | |
@functools.wraps(function) | |
def wrapper(*args, **kwargs): | |
if len(args) > len(types): | |
raise ValueError("too many arguments") | |
elif len(args) < len(types): | |
raise ValueError("too few arguments") | |
for i, (arg, type_) in enumerate(zip(args, types)): | |
if not isinstance(arg, type_): | |
raise ValueError("argument {} must be of type {}".format(i , type_.__name__)) | |
result = function(*args, **kwargs) | |
if (return_type is not None and not isinstance(result, return_type)): | |
raise ValueError("return value must be of type {}".format(return_type.__name__)) | |
return result | |
return wrapper | |
return decorator | |
# Method decorator | |
class ImportantStuff(object): | |
@time_this | |
def do_stuff_1(self): | |
... | |
@time_this | |
def do_stuff_2(self): | |
... | |
@time_this | |
def do_stuff_3(self): | |
... | |
def time_this(original_function): | |
print "decorating" | |
def new_function(*args,**kwargs): | |
print "starting timer" | |
import datetime | |
before = datetime.datetime.now() | |
x = original_function(*args,**kwargs) | |
after = datetime.datetime.now() | |
print "Elapsed Time = {0}".format(after-before) | |
return x | |
return new_function | |
# Class decorator | |
@time_all_class_methods | |
class ImportantStuff: | |
def do_stuff_1(self): | |
... | |
def do_stuff_2(self): | |
... | |
def do_stuff_3(self): | |
... | |
ImportantStuff = time_all_class_methods(ImportantStuff) | |
def time_all_class_methods(Cls): | |
class NewCls(object): | |
def __init__(self,*args,**kwargs): | |
self.oInstance = Cls(*args,**kwargs) | |
def __getattribute__(self,s): | |
""" | |
this is called whenever any attribute of a NewCls object is accessed. This function first tries to | |
get the attribute off NewCls. If it fails then it tries to fetch the attribute from self.oInstance (an | |
instance of the decorated class). If it manages to fetch the attribute from self.oInstance, and | |
the attribute is an instance method then `time_this` is applied. | |
""" | |
try: | |
x = super(NewCls,self).__getattribute__(s) | |
except AttributeError: | |
pass | |
else: | |
return x | |
x = self.oInstance.__getattribute__(s) | |
if type(x) == type(self.__init__): # it is an instance method | |
return time_this(x) # this is equivalent of just decorating the method with time_this | |
else: | |
return x | |
return NewCls | |
# Define the validation wrapper | |
def ensure(name, validate, doc=None): | |
def decorator(Class): | |
privateName = "__" + name | |
def getter(self): | |
return getattr(self, privateName) | |
def setter(self, value): | |
validate(name, value) | |
setattr(self, privateName, value) | |
setattr(Class, name, property(getter, setter, doc=doc)) | |
return Class | |
return decorator | |
@ensure("url", is_str) | |
class Person(object): | |
def http_methods(methods=[]): | |
""" | |
Данный декоратор проверяет метод HTTP запроса, | |
который пришел на вью, перед тем как | |
она будет вызвана. | |
Удобен тем, что можно задать набор HTTP слов, | |
на которые вьюха будет реагировать. В противном случае Http404. | |
""" | |
def decorator(func): | |
def wrapper(request, *args, **kwargs): | |
if request.method in methods: | |
view = func(request, *args, **kwargs) | |
return view | |
raise Http404 | |
return wrapper | |
return decorator | |
#... | |
@http_methods(methods=['POST', 'GET']) | |
def your_view(request, *args, **kwargs): | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment