Skip to content

Instantly share code, notes, and snippets.

@ssut
Last active August 24, 2019 08:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ssut/6ecf93fac9457dd623b0 to your computer and use it in GitHub Desktop.
Save ssut/6ecf93fac9457dd623b0 to your computer and use it in GitHub Desktop.
Python decorator endpoint implementation (like Flask blueprint module) - O(1)
#-*- coding: utf-8 -*-
import time
from collections import namedtuple
from test import ep as app
BenchResult = namedtuple('BenchResult', ['str', 'time'])
def benchmark(str, times=100000):
t_start = time.time()
for i in range(times):
app(str)
t_end = time.time()
result = BenchResult(str=str, time=t_end - t_start)
return result
if __name__ == '__main__':
print benchmark(u'안녕')
print benchmark(u'ㅎㅇ')
print benchmark(u'가나다')
print benchmark(u'가나라마')
#-*- coding: utf-8 -*-
import inspect
import re
def endpoint_from_func(func):
assert func is not None, 'expected func if endpoint is not provided.'
return func.__name__
class Endpoint(object):
def __init__(self):
self.rules = []
self.functions = {}
def __call__(self, *args):
return self.dispatch(*args)
@property
def routes(self):
routes = []
routes.append(' %-30s| %-20s| %-16s' % ('Rule', 'Endpoint Function', 'Arguments'))
for regex, endpoint in self.rules:
args = tuple(inspect.getargspec(self.functions[endpoint]).args)
route = ' %-30s| %-20s| %-16s' % (regex.pattern, endpoint, args)
route = u' {:30s}| {:20s}| {:16s}'.format(regex.pattern, endpoint, args)
routes.append(route)
return '\n'.join(routes)
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_rule(rule, endpoint, f, **options)
return f
return decorator
def add_rule(self, rule, endpoint=None, func=None, **options):
"""
Basically this example:
@app.route('f')
def foo():
pass
Is equivalent to the following:
def foo():
pass
app.add_rule('f', 'foo', foo)
"""
if endpoint is None:
endpoint = endpoint_from_func(func)
options['endpoint'] = endpoint
if func is not None:
old_func = self.functions.get(endpoint)
if old_func is not None and old_func != func:
raise AssertionError('function mapping is overwriting an '
'existing endpoint function: %s', endpoint)
self.functions[endpoint] = func
if not options.has_key('re'):
rule = re.compile('^' + re.escape(rule) + '$')
else:
rule = re.compile(rule)
rule = (rule, endpoint)
self.rules.append(rule)
def dispatch(self, rule, *args):
matches = (
(regex.match(rule), ep) for regex, ep in self.rules
)
# print matches
matches = (
(match.groups(), ep) for match, ep in matches if match is not None
)
for args, endpoint in matches:
return self.functions[endpoint](*args)
return None
#-*- coding: utf-8 -*-
from endpoint import Endpoint
ep = Endpoint()
@ep.route(u'^안녕', re=True)
def hello():
return u'안녕'
@ep.route(u'ㅎㅇ')
@ep.route(u'안뇽')
def hello_multiple_route():
return u'안녕!'
@ep.route(u'가나(다|라)(마)?', re=True)
def test2(dara, ma):
return '%s %s' % (dara, ma)
if __name__ == '__main__':
# Call hello function
print ep(u'안녕')
# Call hello_multiple_route function
print ep(u'ㅎㅇ')
# Call test2 function with one(dara) parameter
print ep(u'가나다')
# Call test2 function with two(dara, ma) parameter
print ep(u'가나라마')
print ep.routes
@ssut
Copy link
Author

ssut commented May 7, 2014

Benchmark Result

Processor: Intel Core i7-4770 CPU @ 3.40GHz

Benchmark count: 100,000

Windows 7 + Cygwin x64 + Python 2.7.5

BenchResult(str=u'\uc548\ub155', time=0.2960171699523926)
BenchResult(str=u'\u314e\u3147', time=0.22201180458068848)
BenchResult(str=u'\uac00\ub098\ub2e4', time=0.3260190486907959)
BenchResult(str=u'\uac00\ub098\ub77c\ub9c8', time=0.3150179386138916)

Windows 7 + Python 2.7.6

BenchResult(str=u'\uc548\ub155', time=0.2330000400543213)
BenchResult(str=u'\u314e\u3147', time=0.18600010871887207)
BenchResult(str=u'\uac00\ub098\ub2e4', time=0.37599992752075195)
BenchResult(str=u'\uac00\ub098\ub77c\ub9c8', time=0.3560001850128174)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment