jsrouting.py (7239B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\werkzeug\contrib\jsrouting.py 2 try: 3 from simplejson import dumps 4 except ImportError: 5 6 def dumps(*args): 7 raise RuntimeError('simplejson required for jsrouting') 8 9 10 from inspect import getmro 11 from werkzeug.templates import Template 12 from werkzeug.routing import NumberConverter 13 _javascript_routing_template = Template(u"<% if name_parts %><% for idx in xrange(0, len(name_parts) - 1) %>if (typeof ${'.'.join(name_parts[:idx + 1])} === 'undefined') ${'.'.join(name_parts[:idx + 1])} = {};\n<% endfor %>${'.'.join(name_parts)} = <% endif %>(function (server_name, script_name, subdomain, url_scheme) {\n var converters = ${', '.join(converters)};\n var rules = $rules;\n function in_array(array, value) {\n if (array.indexOf != undefined) {\n return array.indexOf(value) != -1;\n }\n for (var i = 0; i < array.length; i++) {\n if (array[i] == value) {\n return true;\n }\n }\n return false;\n }\n function array_diff(array1, array2) {\n array1 = array1.slice();\n for (var i = array1.length-1; i >= 0; i--) {\n if (in_array(array2, array1[i])) {\n array1.splice(i, 1);\n }\n }\n return array1;\n }\n function split_obj(obj) {\n var names = [];\n var values = [];\n for (var name in obj) {\n if (typeof(obj[name]) != 'function') {\n names.push(name);\n values.push(obj[name]);\n }\n }\n return {names: names, values: values, original: obj};\n }\n function suitable(rule, args) {\n var default_args = split_obj(rule.defaults || {});\n var diff_arg_names = array_diff(rule.arguments, default_args.names);\n\n for (var i = 0; i < diff_arg_names.length; i++) {\n if (!in_array(args.names, diff_arg_names[i])) {\n return false;\n }\n }\n\n if (array_diff(rule.arguments, args.names).length == 0) {\n if (rule.defaults == null) {\n return true;\n }\n for (var i = 0; i < default_args.names.length; i++) {\n var key = default_args.names[i];\n var value = default_args.values[i];\n if (value != args.original[key]) {\n return false;\n }\n }\n }\n\n return true;\n }\n function build(rule, args) {\n var tmp = [];\n var processed = rule.arguments.slice();\n for (var i = 0; i < rule.trace.length; i++) {\n var part = rule.trace[i];\n if (part.is_dynamic) {\n var converter = converters[rule.converters[part.data]];\n var data = converter(args.original[part.data]);\n if (data == null) {\n return null;\n }\n tmp.push(data);\n processed.push(part.name);\n } else {\n tmp.push(part.data);\n }\n }\n tmp = tmp.join('');\n var pipe = tmp.indexOf('|');\n var subdomain = tmp.substring(0, pipe);\n var url = tmp.substring(pipe+1);\n\n var unprocessed = array_diff(args.names, processed);\n var first_query_var = true;\n for (var i = 0; i < unprocessed.length; i++) {\n if (first_query_var) {\n url += '?';\n } else {\n url += '&';\n }\n first_query_var = false;\n url += encodeURIComponent(unprocessed[i]);\n url += '=';\n url += encodeURIComponent(args.original[unprocessed[i]]);\n }\n return {subdomain: subdomain, path: url};\n }\n function lstrip(s, c) {\n while (s && s.substring(0, 1) == c) {\n s = s.substring(1);\n }\n return s;\n }\n function rstrip(s, c) {\n while (s && s.substring(s.length-1, s.length) == c) {\n s = s.substring(0, s.length-1);\n }\n return s;\n }\n return function(endpoint, args, force_external) {\n args = split_obj(args);\n var rv = null;\n for (var i = 0; i < rules.length; i++) {\n var rule = rules[i];\n if (rule.endpoint != endpoint) continue;\n if (suitable(rule, args)) {\n rv = build(rule, args);\n if (rv != null) {\n break;\n }\n }\n }\n if (rv == null) {\n return null;\n }\n if (!force_external && rv.subdomain == subdomain) {\n return rstrip(script_name, '/') + '/' + lstrip(rv.path, '/');\n } else {\n return url_scheme + '://'\n + (rv.subdomain ? rv.subdomain + '.' : '')\n + server_name + rstrip(script_name, '/')\n + '/' + lstrip(rv.path, '/');\n }\n };\n})") 14 15 def generate_map(map, name = 'url_map'): 16 map.update() 17 rules = [] 18 converters = [] 19 for rule in map.iter_rules(): 20 trace = [ {'is_dynamic': is_dynamic, 21 'data': data} for is_dynamic, data in rule._trace ] 22 rule_converters = {} 23 for key, converter in rule._converters.iteritems(): 24 js_func = js_to_url_function(converter) 25 try: 26 index = converters.index(js_func) 27 except ValueError: 28 converters.append(js_func) 29 index = len(converters) - 1 30 31 rule_converters[key] = index 32 33 rules.append({u'endpoint': rule.endpoint, 34 u'arguments': list(rule.arguments), 35 u'converters': rule_converters, 36 u'trace': trace, 37 u'defaults': rule.defaults}) 38 39 return _javascript_routing_template.render({'name_parts': name and name.split('.') or [], 40 'rules': dumps(rules), 41 'converters': converters}) 42 43 44 def generate_adapter(adapter, name = 'url_for', map_name = 'url_map'): 45 values = {u'server_name': dumps(adapter.server_name), 46 u'script_name': dumps(adapter.script_name), 47 u'subdomain': dumps(adapter.subdomain), 48 u'url_scheme': dumps(adapter.url_scheme), 49 u'name': name, 50 u'map_name': map_name} 51 return u'var %(name)s = %(map_name)s(\n %(server_name)s,\n %(script_name)s,\n %(subdomain)s,\n %(url_scheme)s\n);' % values 52 53 54 def js_to_url_function(converter): 55 if hasattr(converter, 'js_to_url_function'): 56 data = converter.js_to_url_function() 57 else: 58 for cls in getmro(type(converter)): 59 if cls in js_to_url_functions: 60 data = js_to_url_functions[cls](converter) 61 break 62 else: 63 return 'encodeURIComponent' 64 65 return '(function(value) { %s })' % data 66 67 68 def NumberConverter_js_to_url(conv): 69 if conv.fixed_digits: 70 return u"var result = value.toString();\nwhile (result.length < %s)\n result = '0' + result;\nreturn result;" % conv.fixed_digits 71 return u'return value.toString();' 72 73 74 js_to_url_functions = {NumberConverter: NumberConverter_js_to_url}