From e79f176481ba71e6b20ab61f4c3d5f8e6016bce1 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 2 Dec 2013 19:13:37 +0100 Subject: [PATCH 001/160] remove generator which is only supported in a few browsers --- pythonium/lib/generator.py | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 pythonium/lib/generator.py diff --git a/pythonium/lib/generator.py b/pythonium/lib/generator.py deleted file mode 100644 index dc9a2b0..0000000 --- a/pythonium/lib/generator.py +++ /dev/null @@ -1,13 +0,0 @@ -class Generator: - - def __init__(self, generator): - self.generator = generator - - def next(self): - try: - return self.generator.next() - except: - if {}.toString.call(__exception__) == '[object StopIteration]': - raise StopIteration - else: - raise Exception(__exception__) From 943d553c08d2c843f25cd334282b99b864c81580 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 2 Dec 2013 19:26:33 +0100 Subject: [PATCH 002/160] 0.4.5 bump --- pythonium/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonium/main.py b/pythonium/main.py index ec295f0..e4c8554 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -23,7 +23,7 @@ from .pythonium import pythonium_generate_js -__version__ = '0.4.4' +__version__ = '0.4.5' def main(): From 2b057ce378ee734a3f3dc701f970fab05f908a0d Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 3 Dec 2013 00:41:58 +0100 Subject: [PATCH 003/160] UPDATE - removed filter which was not compatible with most browsers - added range - added print and repr for builtins - added map - improved argument unpacking --- pythonium/lib/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pythonium/lib/__init__.py diff --git a/pythonium/lib/__init__.py b/pythonium/lib/__init__.py new file mode 100644 index 0000000..e69de29 From c99bd89314c4e63e16b7c27cc8a83e3ad2e78c35 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 3 Dec 2013 01:09:04 +0100 Subject: [PATCH 004/160] missing files from previous commit --- pythonium/lib/builtins.py | 41 ++++++++++++++++------ pythonium/lib/dict.py | 23 +++++++++++-- pythonium/lib/float.py | 3 ++ pythonium/lib/int.py | 3 ++ pythonium/lib/list.py | 4 +++ pythonium/lib/runtime.py | 17 +++++++-- pythonium/lib/str.py | 15 ++++++++ pythonium/main.py | 8 ++--- pythonium/pythonium.py | 72 ++++++++++++++++++++++++++++----------- 9 files changed, 146 insertions(+), 40 deletions(-) diff --git a/pythonium/lib/builtins.py b/pythonium/lib/builtins.py index c4092f8..2c107be 100644 --- a/pythonium/lib/builtins.py +++ b/pythonium/lib/builtins.py @@ -1,12 +1,31 @@ -def filter(func, objects): - if func: - def generator(): - for obj in objects: - if func(obj): - yield obj +def range(a, b=None): + if b: + index = a + end = b else: - def generator(): - for obj in objects: - if obj: - yield obj - return Generator(generator) + index = 0 + end = a + out = list() + while index < end: + out.append(index) + index += 1 + return out + + +def repr(obj): + return obj.__repr__() + + +def print(*args): + out = list() + for arg in args: + r = repr(arg) # returns a str object + out.append(r.jsobject) + console.log.apply(console, out.jsobject) + + +def map(func, objects): + out = list() + for obj in objects: + out.append(func(obj)) + return out diff --git a/pythonium/lib/dict.py b/pythonium/lib/dict.py index e1fb54a..d448e2b 100644 --- a/pythonium/lib/dict.py +++ b/pythonium/lib/dict.py @@ -1,11 +1,22 @@ class dict: + # only support str, int, float as keys def __init__(self, jsobject): self.jsobject = jsobject + def __repr__(self): + out = [] + for key in self.keys(): + key_repr = repr(key) + value_repr = repr(self.get(key)) + out.append(key_repr + ': ' + value_repr) + return "{" + ", ".join(out) + "}" + def get(self, key, d=None): - attr = self.jsobject[key] - if attr: + jsobject = self.jsobject + key = key.jsobject + attr = JS('jsobject[key]') + if None is not attr: return attr else: return d @@ -14,4 +25,10 @@ def __setitem__(self, key, value): self.jsobject[key] = value def keys(self): - return list(Object.keys(self.jsobject)) + return map(str, list(Object.keys(self.jsobject))) + + def items(self): + out = list() + for key in self.keys(): + out.append([key, self.get(key)]) + return out diff --git a/pythonium/lib/float.py b/pythonium/lib/float.py index cdbbbb4..eb7d298 100644 --- a/pythonium/lib/float.py +++ b/pythonium/lib/float.py @@ -2,6 +2,9 @@ class float: def __init__(self, jsobject): self.jsobject = jsobject + + def __repr__(self): + return self def __div__(self, other): a = self.jsobject diff --git a/pythonium/lib/int.py b/pythonium/lib/int.py index 9e2f4ab..2b09bd9 100644 --- a/pythonium/lib/int.py +++ b/pythonium/lib/int.py @@ -3,6 +3,9 @@ class int: def __init__(self, jsobject): self.jsobject = jsobject + def __repr__(self): + return self + def __add__(self, other): a = self.jsobject b = other.jsobject diff --git a/pythonium/lib/list.py b/pythonium/lib/list.py index 150b45e..f2428d2 100644 --- a/pythonium/lib/list.py +++ b/pythonium/lib/list.py @@ -36,6 +36,10 @@ def __init__(self, jsobject=None): else: self.jsobject = JSArray() + def __repr__(self): + s = "[" + ", ".join(self) + "]" + return s + def append(self, item): jsobject = self.jsobject JS('jsobject.push(item)') diff --git a/pythonium/lib/runtime.py b/pythonium/lib/runtime.py index 9ad03c6..32d88aa 100644 --- a/pythonium/lib/runtime.py +++ b/pythonium/lib/runtime.py @@ -6,6 +6,9 @@ __object.__metaclass__ = __type +__ARGUMENTS_PADDING__ = {ARGUMENTS_PADDING:"YES IT IS!"} + + def __isnot__(self, other): return not (self is other) @@ -23,6 +26,18 @@ def issubclass(klass, other): return False +def pythonium_create_dict(keys, values): + out = {} + max = keys.length + index = 0 + while index < max: + key = keys[index].jsobject + value = values[index] + out[key] = value + index += 1 + return pythonium_call(dict, out, None) + + def pythonium_is_true(v): if v is __FALSE or v is False: return False @@ -153,8 +168,6 @@ def pythonium_object_get_attribute(object, attr): if getattr: return getattr(attr) else: - console.log('__get_attribute__', object, attr) - console.trace() raise AttributeError __object.__getattribute__ = pythonium_object_get_attribute diff --git a/pythonium/lib/str.py b/pythonium/lib/str.py index 1fee864..b5e9174 100644 --- a/pythonium/lib/str.py +++ b/pythonium/lib/str.py @@ -3,6 +3,21 @@ class str: def __init__(self, jsobject): self.jsobject = jsobject + def __repr__(self): + return self + + def join(self, objects): + L = len(objects) + if not L: + return "" + out = objects[0] + index = 1 + while index < L: + obj = objects[index] + out = out + self + obj + index += 1 + return out + def __add__(self, other): a = self.jsobject b = other.jsobject diff --git a/pythonium/main.py b/pythonium/main.py index e4c8554..1d18e4a 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -23,7 +23,7 @@ from .pythonium import pythonium_generate_js -__version__ = '0.4.5' +__version__ = '0.4.6' def main(): @@ -33,16 +33,16 @@ def main(): from pythonium import lib path = lib.__path__[0] output = sys.stdout - for name in ['runtime.py', 'builtins.py']: + for name in ['runtime.py']: sys.stderr.write('Processing {}\n'.format(name)) veloce_generate_js(os.path.join(path, name), False, None, output, False) for name in os.listdir(path): if name == '__pycache__': continue - sys.stderr.write('Processing {}\n'.format(name)) - if name in ['runtime.py', 'builtins.py']: + if name in ['runtime.py']: continue else: + sys.stderr.write('Processing {}\n'.format(name)) pythonium_generate_js(os.path.join(path, name), False, None, output, False) output.close() else: diff --git a/pythonium/pythonium.py b/pythonium/pythonium.py index 654bcc5..95d21f4 100644 --- a/pythonium/pythonium.py +++ b/pythonium/pythonium.py @@ -184,20 +184,49 @@ def visit_FunctionDef(self, node): else: self.writer.write('var {} = function({}) {{'.format(name, __args)) self.writer.push() - if not varkwargs: + if not varkwargs and kwargs: varkwargs = '__kwargs' # unpack arguments + self.writer.write('/* BEGIN unpacking arguments */') if varargs or varkwargs != '__kwargs' or kwargs: self.writer.write('var __args = Array.prototype.slice.call(arguments);') - if varkwargs != '__kwargs' or kwargs: + if varkwargs and (varkwargs != '__kwargs' or kwargs): + self.writer.write('if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) {') + self.writer.push() self.writer.write('var {} = __args[__args.length - 1];'.format(varkwargs)) - for keyword in kwargs.keys(): + self.writer.write('var varkwargs_start = __args.length - 2;') + self.writer.pull() + self.writer.write('} else {') # no variable keywords was provided so it's empty + self.writer.push() + self.writer.write('var {} = {{}};'.format(varkwargs)) + self.writer.write('var varkwargs_start = undefined;') + self.writer.pull() + self.writer.write('}') + num_args = len(args) + for index, keyword in enumerate(kwargs.keys()): + position = num_args + index - 1 + self.writer.write('if (varkwargs_start !== undefined && {} > varkwargs_start) {{'.format(position)) + self.writer.push() + + self.writer.write('{} = {}.{} || {};'.format(keyword, varkwargs, keyword, kwargs[keyword])) + self.writer.pull() + self.writer.write('} else {') + self.writer.push() self.writer.write('{} = {} || {}.{} || {};'.format(keyword, keyword, varkwargs, keyword, kwargs[keyword])) - self.writer.write('delete {}.{};'.format(varkwargs, keyword)) + self.writer.pull() + self.writer.write('}') + if varkwargs != '__kwargs': + self.writer.write('delete {}.{};'.format(varkwargs, keyword)) if varargs: self.writer.write('var {} = __args.splice({});'.format(varargs, len(args))) - self.writer.write('{}.pop();'.format(varargs)) + if varkwargs and (varkwargs != '__kwargs' or kwargs): + self.writer.write('if (varkwargs_start) {{ {}.splice(varkwargs_start - {}) }}'.format(varargs, len(args))) + self.writer.write('{} = pythonium_call(list, {});'.format(varargs, varargs)) + if varkwargs and varkwargs != '__kwargs': + self.writer.write('{} = pythonium_call(dict, {});'.format(varkwargs, varkwargs)) + self.writer.write('/* END unpacking arguments */') + # check for variable creation use var if not global def retrieve_vars(body, vars=None): local_vars = set() @@ -226,7 +255,7 @@ def retrieve_vars(body, vars=None): if local_vars - global_vars: a = ','.join(local_vars-global_vars) self.writer.write('var {};'.format(a)) - + self.writer.write('/* BEGIN function */') # output function body list(map(self.visit, node.body)) self.writer.pull() @@ -317,10 +346,6 @@ def visit_Call(self, node): return '[{}]'.format(out) elif name == 'JS': return node.args[0].s - elif name == 'print': - args = [self.visit(e) for e in node.args] - s = 'console.log({})'.format(', '.join(args)) - return s else: if node.args: args = [self.visit(e) for e in node.args] @@ -330,18 +355,19 @@ def visit_Call(self, node): if node.keywords and not node.kwargs: keywords = '__kwargs{}__'.format(self.uuid()) _ = ', '.join(map(lambda x: '{}: {}'.format(x[0], x[1]), map(self.visit, node.keywords))) - self.writer.write('var {} = {{{}}}'.format(keywords, _)) + self.writer.write('var {} = {{{}}};'.format(keywords, _)) + args.append('__ARGUMENTS_PADDING__') args.append(keywords) elif node.kwargs and not node.keywords: + args.append('__ARGUMENTS_PADDING__') args.append(node.kwargs.id) elif node.kwargs and node.keywords: for key, value in map(self.visit, node.keywords): - self.writer.write('{}.{} = {}'.format(node.kwargs.id, key, value)) + self.writer.write('{}.{} = {};'.format(node.kwargs.id, key, value)) + args.append('__ARGUMENTS_PADDING__') args.append(node.kwargs.id) - if args: - return 'pythonium_call({}, {})'.format(name, ', '.join(args)) - else: - return 'pythonium_call({})'.format(name) + args.insert(0, name) + return 'pythonium_call({})'.format(', '.join(args)) def visit_ListComp(self, node): # 'elt', 'generators' @@ -574,13 +600,19 @@ def visit_If(self, node): self.writer.write('}') def visit_Dict(self, node): - a = [] + keys = [] + values = [] for i in range(len(node.keys)): k = self.visit(node.keys[i]) + keys.append(k) v = self.visit(node.values[i]) - a.append('{}:{}'.format(k, v)) - b = ','.join(a) - return '{{{}}}'.format(b) + values.append(v) + keys = "[{}]".format(", ".join(keys)) + values = "[{}]".format(", ".join(values)) + if node.keys: + return "pythonium_create_dict({}, {})".format(keys, values) + else: + return "pythonium_create_dict()" def visit_For(self, node): # support only arrays From 4203e4ce5f543b4a6b4f6737522396a969b64300 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 3 Dec 2013 01:09:23 +0100 Subject: [PATCH 005/160] started a tutorial to create a todo list --- examples/todo-list/README.rst | 75 +++ examples/todo-list/app.py | 1 + examples/todo-list/app.py.js | 1 + examples/todo-list/exec.js | 1121 +++++++++++++++++++++++++++++++ examples/todo-list/index.html | 15 + examples/todo-list/pythonium.js | 1076 +++++++++++++++++++++++++++++ 6 files changed, 2289 insertions(+) create mode 100644 examples/todo-list/README.rst create mode 100644 examples/todo-list/app.py create mode 100644 examples/todo-list/app.py.js create mode 100644 examples/todo-list/exec.js create mode 100644 examples/todo-list/index.html create mode 100644 examples/todo-list/pythonium.js diff --git a/examples/todo-list/README.rst b/examples/todo-list/README.rst new file mode 100644 index 0000000..c6f9909 --- /dev/null +++ b/examples/todo-list/README.rst @@ -0,0 +1,75 @@ +todo list +######### + +This is a small tutorial coming with `Pythonium `_ that will help you get started. + +Getting started +=============== + +First you will need Python 3, refer to your OS documentation to know how to get it. + +The second step is to install Pythonium, similarly refer to your OS documentation to know how to do it. Most likely you will use ``pip``:: + + pip install pythonium + +Or ``easy_install``:: + + easy_install pythonium + +It's assumed you have recent browser and an editor. Create a file named ``index.html`` with the following content:: + + + + + todo list by Pythonium + + + + +

A todo list

+
+ + + + + + +In the same directory download ``jquery.js``:: + + wget https://code.jquery.com/jquery.js + +The second dependency is generated from python sources included in the *Pythonium* package downloaded previously, it can be found under ``path/site-packages/pythonium/lib/``. You don't need to read that code. It's the runtime library needed by scripts generated with Pythonium to run in JavaScript environments like browsers. It's always accessible online at `github `_. + +Anyway, the command to generate ``pythonium.js`` under GNU/Linux is the following:: + + pythonium -g > pythonium.js + +It's assumed the following command was executed in the same directory as the one where you created the ``index.html`` file. + +Now create an empty ``app.py`` file:: + + touch app.py + +The command to compile a Python file to Javascript using the compliant mode, is the following:: + + pythonium app.py -o app.py.js + +Try it. It will create an empty file. + +Add something in the file like a print:: + + echo "print('Héllo')" > app.py + +And use the previous command to generate ``app.py.js``:: + + pythonium app.py -o app.py.js + +**If** you have *nodejs*, you can execute the following command:: + + cat pythonium.js app.py.js | nodejs + +It will print the following:: + + Héllo + +You can also open ``index.html`` it should also print the same message in the developer console. Refer to your browser documentation to know how to get access to it. diff --git a/examples/todo-list/app.py b/examples/todo-list/app.py new file mode 100644 index 0000000..6bd0f78 --- /dev/null +++ b/examples/todo-list/app.py @@ -0,0 +1 @@ +print('Héllo') diff --git a/examples/todo-list/app.py.js b/examples/todo-list/app.py.js new file mode 100644 index 0000000..b5cb373 --- /dev/null +++ b/examples/todo-list/app.py.js @@ -0,0 +1 @@ +pythonium_call(print, pythonium_call(str, "Héllo")); diff --git a/examples/todo-list/exec.js b/examples/todo-list/exec.js new file mode 100644 index 0000000..758c56c --- /dev/null +++ b/examples/todo-list/exec.js @@ -0,0 +1,1121 @@ +__object = {__bases__:[],__name__:"object"}; +__object.__mro__ = [__object]; +__type = {__bases__:[__object],__mro__:[__object],__name__:"type"}; +__object.__metaclass__ = __type; +__ARGUMENTS_PADDING__ = {ARGUMENTS_PADDING:"YES IT IS!"}; +var __isnot__ = function(self, other) { + return !(this === other); +}; +__object.__isnot__ = __isnot__; +var issubclass = function(klass, other) { + if((klass === other)) { + return true; + } + if(!klass.__bases__) { + return false; + } + var iterator_base = klass.__bases__; + for (var base_iterator_index=0; base_iterator_index < iterator_base.length; base_iterator_index++) { + var base = iterator_base[base_iterator_index]; + if(issubclass(base, other)) { + return true; + } + } + return false; +}; +var pythonium_create_dict = function(keys, values) { + var key,out,index,value,max; + out = {}; + max = keys.length; + index = 0; + while((index < max)) { + key = keys[index].jsobject; + value = values[index]; + out[key] = value; + index = index + 1; + } + return pythonium_call(dict, out, undefined); +}; +var pythonium_is_true = function(v) { + if(((v === __FALSE)||(v === false))) { + return false; + } + if(((v === __TRUE)||(v !== undefined&&(v != __NONE)))) { + return true; + } + if(isinstance(v, int)) { + if((pythonium_get_attribute(v, "jsobject") == 0)) { + return false; + } + return true; + } + return false; +}; +var isinstance = function(object, klass) { + if(object.__class__) { + return issubclass(object.__class__, klass); + } + return false; +}; +var pythonium_obj_to_js_exception = function(obj) { + var exception = function() { + this.exception = obj; + }; + return exception; +}; +var pythonium_is_exception = function(obj, exc) { + if((obj === exc)) { + return true; + } + return isinstance(obj, exc); +}; +var pythonium_call = function(object) { + var instance,init,args; + args = Array.prototype.slice.call(arguments, 1); + if(object.__metaclass__) { + instance = {__class__:object}; + init = lookup(instance, "__init__"); + if(init) { + init.apply(instance, args); + } + return instance; + } + else { + return object.apply(object, args); + } +}; +var pythonium_mro = function(bases) { + var not_head,candidate,non_empty,res,empty,index,seqs; + "Calculate the Method Resolution Order of bases using the C3 algorithm.\n\n Suppose you intended creating a class K with the given base classes. This\n function returns the MRO which K would have, *excluding* K itself (since\n it doesn't yet exist), as if you had actually created the class.\n\n Another way of looking at this, if you pass a single class K, this will\n return the linearization of K (the MRO of K, *including* itself).\n "; + var __comp0__ = []; + var __iterator1__ = bases; + for (var __index2__ = 0; __index2__<__iterator1__.length; __index2__++) { + var C = __iterator1__[__index2__]; + __comp0__.push(C.__mro__); + } + seqs = __comp0__; + seqs.push(bases.slice()); + res = []; + while(true) { + non_empty = []; + var iterator_seq = seqs; + for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { + var seq = iterator_seq[seq_iterator_index]; + empty = true; + var iterator_item = seq; + for (var item_iterator_index=0; item_iterator_index < iterator_item.length; item_iterator_index++) { + var item = iterator_item[item_iterator_index]; + if(item) { + empty = false; + break; + } + } + if(!empty) { + non_empty.push(seq); + } + } + if((non_empty.length == 0)) { + return res; + } + var iterator_seq = non_empty; + for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { + var seq = iterator_seq[seq_iterator_index]; + candidate = seq[0]; + var __comp3__ = []; + var __iterator4__ = non_empty; + for (var __index5__ = 0; __index5__<__iterator4__.length; __index5__++) { + var s = __iterator4__[__index5__]; + if(!(candidate in s.splice(1))) { continue; } + __comp3__.push(s); + } + not_head = __comp3__; + if((not_head.length != 0)) { + candidate = undefined; + } + else { + break; + } + } + if(!candidate) { + throw TypeError("Inconsistent hierarchy, no C3 MRO is possible"); + } + res.push(candidate); + var iterator_seq = seqs; + for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { + var seq = iterator_seq[seq_iterator_index]; + index = seq.indexOf(candidate); + if((index >= 0)) { + delete seq[index]; + } + } + } +}; +var pythonium_create_class = function(name, bases, attrs) { + var mro; + attrs.__name__ = name; + attrs.__metaclass__ = __type; + attrs.__bases__ = bases; + mro = pythonium_mro(bases); + mro.splice(0, 0, attrs); + attrs.__mro__ = mro; + return attrs; +}; +var lookup = function(object, attr) { + var object_attr,class_attr; + object_attr = object[attr]; + if((object_attr != undefined)) { + if((object_attr&&({}.toString.call(object_attr) == "[object Function]"))) { + var method_wrapper = function() { + var args; + args = Array.prototype.slice.call(arguments); + args.splice(0, 0, object); + return object_attr.apply(undefined, args); + }; + return method_wrapper; + } + return object_attr; + } + else { + var iterator_base = object.__class__.__mro__; + for (var base_iterator_index=0; base_iterator_index < iterator_base.length; base_iterator_index++) { + var base = iterator_base[base_iterator_index]; + class_attr = base[attr]; + if((class_attr != undefined)) { + if(({}.toString.call(class_attr) == "[object Function]")) { + var method_wrapper = function() { + var args; + args = Array.prototype.slice.call(arguments); + args.splice(0, 0, object); + return class_attr.apply(undefined, args); + }; + return method_wrapper; + } + return class_attr; + } + } + } +}; +var pythonium_object_get_attribute = function(object, attr) { + var getattr,r; + r = lookup(object, attr); + if((r != undefined)) { + return r; + } + else { + getattr = lookup(object, "__getattr__"); + if(getattr) { + return getattr(attr); + } + else { + throw AttributeError; + } + } +}; +__object.__getattribute__ = pythonium_object_get_attribute; +var pythonium_get_attribute = function(object, attr) { + var getattribute; + if(object.__class__) { + getattribute = lookup(object, "__getattribute__"); + return getattribute(attr); + } + attr = object[attr]; + if(attr) { + if(({}.toString.call(attr) == "[object Function]")) { + var method_wrapper = function() { + return attr.apply(object, arguments); + }; + return method_wrapper; + } + else { + return attr; + } + } +}; +var pythonium_set_attribute = function(object, attr, value) { + object[attr] = value; +}; +var range = function(a, b) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 1 > varkwargs_start) { + b = __kwargs.b || __NONE; + } else { + b = b || __kwargs.b || __NONE; + } + /* END unpacking arguments */ + var out,end,index; + /* BEGIN function */ + if (pythonium_is_true(b)) { + index = a; + end = b; + } + else { + index = pythonium_call(int, 0); + end = a; + } + out = pythonium_call(list); + while(pythonium_is_true((pythonium_get_attribute(index, "__lt__")(end)))) { + pythonium_call(pythonium_get_attribute(out, "append"), index); + index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); + } + return out; +}; +var repr = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__repr__")); +}; +var print = function() { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + var args = __args.splice(0); + args = pythonium_call(list, args); + /* END unpacking arguments */ + var out,r; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(args), "__next__"); + while(true) { + var arg = pythonium_call(__next__); + r = pythonium_call(repr, arg); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_get_attribute(r, "jsobject")); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(console, "log"), "apply"), console, pythonium_get_attribute(out, "jsobject")); +}; +var map = function(func, objects) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(objects), "__next__"); + while(true) { + var obj = pythonium_call(__next__); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_call(func, obj)); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return out; +}; +/* class definition Generator */ +var __init__ = function(self, generator) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "generator", generator); +}; +var next = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + try { + return pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "generator"), "next")); + } + catch (__exception__) { + if (pythonium_is_true((pythonium_get_attribute(pythonium_call(pythonium_get_attribute(pythonium_get_attribute(pythonium_create_dict(), "toString"), "call"), __exception__), "__eq__")(pythonium_call(str, "[object StopIteration]"))))) { + throw StopIteration; + } + else { + throw pythonium_call(Exception, __exception__); + } + } +}; +var Generator = pythonium_create_class("Generator", [__object], { + __init__: __init__, + next: next, +}); +/* class definition _True */ +var __init__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", true); +}; +var __and__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __TRUE; +}; +var __is__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __FALSE; +}; +var _True = pythonium_create_class("_True", [__object], { + __init__: __init__, + __and__: __and__, + __or__: __or__, + __is__: __is__, + __neg__: __neg__, +}); +/* class definition _False */ +var __init__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", false); +}; +var __and__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __FALSE; +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === True)) { + return __TRUE; + } + return __FALSE; +}; +var __is__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __TRUE; +}; +var _False = pythonium_create_class("_False", [__object], { + __init__: __init__, + __and__: __and__, + __or__: __or__, + __is__: __is__, + __neg__: __neg__, +}); +__TRUE = pythonium_call(_True); +__FALSE = pythonium_call(_False); +/* class definition StopIteration */ +/* pass */ +var StopIteration = pythonium_create_class("StopIteration", [__object], { +}); +var iter = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__iter__")); +}; +var next = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__next__")); +}; +var len = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__len__")); +}; +/* class definition ListIterator */ +var __init__ = function(self, obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "list", obj); + pythonium_set_attribute(self, "index", pythonium_call(int, 0)); + pythonium_set_attribute(self, "length", pythonium_call(len, obj)); +}; +var __next__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__eq__")(pythonium_get_attribute(self, "length"))))) { + throw StopIteration; + } + pythonium_set_attribute(self, "index", (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__add__"), pythonium_call(int, 1)))); + return pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "list"), '__getitem__'), (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__sub__"), pythonium_call(int, 1)))); +}; +var ListIterator = pythonium_create_class("ListIterator", [__object], { + __init__: __init__, + __next__: __next__, +}); +/* class definition list */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 1 > varkwargs_start) { + jsobject = __kwargs.jsobject || __NONE; + } else { + jsobject = jsobject || __kwargs.jsobject || __NONE; + } + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(jsobject)) { + pythonium_set_attribute(self, "jsobject", jsobject); + } + else { + pythonium_set_attribute(self, "jsobject", []); + } +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var s; + /* BEGIN function */ + s = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "["), "__add__"), pythonium_call(pythonium_get_attribute(pythonium_call(str, ", "), "join"), self))), "__add__"), pythonium_call(str, "]"))); + return s; +}; +var append = function(self, item) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + jsobject.push(item); +}; +var insert = function(self, index, item) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "splice"), index, pythonium_call(int, 0), item); +}; +var __setitem__ = function(self, index, value) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(index, "jsobject"); + jsobject[index] = value; +}; +var __getitem__ = function(self, s) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var index,jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(s, "jsobject"); + return jsobject[index]; +}; +var __len__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject,length; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + length = jsobject.length; + return pythonium_call(int, length); +}; +var __iter__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(ListIterator, self); +}; +var list = pythonium_create_class("list", [__object], { + __init__: __init__, + __repr__: __repr__, + append: append, + insert: insert, + __setitem__: __setitem__, + __getitem__: __getitem__, + __len__: __len__, + __iter__: __iter__, +}); +/* class definition float */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return self; +}; +var __div__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(float, a / b); +}; +var __sub__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(float, a - b); +}; +var __eq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { + return __TRUE; + } + return __FALSE; +}; +var float = pythonium_create_class("float", [__object], { + __init__: __init__, + __repr__: __repr__, + __div__: __div__, + __sub__: __sub__, + __eq__: __eq__, +}); +/* class definition _None */ +var __and__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + return __TRUE; + } + return __FALSE; +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + return __TRUE; + } + return __FALSE; +}; +var __is__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __TRUE; +}; +var _None = pythonium_create_class("_None", [__object], { + __and__: __and__, + __or__: __or__, + __is__: __is__, + __neg__: __neg__, +}); +__NONE = pythonium_call(_None); +/* class definition iterator */ +var __init__ = function(self, list) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + /* pass */ +}; +var iterator = pythonium_create_class("iterator", [__object], { + __init__: __init__, +}); +/* class definition slice */ +var __init__ = function(self, start, step, end) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "start", start); + pythonium_set_attribute(self, "step", step); + pythonium_set_attribute(self, "end", end); +}; +var slice = pythonium_create_class("slice", [__object], { + __init__: __init__, +}); +/* class definition Exception */ +var __init__ = function(self, message) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "message", message); +}; +var Exception = pythonium_create_class("Exception", [__object], { + __init__: __init__, +}); +/* class definition TypeError */ +/* pass */ +var TypeError = pythonium_create_class("TypeError", [Exception], { +}); +/* class definition AttributeError */ +/* pass */ +var AttributeError = pythonium_create_class("AttributeError", [Exception], { +}); +/* class definition int */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return self; +}; +var __add__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(int, a + b); +}; +var __sub__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(int, a - b); +}; +var __lt__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a < b)) { + return __TRUE; + } + return __FALSE; +}; +var __lte__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a <= b)) { + return __TRUE; + } + return __FALSE; +}; +var __mul__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var c,b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a * b; + return pythonium_call(int, c); +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var c,b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a || b; + return pythonium_call(int, c); +}; +var __eq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + return pythonium_call(int, -jsobject); +}; +var __div__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(int, a / b); +}; +var int = pythonium_create_class("int", [__object], { + __init__: __init__, + __repr__: __repr__, + __add__: __add__, + __sub__: __sub__, + __lt__: __lt__, + __lte__: __lte__, + __mul__: __mul__, + __or__: __or__, + __eq__: __eq__, + __neg__: __neg__, + __div__: __div__, +}); +/* class definition dict */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out,value_repr,key_repr; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(pythonium_call(pythonium_get_attribute(self, "keys"))), "__next__"); + while(true) { + var key = pythonium_call(__next__); + key_repr = pythonium_call(repr, key); + value_repr = pythonium_call(repr, pythonium_call(pythonium_get_attribute(self, "get"), key)); + pythonium_call(pythonium_get_attribute(out, "append"), (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(key_repr, "__add__"), pythonium_call(str, ": "))), "__add__"), value_repr))); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "{"), "__add__"), pythonium_call(pythonium_get_attribute(pythonium_call(str, ", "), "join"), out))), "__add__"), pythonium_call(str, "}"))); +}; +var get = function(self, key, d) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 2 > varkwargs_start) { + d = __kwargs.d || __NONE; + } else { + d = d || __kwargs.d || __NONE; + } + /* END unpacking arguments */ + var jsobject,attr; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + key = pythonium_get_attribute(key, "jsobject"); + attr = jsobject[key]; + if (pythonium_is_true((pythonium_get_attribute(__NONE, "__isnot__")(attr)))) { + return attr; + } + else { + return d; + } +}; +var __setitem__ = function(self, key, value) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "__setitem__"), key, value); +}; +var keys = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(map, str, pythonium_call(list, pythonium_call(pythonium_get_attribute(Object, "keys"), pythonium_get_attribute(self, "jsobject")))); +}; +var items = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(pythonium_call(pythonium_get_attribute(self, "keys"))), "__next__"); + while(true) { + var key = pythonium_call(__next__); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_call(list, [key, pythonium_call(pythonium_get_attribute(self, "get"), key)])); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return out; +}; +var dict = pythonium_create_class("dict", [__object], { + __init__: __init__, + __repr__: __repr__, + get: get, + __setitem__: __setitem__, + keys: keys, + items: items, +}); +/* class definition str */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return self; +}; +var join = function(self, objects) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out,obj,index,L; + /* BEGIN function */ + L = pythonium_call(len, objects); + if (pythonium_is_true(pythonium_call(pythonium_get_attribute(L, "__neg__")))) { + return pythonium_call(str, ""); + } + out = pythonium_call(pythonium_get_attribute(objects, '__getitem__'), pythonium_call(int, 0)); + index = pythonium_call(int, 1); + while(pythonium_is_true((pythonium_get_attribute(index, "__lt__")(L)))) { + obj = pythonium_call(pythonium_get_attribute(objects, '__getitem__'), index); + out = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(out, "__add__"), self)), "__add__"), obj)); + index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); + } + return out; +}; +var __add__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(str, a + b); +}; +var __lte__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a <= b)) { + return __TRUE; + } + return __FALSE; +}; +var __gte__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a >= b)) { + return __TRUE; + } + return __FALSE; +}; +var __gt__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a > b)) { + return __TRUE; + } + return __FALSE; +}; +var __eq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { + return __TRUE; + } + return __FALSE; +}; +var __getitem__ = function(self, index) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var c,jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(index, "jsobject"); + c = jsobject[index]; + return pythonium_call(str, c); +}; +var __neq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(pythonium_call(pythonium_get_attribute(self, "__eq__"), other), "__neg__")); +}; +var str = pythonium_create_class("str", [__object], { + __init__: __init__, + __repr__: __repr__, + join: join, + __add__: __add__, + __lte__: __lte__, + __gte__: __gte__, + __gt__: __gt__, + __eq__: __eq__, + __getitem__: __getitem__, + __neq__: __neq__, +}); +var print = function() { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + var args = __args.splice(0); + args = pythonium_call(list, args); + /* END unpacking arguments */ + var out,r; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(args), "__next__"); + while(true) { + var arg = pythonium_call(__next__); + r = pythonium_call(repr, arg); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_get_attribute(r, "jsobject")); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(console, "log"), "apply"), console, pythonium_get_attribute(out, "jsobject")); +}; +var func = function(a, b, c, d, e) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 4 > varkwargs_start) { + e = __kwargs.e || pythonium_call(int, 5); + } else { + e = e || __kwargs.e || pythonium_call(int, 5); + } + if (varkwargs_start !== undefined && 5 > varkwargs_start) { + d = __kwargs.d || pythonium_call(int, 4); + } else { + d = d || __kwargs.d || pythonium_call(int, 4); + } + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_call(print, pythonium_call(str, "results")); + pythonium_call(print, a, b, c, d, e); +}; +pythonium_call(func, pythonium_call(int, 1), pythonium_call(int, 2), pythonium_call(int, 3), pythonium_call(int, 44), pythonium_call(int, 55)); diff --git a/examples/todo-list/index.html b/examples/todo-list/index.html new file mode 100644 index 0000000..071be68 --- /dev/null +++ b/examples/todo-list/index.html @@ -0,0 +1,15 @@ + + + + todo list by Pythonium + + + + +

A todo list

+
+ + + + + diff --git a/examples/todo-list/pythonium.js b/examples/todo-list/pythonium.js new file mode 100644 index 0000000..08aef92 --- /dev/null +++ b/examples/todo-list/pythonium.js @@ -0,0 +1,1076 @@ +__object = {__bases__:[],__name__:"object"}; +__object.__mro__ = [__object]; +__type = {__bases__:[__object],__mro__:[__object],__name__:"type"}; +__object.__metaclass__ = __type; +__ARGUMENTS_PADDING__ = {ARGUMENTS_PADDING:"YES IT IS!"}; +var __isnot__ = function(self, other) { + return !(this === other); +}; +__object.__isnot__ = __isnot__; +var issubclass = function(klass, other) { + if((klass === other)) { + return true; + } + if(!klass.__bases__) { + return false; + } + var iterator_base = klass.__bases__; + for (var base_iterator_index=0; base_iterator_index < iterator_base.length; base_iterator_index++) { + var base = iterator_base[base_iterator_index]; + if(issubclass(base, other)) { + return true; + } + } + return false; +}; +var pythonium_create_dict = function(keys, values) { + var key,out,index,value,max; + out = {}; + max = keys.length; + index = 0; + while((index < max)) { + key = keys[index].jsobject; + value = values[index]; + out[key] = value; + index = index + 1; + } + return pythonium_call(dict, out, undefined); +}; +var pythonium_is_true = function(v) { + if(((v === __FALSE)||(v === false))) { + return false; + } + if(((v === __TRUE)||(v !== undefined&&(v != __NONE)))) { + return true; + } + if(isinstance(v, int)) { + if((pythonium_get_attribute(v, "jsobject") == 0)) { + return false; + } + return true; + } + return false; +}; +var isinstance = function(object, klass) { + if(object.__class__) { + return issubclass(object.__class__, klass); + } + return false; +}; +var pythonium_obj_to_js_exception = function(obj) { + var exception = function() { + this.exception = obj; + }; + return exception; +}; +var pythonium_is_exception = function(obj, exc) { + if((obj === exc)) { + return true; + } + return isinstance(obj, exc); +}; +var pythonium_call = function(object) { + var instance,init,args; + args = Array.prototype.slice.call(arguments, 1); + if(object.__metaclass__) { + instance = {__class__:object}; + init = lookup(instance, "__init__"); + if(init) { + init.apply(instance, args); + } + return instance; + } + else { + return object.apply(object, args); + } +}; +var pythonium_mro = function(bases) { + var not_head,candidate,non_empty,res,empty,index,seqs; + "Calculate the Method Resolution Order of bases using the C3 algorithm.\n\n Suppose you intended creating a class K with the given base classes. This\n function returns the MRO which K would have, *excluding* K itself (since\n it doesn't yet exist), as if you had actually created the class.\n\n Another way of looking at this, if you pass a single class K, this will\n return the linearization of K (the MRO of K, *including* itself).\n "; + var __comp0__ = []; + var __iterator1__ = bases; + for (var __index2__ = 0; __index2__<__iterator1__.length; __index2__++) { + var C = __iterator1__[__index2__]; + __comp0__.push(C.__mro__); + } + seqs = __comp0__; + seqs.push(bases.slice()); + res = []; + while(true) { + non_empty = []; + var iterator_seq = seqs; + for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { + var seq = iterator_seq[seq_iterator_index]; + empty = true; + var iterator_item = seq; + for (var item_iterator_index=0; item_iterator_index < iterator_item.length; item_iterator_index++) { + var item = iterator_item[item_iterator_index]; + if(item) { + empty = false; + break; + } + } + if(!empty) { + non_empty.push(seq); + } + } + if((non_empty.length == 0)) { + return res; + } + var iterator_seq = non_empty; + for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { + var seq = iterator_seq[seq_iterator_index]; + candidate = seq[0]; + var __comp3__ = []; + var __iterator4__ = non_empty; + for (var __index5__ = 0; __index5__<__iterator4__.length; __index5__++) { + var s = __iterator4__[__index5__]; + if(!(candidate in s.splice(1))) { continue; } + __comp3__.push(s); + } + not_head = __comp3__; + if((not_head.length != 0)) { + candidate = undefined; + } + else { + break; + } + } + if(!candidate) { + throw TypeError("Inconsistent hierarchy, no C3 MRO is possible"); + } + res.push(candidate); + var iterator_seq = seqs; + for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { + var seq = iterator_seq[seq_iterator_index]; + index = seq.indexOf(candidate); + if((index >= 0)) { + delete seq[index]; + } + } + } +}; +var pythonium_create_class = function(name, bases, attrs) { + var mro; + attrs.__name__ = name; + attrs.__metaclass__ = __type; + attrs.__bases__ = bases; + mro = pythonium_mro(bases); + mro.splice(0, 0, attrs); + attrs.__mro__ = mro; + return attrs; +}; +var lookup = function(object, attr) { + var object_attr,class_attr; + object_attr = object[attr]; + if((object_attr != undefined)) { + if((object_attr&&({}.toString.call(object_attr) == "[object Function]"))) { + var method_wrapper = function() { + var args; + args = Array.prototype.slice.call(arguments); + args.splice(0, 0, object); + return object_attr.apply(undefined, args); + }; + return method_wrapper; + } + return object_attr; + } + else { + var iterator_base = object.__class__.__mro__; + for (var base_iterator_index=0; base_iterator_index < iterator_base.length; base_iterator_index++) { + var base = iterator_base[base_iterator_index]; + class_attr = base[attr]; + if((class_attr != undefined)) { + if(({}.toString.call(class_attr) == "[object Function]")) { + var method_wrapper = function() { + var args; + args = Array.prototype.slice.call(arguments); + args.splice(0, 0, object); + return class_attr.apply(undefined, args); + }; + return method_wrapper; + } + return class_attr; + } + } + } +}; +var pythonium_object_get_attribute = function(object, attr) { + var getattr,r; + r = lookup(object, attr); + if((r != undefined)) { + return r; + } + else { + getattr = lookup(object, "__getattr__"); + if(getattr) { + return getattr(attr); + } + else { + throw AttributeError; + } + } +}; +__object.__getattribute__ = pythonium_object_get_attribute; +var pythonium_get_attribute = function(object, attr) { + var getattribute; + if(object.__class__) { + getattribute = lookup(object, "__getattribute__"); + return getattribute(attr); + } + attr = object[attr]; + if(attr) { + if(({}.toString.call(attr) == "[object Function]")) { + var method_wrapper = function() { + return attr.apply(object, arguments); + }; + return method_wrapper; + } + else { + return attr; + } + } +}; +var pythonium_set_attribute = function(object, attr, value) { + object[attr] = value; +}; +var range = function(a, b) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 1 > varkwargs_start) { + b = __kwargs.b || __NONE; + } else { + b = b || __kwargs.b || __NONE; + } + /* END unpacking arguments */ + var out,end,index; + /* BEGIN function */ + if (pythonium_is_true(b)) { + index = a; + end = b; + } + else { + index = pythonium_call(int, 0); + end = a; + } + out = pythonium_call(list); + while(pythonium_is_true((pythonium_get_attribute(index, "__lt__")(end)))) { + pythonium_call(pythonium_get_attribute(out, "append"), index); + index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); + } + return out; +}; +var repr = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__repr__")); +}; +var print = function() { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + var args = __args.splice(0); + args = pythonium_call(list, args); + /* END unpacking arguments */ + var out,r; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(args), "__next__"); + while(true) { + var arg = pythonium_call(__next__); + r = pythonium_call(repr, arg); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_get_attribute(r, "jsobject")); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(console, "log"), "apply"), console, pythonium_get_attribute(out, "jsobject")); +}; +var map = function(func, objects) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(objects), "__next__"); + while(true) { + var obj = pythonium_call(__next__); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_call(func, obj)); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return out; +}; +/* class definition Generator */ +var __init__ = function(self, generator) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "generator", generator); +}; +var next = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + try { + return pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "generator"), "next")); + } + catch (__exception__) { + if (pythonium_is_true((pythonium_get_attribute(pythonium_call(pythonium_get_attribute(pythonium_get_attribute(pythonium_create_dict(), "toString"), "call"), __exception__), "__eq__")(pythonium_call(str, "[object StopIteration]"))))) { + throw StopIteration; + } + else { + throw pythonium_call(Exception, __exception__); + } + } +}; +var Generator = pythonium_create_class("Generator", [__object], { + __init__: __init__, + next: next, +}); +/* class definition _True */ +var __init__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", true); +}; +var __and__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __TRUE; +}; +var __is__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __FALSE; +}; +var _True = pythonium_create_class("_True", [__object], { + __init__: __init__, + __and__: __and__, + __or__: __or__, + __is__: __is__, + __neg__: __neg__, +}); +/* class definition _False */ +var __init__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", false); +}; +var __and__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __FALSE; +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === True)) { + return __TRUE; + } + return __FALSE; +}; +var __is__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __TRUE; +}; +var _False = pythonium_create_class("_False", [__object], { + __init__: __init__, + __and__: __and__, + __or__: __or__, + __is__: __is__, + __neg__: __neg__, +}); +__TRUE = pythonium_call(_True); +__FALSE = pythonium_call(_False); +/* class definition StopIteration */ +/* pass */ +var StopIteration = pythonium_create_class("StopIteration", [__object], { +}); +var iter = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__iter__")); +}; +var next = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__next__")); +}; +var len = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__len__")); +}; +/* class definition ListIterator */ +var __init__ = function(self, obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "list", obj); + pythonium_set_attribute(self, "index", pythonium_call(int, 0)); + pythonium_set_attribute(self, "length", pythonium_call(len, obj)); +}; +var __next__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__eq__")(pythonium_get_attribute(self, "length"))))) { + throw StopIteration; + } + pythonium_set_attribute(self, "index", (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__add__"), pythonium_call(int, 1)))); + return pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "list"), '__getitem__'), (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__sub__"), pythonium_call(int, 1)))); +}; +var ListIterator = pythonium_create_class("ListIterator", [__object], { + __init__: __init__, + __next__: __next__, +}); +/* class definition list */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 1 > varkwargs_start) { + jsobject = __kwargs.jsobject || __NONE; + } else { + jsobject = jsobject || __kwargs.jsobject || __NONE; + } + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(jsobject)) { + pythonium_set_attribute(self, "jsobject", jsobject); + } + else { + pythonium_set_attribute(self, "jsobject", []); + } +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var s; + /* BEGIN function */ + s = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "["), "__add__"), pythonium_call(pythonium_get_attribute(pythonium_call(str, ", "), "join"), self))), "__add__"), pythonium_call(str, "]"))); + return s; +}; +var append = function(self, item) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + jsobject.push(item); +}; +var insert = function(self, index, item) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "splice"), index, pythonium_call(int, 0), item); +}; +var __setitem__ = function(self, index, value) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(index, "jsobject"); + jsobject[index] = value; +}; +var __getitem__ = function(self, s) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var index,jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(s, "jsobject"); + return jsobject[index]; +}; +var __len__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject,length; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + length = jsobject.length; + return pythonium_call(int, length); +}; +var __iter__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(ListIterator, self); +}; +var list = pythonium_create_class("list", [__object], { + __init__: __init__, + __repr__: __repr__, + append: append, + insert: insert, + __setitem__: __setitem__, + __getitem__: __getitem__, + __len__: __len__, + __iter__: __iter__, +}); +/* class definition float */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return self; +}; +var __div__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(float, a / b); +}; +var __sub__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(float, a - b); +}; +var __eq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { + return __TRUE; + } + return __FALSE; +}; +var float = pythonium_create_class("float", [__object], { + __init__: __init__, + __repr__: __repr__, + __div__: __div__, + __sub__: __sub__, + __eq__: __eq__, +}); +/* class definition _None */ +var __and__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + return __TRUE; + } + return __FALSE; +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + return __TRUE; + } + return __FALSE; +}; +var __is__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __TRUE; +}; +var _None = pythonium_create_class("_None", [__object], { + __and__: __and__, + __or__: __or__, + __is__: __is__, + __neg__: __neg__, +}); +__NONE = pythonium_call(_None); +/* class definition iterator */ +var __init__ = function(self, list) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + /* pass */ +}; +var iterator = pythonium_create_class("iterator", [__object], { + __init__: __init__, +}); +/* class definition slice */ +var __init__ = function(self, start, step, end) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "start", start); + pythonium_set_attribute(self, "step", step); + pythonium_set_attribute(self, "end", end); +}; +var slice = pythonium_create_class("slice", [__object], { + __init__: __init__, +}); +/* class definition Exception */ +var __init__ = function(self, message) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "message", message); +}; +var Exception = pythonium_create_class("Exception", [__object], { + __init__: __init__, +}); +/* class definition TypeError */ +/* pass */ +var TypeError = pythonium_create_class("TypeError", [Exception], { +}); +/* class definition AttributeError */ +/* pass */ +var AttributeError = pythonium_create_class("AttributeError", [Exception], { +}); +/* class definition int */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return self; +}; +var __add__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(int, a + b); +}; +var __sub__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(int, a - b); +}; +var __lt__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a < b)) { + return __TRUE; + } + return __FALSE; +}; +var __lte__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a <= b)) { + return __TRUE; + } + return __FALSE; +}; +var __mul__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var c,b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a * b; + return pythonium_call(int, c); +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var c,b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a || b; + return pythonium_call(int, c); +}; +var __eq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + return pythonium_call(int, -jsobject); +}; +var __div__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(int, a / b); +}; +var int = pythonium_create_class("int", [__object], { + __init__: __init__, + __repr__: __repr__, + __add__: __add__, + __sub__: __sub__, + __lt__: __lt__, + __lte__: __lte__, + __mul__: __mul__, + __or__: __or__, + __eq__: __eq__, + __neg__: __neg__, + __div__: __div__, +}); +/* class definition dict */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out,value_repr,key_repr; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(pythonium_call(pythonium_get_attribute(self, "keys"))), "__next__"); + while(true) { + var key = pythonium_call(__next__); + key_repr = pythonium_call(repr, key); + value_repr = pythonium_call(repr, pythonium_call(pythonium_get_attribute(self, "get"), key)); + pythonium_call(pythonium_get_attribute(out, "append"), (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(key_repr, "__add__"), pythonium_call(str, ": "))), "__add__"), value_repr))); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "{"), "__add__"), pythonium_call(pythonium_get_attribute(pythonium_call(str, ", "), "join"), out))), "__add__"), pythonium_call(str, "}"))); +}; +var get = function(self, key, d) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 2 > varkwargs_start) { + d = __kwargs.d || __NONE; + } else { + d = d || __kwargs.d || __NONE; + } + /* END unpacking arguments */ + var jsobject,attr; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + key = pythonium_get_attribute(key, "jsobject"); + attr = jsobject[key]; + if (pythonium_is_true((pythonium_get_attribute(__NONE, "__isnot__")(attr)))) { + return attr; + } + else { + return d; + } +}; +var __setitem__ = function(self, key, value) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "__setitem__"), key, value); +}; +var keys = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(map, str, pythonium_call(list, pythonium_call(pythonium_get_attribute(Object, "keys"), pythonium_get_attribute(self, "jsobject")))); +}; +var items = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(pythonium_call(pythonium_get_attribute(self, "keys"))), "__next__"); + while(true) { + var key = pythonium_call(__next__); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_call(list, [key, pythonium_call(pythonium_get_attribute(self, "get"), key)])); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return out; +}; +var dict = pythonium_create_class("dict", [__object], { + __init__: __init__, + __repr__: __repr__, + get: get, + __setitem__: __setitem__, + keys: keys, + items: items, +}); +/* class definition str */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return self; +}; +var join = function(self, objects) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out,obj,index,L; + /* BEGIN function */ + L = pythonium_call(len, objects); + if (pythonium_is_true(pythonium_call(pythonium_get_attribute(L, "__neg__")))) { + return pythonium_call(str, ""); + } + out = pythonium_call(pythonium_get_attribute(objects, '__getitem__'), pythonium_call(int, 0)); + index = pythonium_call(int, 1); + while(pythonium_is_true((pythonium_get_attribute(index, "__lt__")(L)))) { + obj = pythonium_call(pythonium_get_attribute(objects, '__getitem__'), index); + out = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(out, "__add__"), self)), "__add__"), obj)); + index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); + } + return out; +}; +var __add__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(str, a + b); +}; +var __lte__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a <= b)) { + return __TRUE; + } + return __FALSE; +}; +var __gte__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a >= b)) { + return __TRUE; + } + return __FALSE; +}; +var __gt__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a > b)) { + return __TRUE; + } + return __FALSE; +}; +var __eq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { + return __TRUE; + } + return __FALSE; +}; +var __getitem__ = function(self, index) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var c,jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(index, "jsobject"); + c = jsobject[index]; + return pythonium_call(str, c); +}; +var __neq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(pythonium_call(pythonium_get_attribute(self, "__eq__"), other), "__neg__")); +}; +var str = pythonium_create_class("str", [__object], { + __init__: __init__, + __repr__: __repr__, + join: join, + __add__: __add__, + __lte__: __lte__, + __gte__: __gte__, + __gt__: __gt__, + __eq__: __eq__, + __getitem__: __getitem__, + __neq__: __neq__, +}); From 4f4bf616d49d4a44491c2b6e1a0e7597d0816f9a Mon Sep 17 00:00:00 2001 From: mvasilkov Date: Tue, 3 Dec 2013 09:29:14 +0200 Subject: [PATCH 006/160] Fix broken link --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index b38bafd..107a64d 100644 --- a/README.rst +++ b/README.rst @@ -82,7 +82,7 @@ Ahah! Want to help? (30 seconds) ========================== -- `Star this repository `_ +- `Star this repository `_ - `Follow the project on twitter `_ - `Join the mailling list `_ From b1ccd8f62a5adf642bf9ad2c449c9782b51d6132 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 3 Dec 2013 19:38:01 +0100 Subject: [PATCH 007/160] added results of pystone benchmark --- pystone/README.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 pystone/README.rst diff --git a/pystone/README.rst b/pystone/README.rst new file mode 100644 index 0000000..a86be66 --- /dev/null +++ b/pystone/README.rst @@ -0,0 +1,15 @@ +Veloce mode:: + + Pystone(1.1) time for 100000 passes = 0.3130004405975342 + This machine benchmarks at 319488.36816042423 pystones/second + +Compliant mode:: + + Pystone(1.1) time for 100000 passes = 82.98399996757507 + This machine benchmarks at 1205.05157667832 pystones/second + +Reference CPython:: + + Pystone(1.1) time for 100000 passes = 0.73 + This machine benchmarks at 136986 pystones/second + From 9a1409ef7b24ce1fc101aaba310b58b748cfce84 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 3 Dec 2013 19:38:46 +0100 Subject: [PATCH 008/160] added the version with which the tests were run --- pystone/README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pystone/README.rst b/pystone/README.rst index a86be66..b419c55 100644 --- a/pystone/README.rst +++ b/pystone/README.rst @@ -1,3 +1,5 @@ +Tested with 0.4.6 release + Veloce mode:: Pystone(1.1) time for 100000 passes = 0.3130004405975342 From 22a1d434bd363a6a5bb9c7a62f439127c38aba51 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 3 Dec 2013 19:41:23 +0100 Subject: [PATCH 009/160] added AUTHORS --- AUTHORS | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..29d4248 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Amirouche Boubekki (creator and maintainer) +Steven D'Aprano (method resolution order) \ No newline at end of file From b9a98e40edf79f554e7d8af8a2fcd8725cf104bc Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 3 Dec 2013 21:58:37 +0100 Subject: [PATCH 010/160] update the todo-list tutorial and mock the jstype function --- examples/todo-list/README.rst | 112 +++++++++++++++++++++++++++++++++- examples/todo-list/app.py | 1 - examples/todo-list/index.html | 4 +- pythonium/lib/builtins.py | 4 ++ 4 files changed, 116 insertions(+), 5 deletions(-) diff --git a/examples/todo-list/README.rst b/examples/todo-list/README.rst index c6f9909..eb84b41 100644 --- a/examples/todo-list/README.rst +++ b/examples/todo-list/README.rst @@ -3,8 +3,15 @@ todo list This is a small tutorial coming with `Pythonium `_ that will help you get started. -Getting started -=============== +Admonition +========== + +Pythonium just allows to translate programs written in Python 3 to be run in the browser. So what? So you still need to learn HTML5. This is not difficult, documentation is all over the web `dochub.io `_ is very nice. `jQuery API `_ is well documented. With the knowledge that you can directly call Javascript objects from Python with Pythonium you can do most of the things. That's why the following don't dive into how to use jQuery or how to build a full blown application but only walk through the step to create a simple todo list. + +Enjoy! + +Getting Ready +============= First you will need Python 3, refer to your OS documentation to know how to get it. @@ -27,7 +34,9 @@ It's assumed you have recent browser and an editor. Create a file named ``index.

A todo list

-
+ +
    +
@@ -73,3 +82,100 @@ It will print the following:: Héllo You can also open ``index.html`` it should also print the same message in the developer console. Refer to your browser documentation to know how to get access to it. + +Jumping +======= + +First thing, first we need to be able to add a task. For that matter contains an input field with a button. jQuery is tailored manipulate HTML. The first thing you need is to retrieve HTML nodes, for this, you use `selectors `_. Selectors are similar to XPATH, it's specialized for HTML documents. jQuery can be compared is JavaScript class, that once instantiated represents one or several HTML nodes that match the selector given to the constructor. To retrieve the input and the button the following code can be used:: + + input = jQuery('[type="text"]') + button = jQuery('[type="submit"]') + +If you write this directly and compile it. It will fail, because jQuery takes a JavaScript string as argument and strings in the source Python are converted to Python strings. This is the same for floats and integers. + +There is several workarounds. + +``JS`` special function +----------------------- + +First you can tell the compiler that the string is actually JavaScript code, and that it should not try to compile it. For that matter there is special function named ``JS`` which string argument is inlined in the generated code, it can be used in this context as follow:: + + input = jQuery(JS("""'[type="text"]'""")) + +Mind the extra care needed to handle the different types of quotes. This is a bit ugly, but it allows to bypass the translation process. It can come handy in some situations, where the JavaScript syntax is not compatible with the Python syntax. For instance there is no new keyword in Python, so the following valid Javascript code:: + + now = new Date() + +The above is invalid in code written to be compiled by Pythonium. You can use the ``JS`` function to circuvent this limitation as follow:: + + now = JS('new Date()') + +This looks pretty good. And you can call ``now`` methods transparently from Python:: + + year = now.getFullYear() + +``year`` is now, the current year as a **JavaScript integer**. + +You must be carful when interacting with JavaScript objects, depending on what you need, to convert to Python and call Python methods and keep them as JavaScript objects and call JavaScript methods. Mind the fact that the following code will fail:: + + delta = Date.now() - Date.now() + +Because the compiler only knows how to call methods, it can find out whether one object is a native JavaScript object and call its JavaScript method. But it can not convert automatically JavaScript objects to their Python version on-the-fly. In this case, Pythonium will try to call ``__add__`` method of the JavaScript integer returned by ``Date.now()`` and will fail, because it doesn't exists. + +Anyway, if you really want do the above operation you can use ``JS`` function:: + + delta = JS('Date.now() - Date.now()') + +But ``delta`` will still be a JavaScript object. It's possible to convert the JavaScript integer to a Python integer with the following code:: + + year = int(JS('Date.now() - Date.now()')) + +``list``, ``dict``, ``int`` and ``float`` can be used in a similar fashion. + +``jstype`` function +------------------- + +``jstype`` allows to convert a Python type to a JavaScript object, it can be used to solve the above problem as follow:: + + input = jQuery(jstype('[type="text"]')) + +Solution +-------- + +Let's define a another ``jQuery`` function that automatically convert it argument to a JavaScript string, since that's what we will use all the time:: + + def jQuery(selector): + return __DOLLAR__(jstype(selector)) + +``__DOLLAR__`` is replaced by the ``$`` character anywhere it's found. ``$`` is another name of the jQuery object. + +At this point ``app.py`` is:: + + def jQuery(selector): + return __DOLLAR__(jstype(selector)) + + input = jQuery('[type="text"]') + button = jQuery('[type="submit"]') + + +Call me back! +============= + +Frontend dev is full of callbacks. At least when you don't use ``yield`` or ``yield from``. When the user clicks on the button we want to check the content of field and if it has content, add the content as a task. Let's define an ``on_click`` function:: + + def on_click(event): + # event is JavaScript Event + text = str(input.val()) # convert the JavaScript string to a Python string + if len(text): + add_todo(text) + +To attach this method to ``button``, use its ``click`` method:: + + button.click(on_click) + +``add_todo`` is not yet defined and is left as an exercise. + +Diving +====== + +Read `MDN `_, `webplatform `_ and create beautiful things :-) diff --git a/examples/todo-list/app.py b/examples/todo-list/app.py index 6bd0f78..e69de29 100644 --- a/examples/todo-list/app.py +++ b/examples/todo-list/app.py @@ -1 +0,0 @@ -print('Héllo') diff --git a/examples/todo-list/index.html b/examples/todo-list/index.html index 071be68..9dd9678 100644 --- a/examples/todo-list/index.html +++ b/examples/todo-list/index.html @@ -7,7 +7,9 @@

A todo list

-
+ +
    +
diff --git a/pythonium/lib/builtins.py b/pythonium/lib/builtins.py index 2c107be..2638a91 100644 --- a/pythonium/lib/builtins.py +++ b/pythonium/lib/builtins.py @@ -29,3 +29,7 @@ def map(func, objects): for obj in objects: out.append(func(obj)) return out + +def jstype(obj): + # XXX: fallback to __jstype__ method when it doesn't exist + return obj.jsobject From 246d3be95c918b31063c0b4ee99e4a2783dc082f Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 3 Dec 2013 22:02:27 +0100 Subject: [PATCH 011/160] bump 0.4.7 --- pythonium/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonium/main.py b/pythonium/main.py index 1d18e4a..90ca385 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -23,7 +23,7 @@ from .pythonium import pythonium_generate_js -__version__ = '0.4.6' +__version__ = '0.4.7' def main(): From 7cfeaf2468e7d6bc93a5221c80090b6515898b63 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 3 Dec 2013 22:03:56 +0100 Subject: [PATCH 012/160] add a note about the tutorial at the top of README.rst --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 107a64d..f3aae2e 100644 --- a/README.rst +++ b/README.rst @@ -5,6 +5,8 @@ Pythonium Python 3 to Javascript translator written in Python that produces fast portable javascript code. +**tldr**: read the `tutorial `_ + Getting started (2 minutes) =========================== From de2e2fe6820bb53a5c5d050fc59575470051597b Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Wed, 4 Dec 2013 20:15:07 +0100 Subject: [PATCH 013/160] stub solution to the tutorial --- examples/todo-list/app.py | 10 + examples/todo-list/app.py.js | 18 +- examples/todo-list/index.html | 34 +- examples/todo-list/jquery.js | 9789 +++++++++++++++++++++++++++++++ examples/todo-list/pythonium.js | 80 +- 5 files changed, 9862 insertions(+), 69 deletions(-) create mode 100644 examples/todo-list/jquery.js diff --git a/examples/todo-list/app.py b/examples/todo-list/app.py index e69de29..ec57d24 100644 --- a/examples/todo-list/app.py +++ b/examples/todo-list/app.py @@ -0,0 +1,10 @@ +def jQuery(selector): + return __DOLLAR__(jstype(selector)) + +input = jQuery('[type="text"]') +button = jQuery('[type="submit"]') + +def on_click(event): + print('Héy') + +button.click(on_click) diff --git a/examples/todo-list/app.py.js b/examples/todo-list/app.py.js index b5cb373..26f486a 100644 --- a/examples/todo-list/app.py.js +++ b/examples/todo-list/app.py.js @@ -1 +1,17 @@ -pythonium_call(print, pythonium_call(str, "Héllo")); +var jQuery = function(selector) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call($, pythonium_call(jstype, selector)); +}; +input = pythonium_call(jQuery, pythonium_call(str, '[type="text"]')); +button = pythonium_call(jQuery, pythonium_call(str, '[type="submit"]')); +var on_click = function(event) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_call(print, pythonium_call(str, "Héy")); +}; +pythonium_call(pythonium_get_attribute(button, "click"), on_click); diff --git a/examples/todo-list/index.html b/examples/todo-list/index.html index 9dd9678..a35a7e6 100644 --- a/examples/todo-list/index.html +++ b/examples/todo-list/index.html @@ -1,17 +1,17 @@ - - - - todo list by Pythonium - - - - -

A todo list

- -
    -
- - - - - + + + + todo list by Pythonium + + + + +

A todo list

+ +
    +
+ + + + + diff --git a/examples/todo-list/jquery.js b/examples/todo-list/jquery.js new file mode 100644 index 0000000..c5c6482 --- /dev/null +++ b/examples/todo-list/jquery.js @@ -0,0 +1,9789 @@ +/*! + * jQuery JavaScript Library v1.10.2 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03T13:48Z + */ +(function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.2", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.10.2 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent.attachEvent && parent !== parent.top ) { + parent.attachEvent( "onbeforeunload", function() { + setDocument(); + }); + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "
"; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; + } + }); +} + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
a"; + + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; + a = div.getElementsByTagName("a")[ 0 ]; + if ( !a || !a.style || !all.length ) { + return support; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
t
"; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior. + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
"; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})({}); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + data = null, + i = 0, + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + return tabindex ? + parseInt( tabindex, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = { + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }; + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = ret.push( cur ); + break; + } + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each(function() { + if ( isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery(" + + diff --git a/web-console/js/ace b/web-console/js/ace new file mode 160000 index 0000000..3bded0b --- /dev/null +++ b/web-console/js/ace @@ -0,0 +1 @@ +Subproject commit 3bded0bc1b5b51f74afd2f8dafb768ab8f35b00b diff --git a/web-console/js/app.py b/web-console/js/app.py new file mode 100644 index 0000000..29176f3 --- /dev/null +++ b/web-console/js/app.py @@ -0,0 +1,17 @@ +editors = {} +for lang in ['css', 'html', 'python']: + editor = ace.edit(lang + "-editor") + editors[lang] = editor + editor.setTheme("ace/theme/monokai") + editor.getSession().setMode("ace/mode/" + lang) + +def compile(): + jQuery.ajax({ + url: '/compile', + type: 'POST', + data: {css=editors["css"].getValue(), html=editors["html"].getValue(), python=editors["python"].getValue()}, + } + jQuery("iframe"). + + +jQuery('[value="compile"]').click(compile) diff --git a/web-console/js/app.py.js b/web-console/js/app.py.js new file mode 100644 index 0000000..4ee7e74 --- /dev/null +++ b/web-console/js/app.py.js @@ -0,0 +1,9 @@ +editors = {}; +var iterator_lang = ["css", "html", "python"]; +for (var lang_iterator_index=0; lang_iterator_index < iterator_lang.length; lang_iterator_index++) { + var lang = iterator_lang[lang_iterator_index]; + editor = ace.edit((lang + "-editor")); + editors[lang] = editor; + editor.setTheme("ace/theme/monokai"); + editor.getSession().setMode(("ace/mode/" + lang)); +} diff --git a/web-console/js/classy.js b/web-console/js/classy.js new file mode 100644 index 0000000..d001fc6 --- /dev/null +++ b/web-console/js/classy.js @@ -0,0 +1,158 @@ +/** + * Classy - classy classes for JavaScript + * + * :copyright: (c) 2011 by Armin Ronacher. + * :license: BSD. + */ + +;(function(undefined) { + var + CLASSY_VERSION = '1.4', + root = this, + old_class = root.Class, + disable_constructor = false; + + /* we check if $super is in use by a class if we can. But first we have to + check if the JavaScript interpreter supports that. This also matches + to false positives later, but that does not do any harm besides slightly + slowing calls down. */ + var probe_super = (function(){$super();}).toString().indexOf('$super') > 0; + function usesSuper(obj) { + return !probe_super || /\B\$super\b/.test(obj.toString()); + } + + /* helper function to set the attribute of something to a value or + removes it if the value is undefined. */ + function setOrUnset(obj, key, value) { + if (value === undefined) + delete obj[key]; + else + obj[key] = value; + } + + /* gets the own property of an object */ + function getOwnProperty(obj, name) { + return Object.prototype.hasOwnProperty.call(obj, name) + ? obj[name] : undefined; + } + + /* instanciate a class without calling the constructor */ + function cheapNew(cls) { + disable_constructor = true; + var rv = new cls; + disable_constructor = false; + return rv; + } + + /* the base class we export */ + var Class = function() {}; + + /* restore the global Class name and pass it to a function. This allows + different versions of the classy library to be used side by side and + in combination with other libraries. */ + Class.$noConflict = function() { + try { + setOrUnset(root, 'Class', old_class); + } + catch (e) { + // fix for IE that does not support delete on window + root.Class = old_class; + } + return Class; + }; + + /* what version of classy are we using? */ + Class.$classyVersion = CLASSY_VERSION; + + /* extend functionality */ + Class.$extend = function(properties) { + var super_prototype = this.prototype; + + /* disable constructors and instanciate prototype. Because the + prototype can't raise an exception when created, we are safe + without a try/finally here. */ + var prototype = cheapNew(this); + + /* copy all properties of the includes over if there are any */ + if (properties.__include__) + for (var i = 0, n = properties.__include__.length; i != n; ++i) { + var mixin = properties.__include__[i]; + for (var name in mixin) { + var value = getOwnProperty(mixin, name); + if (value !== undefined) + prototype[name] = mixin[name]; + } + } + + /* copy class vars from the superclass */ + properties.__classvars__ = properties.__classvars__ || {}; + if (prototype.__classvars__) + for (var key in prototype.__classvars__) + if (!properties.__classvars__[key]) { + var value = getOwnProperty(prototype.__classvars__, key); + properties.__classvars__[key] = value; + } + + /* copy all properties over to the new prototype */ + for (var name in properties) { + var value = getOwnProperty(properties, name); + if (name === '__include__' || + value === undefined) + continue; + + prototype[name] = typeof value === 'function' && usesSuper(value) ? + (function(meth, name) { + return function() { + var old_super = getOwnProperty(this, '$super'); + this.$super = super_prototype[name]; + try { + return meth.apply(this, arguments); + } + finally { + setOrUnset(this, '$super', old_super); + } + }; + })(value, name) : value + } + + /* dummy constructor */ + var rv = function() { + if (disable_constructor) + return; + var proper_this = root === this ? cheapNew(arguments.callee) : this; + if (proper_this.__init__) + proper_this.__init__.apply(proper_this, arguments); + proper_this.$class = rv; + return proper_this; + } + + /* copy all class vars over of any */ + for (var key in properties.__classvars__) { + var value = getOwnProperty(properties.__classvars__, key); + if (value !== undefined) + rv[key] = value; + } + + /* copy prototype and constructor over, reattach $extend and + return the class */ + rv.prototype = prototype; + rv.constructor = rv; + rv.$extend = Class.$extend; + rv.$withData = Class.$withData; + return rv; + }; + + /* instanciate with data functionality */ + Class.$withData = function(data) { + var rv = cheapNew(this); + for (var key in data) { + var value = getOwnProperty(data, key); + if (value !== undefined) + rv[key] = value; + } + return rv; + }; + + /* export the class */ + root.Class = Class; +})(); diff --git a/web-console/js/jquery.js b/web-console/js/jquery.js new file mode 100644 index 0000000..2be209d --- /dev/null +++ b/web-console/js/jquery.js @@ -0,0 +1,6 @@ +/*! jQuery v2.0.3 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery-2.0.3.min.map +*/ +(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t) +};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"
","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x(" + diff --git a/web-console/js/app.py b/web-console/js/app.py index a1db51e..2a7ecb8 100644 --- a/web-console/js/app.py +++ b/web-console/js/app.py @@ -5,13 +5,17 @@ editor.setTheme("ace/theme/monokai") editor.getSession().setMode("ace/mode/" + lang) +def reload_iframe(): + document.getElementById("result").contentDocument.location.reload(True) + def compile(): + mode = jQuery("select").val() jQuery.ajax({ url: '/compile', type: 'POST', - data: {css: editors["css"].getValue(), html: editors["html"].getValue(), python:editors["python"].getValue()}, - }) - jQuery("iframe").src = '/compiled' + data: {css: editors["css"].getValue(), html: editors["html"].getValue(), python:editors["python"].getValue(), mode: mode}, + }).done(reload_iframe) + jQuery('[value="compile"]').click(compile) diff --git a/web-console/js/app.py.js b/web-console/js/app.py.js index 62c5fff..82595eb 100644 --- a/web-console/js/app.py.js +++ b/web-console/js/app.py.js @@ -7,8 +7,12 @@ for (var lang_iterator_index=0; lang_iterator_index < iterator_lang.length; lang editor.setTheme("ace/theme/monokai"); editor.getSession().setMode(("ace/mode/" + lang)); } +var reload_iframe = function() { + document.getElementById("result").contentDocument.location.reload(true); +}; var compile = function() { - jQuery.ajax({url:"/compile",type:"POST",data:{css:editors["css"].getValue(),html:editors["html"].getValue(),python:editors["python"].getValue()}}); - jQuery("iframe").src = "/compiled"; + var mode; + mode = jQuery("select").val(); + jQuery.ajax({url:"/compile",type:"POST",data:{css:editors["css"].getValue(),html:editors["html"].getValue(),python:editors["python"].getValue(),mode:mode}}).done(reload_iframe); }; jQuery('[value="compile"]').click(compile); diff --git a/web-console/requirements.txt b/web-console/requirements.txt index 4568f24..47e41b6 100644 --- a/web-console/requirements.txt +++ b/web-console/requirements.txt @@ -1,2 +1,4 @@ -rororo +webob +server-reloader pythonium +html5lib diff --git a/web-console/wsgi.py b/web-console/wsgi.py index c6b02a9..e45156c 100755 --- a/web-console/wsgi.py +++ b/web-console/wsgi.py @@ -1,56 +1,140 @@ #!/usr/bin/env python3 -import os - -from rororo import GET -from rororo import manage -from rororo import create_app -from rororo.static import static -from rororo.manager import runserver - - -ROUTES = [] - -# statics - -DIRNAME = os.path.abspath(os.path.dirname(__file__)) -rel = lambda *parts: os.path.abspath(os.path.join(DIRNAME, *parts)) -ROUTES.append(static('css', 'css')) -ROUTES.append(static('js', 'js')) - -# index page - -with open('index.html') as f: - index_content = f.read() - -index = lambda: index_content -ROUTES.append(GET('/', index)) - -# compile -CSS = "" -HTML = "" -PYTHON = "" - -def compile(): - global CSS, HTML, PYTHON - CSS = "" - HTML = "" - PYTHON = "" - -ROUTES.append(GET('/compile', compile)) - -# COMPILED - -with open('howto.html') as f: - HOWTO = f.read() - -def compiled(): - if not PYTHON: - return HOWTO +import random +import string +import json +from ast import parse +from logging import getLogger +from traceback import print_exc +from xml.etree.ElementTree import Element +from xml.etree.ElementTree import tostring + +import html5lib +from webob import Request +from webob import Response +from jinja2 import Environment +from jinja2 import FileSystemLoader +from fileserver import file_response + +from pythonium.veloce import Veloce +from pythonium.pythonium import Pythonium +class Nerfed(object): + + def __init__(self): + self.handlers = dict() + + def register(self, view, path): + self.handlers[path] = view + + def __call__(self, environ, start_response): + request = Request(environ) + # first match the domain if any try to match the path + view = self.handlers.get(request.path, None) + if view is None: + response = Response('

Not found

', 404) + else: + try: + response = view(self, request) + except Exception: + print_exc() + response = Response('

Internal Server Error

', 500) + return response(environ, start_response) + + def redirect(self, url): + return Response(status=302, location=url) + + def reverse(self, view): + for path, v in self.handlers.items(): + if v == view: + return path + +# + +cache = dict() + +# + +def static(path): + def view(self, request): + return file_response(path) + return view + +app = Nerfed() + +# INDEX + +app.register(static('index.html'), '/') + + +# COMPILE + +def compile(app, request): + response = Response('', 200) + token = request.cookies.get('token', None) + if token is None: + token = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(512)) + response.set_cookie('token', token) + POST = request.POST + mode = POST['mode'] + python = POST['python'] + tree = parse(python) + if mode == 'compliant': + veloce = Veloce() + veloce.visit(tree) + js = veloce.writer.value() + else: + pythonium = Pythonium() + pythonium.visit(tree) + js = pythonium.writer.value() + css = POST['css'] + html = POST['html'] + html = html5lib.parse(html, namespaceHTMLElements=False) + style = Element("style") + style.text = css if css else '/* nothing */' + script = Element("script") + script.set('type', "text/javascript") + script.text = js if js else '/* nothing yet */' + body = html.find('body') + body.insert(0, script) + body.insert(0, style) + page = tostring(html) + cache[token] = page + return response + +app.register(compile, '/compile') -ROUTES.append(GET('/compiled', compiled)) - +# COMPILED -app = create_app(routes=ROUTES) -runserver(app, autoreload=True) +def compiled(app, request): + token = request.cookies.get('token', None) + if token is None: + return static('howto.html')(app, request) + try: + page = cache[token] + except: + response = static('howto.html')(app, request) + response.delete_cookie('token') + return response + return Response(page, 200) + +app.register(compiled, '/compiled') + +if __name__ == '__main__': + from wsgiref.simple_server import make_server + from server_reloader import main as reloader + app.register(static('js/ace/src-noconflict/ace.js'), '/js/ace/src-noconflict/ace.js') + app.register(static('js/ace/src-noconflict/theme-monokai.js'), '/js/ace/src-noconflict/theme-monokai.js') + app.register(static('js/ace/src-noconflict/mode-css.js'), '/js/ace/src-noconflict/mode-css.js') + app.register(static('js/ace/src-noconflict/worker-css.js'), '/js/ace/src-noconflict/worker-css.js') + app.register(static('js/ace/src-noconflict/mode-html.js'), '/js/ace/src-noconflict/mode-html.js') + app.register(static('js/ace/src-noconflict/mode-python.js'), '/js/ace/src-noconflict/mode-python.js') + app.register(static('js/classy.js'), '/js/classy.js') + app.register(static('js/jquery.js'), '/js/jquery.js') + app.register(static('js/app.py.js'), '/js/app.py.js') + app.register(static('css/app.css'), '/css/app.css') + def run_server(): + server = make_server('localhost', 8000, app) + print('Starting server at http://127.0.0.1:8000') + server.serve_forever() + reloader(run_server) From 3166902e81799873b0bf0c29a245aadef7d9849b Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 21:15:22 +0100 Subject: [PATCH 024/160] web console: fix support for compliant mode --- web-console/wsgi.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/web-console/wsgi.py b/web-console/wsgi.py index e45156c..05adbdd 100755 --- a/web-console/wsgi.py +++ b/web-console/wsgi.py @@ -79,7 +79,7 @@ def compile(app, request): mode = POST['mode'] python = POST['python'] tree = parse(python) - if mode == 'compliant': + if mode == 'veloce': veloce = Veloce() veloce.visit(tree) js = veloce.writer.value() @@ -90,14 +90,22 @@ def compile(app, request): css = POST['css'] html = POST['html'] html = html5lib.parse(html, namespaceHTMLElements=False) - style = Element("style") - style.text = css if css else '/* nothing */' - script = Element("script") - script.set('type', "text/javascript") - script.text = js if js else '/* nothing yet */' body = html.find('body') - body.insert(0, script) - body.insert(0, style) + if js: + script = Element("script") + script.set('type', 'text/javascript') + script.text = js + body.insert(0, script) + if css: + style = Element("style") + style.text = css + body.insert(0, style) + if mode == 'compliant': + script = Element("script") + script.set('type', 'text/javascript') + script.set('src', '/js/pythonium.js') + script.text = "/* nothing */" + body.insert(0, script) page = tostring(html) cache[token] = page return response @@ -132,6 +140,7 @@ def compiled(app, request): app.register(static('js/classy.js'), '/js/classy.js') app.register(static('js/jquery.js'), '/js/jquery.js') app.register(static('js/app.py.js'), '/js/app.py.js') + app.register(static('js/pythonium.js'), '/js/pythonium.js') app.register(static('css/app.css'), '/css/app.css') def run_server(): server = make_server('localhost', 8000, app) From 594d04390dc2ff43f02e57a50e550d4837048f61 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 21:28:04 +0100 Subject: [PATCH 025/160] web console: add memory limit --- web-console/wsgi.py | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/web-console/wsgi.py b/web-console/wsgi.py index 05adbdd..a7ffb38 100755 --- a/web-console/wsgi.py +++ b/web-console/wsgi.py @@ -17,7 +17,13 @@ from pythonium.veloce import Veloce from pythonium.pythonium import Pythonium - + + +import resource + + +resource.setrlimit(resource.RLIMIT_AS, (1000 * 1048576, -1)) + class Nerfed(object): @@ -28,18 +34,24 @@ def register(self, view, path): self.handlers[path] = view def __call__(self, environ, start_response): - request = Request(environ) - # first match the domain if any try to match the path - view = self.handlers.get(request.path, None) - if view is None: - response = Response('

Not found

', 404) - else: - try: - response = view(self, request) - except Exception: - print_exc() - response = Response('

Internal Server Error

', 500) - return response(environ, start_response) + try: + request = Request(environ) + # first match the domain if any try to match the path + view = self.handlers.get(request.path, None) + if view is None: + response = Response('

Not found

', 404) + else: + try: + response = view(self, request) + except Exception: + print_exc() + response = Response('

Internal Server Error

', 500) + return response(environ, start_response) + except MemoryError: + global cache + del cache + cache = dict() + return self(environ, start_response) def redirect(self, url): return Response(status=302, location=url) From 7fcedf8bfb0e508867dcef9b3538156f632fc8c0 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 21:28:25 +0100 Subject: [PATCH 026/160] web console: missing pythonium.js --- web-console/js/pythonium.js | 1054 +++++++++++++++++++++++++++++++++++ 1 file changed, 1054 insertions(+) create mode 100644 web-console/js/pythonium.js diff --git a/web-console/js/pythonium.js b/web-console/js/pythonium.js new file mode 100644 index 0000000..a72ad17 --- /dev/null +++ b/web-console/js/pythonium.js @@ -0,0 +1,1054 @@ +__object = {__bases__:[],__name__:"object"}; +__object.__mro__ = [__object]; +__type = {__bases__:[__object],__mro__:[__object],__name__:"type"}; +__object.__metaclass__ = __type; +__ARGUMENTS_PADDING__ = {ARGUMENTS_PADDING:"YES IT IS!"}; +var __isnot__ = function(self, other) { + return !(this === other); +}; +__object.__isnot__ = __isnot__; +var issubclass = function(klass, other) { + if((klass === other)) { + return true; + } + if(!klass.__bases__) { + return false; + } + var iterator_base = klass.__bases__; + for (var base_iterator_index=0; base_iterator_index < iterator_base.length; base_iterator_index++) { + var base = iterator_base[base_iterator_index]; + if(issubclass(base, other)) { + return true; + } + } + return false; +}; +var pythonium_create_dict = function(keys, values) { + var index,key,out,max,value; + out = {}; + max = keys.length; + index = 0; + while((index < max)) { + key = keys[index].jsobject; + value = values[index]; + out[key] = value; + index = index + 1; + } + return pythonium_call(dict, out, undefined); +}; +var pythonium_is_true = function(v) { + if(((v === __FALSE)||(v === false))) { + return false; + } + if(((v === __TRUE)||(v !== undefined&&(v != __NONE)))) { + return true; + } + if(isinstance(v, int)) { + if((pythonium_get_attribute(v, "jsobject") == 0)) { + return false; + } + return true; + } + return false; +}; +var isinstance = function(object, klass) { + if(object.__class__) { + return issubclass(object.__class__, klass); + } + return false; +}; +var pythonium_obj_to_js_exception = function(obj) { + var exception = function() { + this.exception = obj; + }; + return exception; +}; +var pythonium_is_exception = function(obj, exc) { + if((obj === exc)) { + return true; + } + return isinstance(obj, exc); +}; +var pythonium_call = function(object) { + var init,instance,args; + args = Array.prototype.slice.call(arguments, 1); + if(object.__metaclass__) { + instance = {__class__:object}; + init = lookup(instance, "__init__"); + if(init) { + init.apply(instance, args); + } + return instance; + } + else { + return object.apply(object, args); + } +}; +var pythonium_mro = function(bases) { + var non_empty,index,empty,not_head,res,candidate,seqs; + "Calculate the Method Resolution Order of bases using the C3 algorithm.\n\n Suppose you intended creating a class K with the given base classes. This\n function returns the MRO which K would have, *excluding* K itself (since\n it doesn't yet exist), as if you had actually created the class.\n\n Another way of looking at this, if you pass a single class K, this will\n return the linearization of K (the MRO of K, *including* itself).\n "; + var __comp0__ = []; + var __iterator1__ = bases; + for (var __index2__ = 0; __index2__<__iterator1__.length; __index2__++) { + var C = __iterator1__[__index2__]; + __comp0__.push(C.__mro__); + } + seqs = __comp0__; + seqs.push(bases.slice()); + res = []; + while(true) { + non_empty = []; + var iterator_seq = seqs; + for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { + var seq = iterator_seq[seq_iterator_index]; + empty = true; + var iterator_item = seq; + for (var item_iterator_index=0; item_iterator_index < iterator_item.length; item_iterator_index++) { + var item = iterator_item[item_iterator_index]; + if(item) { + empty = false; + break; + } + } + if(!empty) { + non_empty.push(seq); + } + } + if((non_empty.length == 0)) { + return res; + } + var iterator_seq = non_empty; + for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { + var seq = iterator_seq[seq_iterator_index]; + candidate = seq[0]; + var __comp3__ = []; + var __iterator4__ = non_empty; + for (var __index5__ = 0; __index5__<__iterator4__.length; __index5__++) { + var s = __iterator4__[__index5__]; + if(!(candidate in s.splice(1))) { continue; } + __comp3__.push(s); + } + not_head = __comp3__; + if((not_head.length != 0)) { + candidate = undefined; + } + else { + break; + } + } + if(!candidate) { + throw TypeError("Inconsistent hierarchy, no C3 MRO is possible"); + } + res.push(candidate); + var iterator_seq = seqs; + for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { + var seq = iterator_seq[seq_iterator_index]; + index = seq.indexOf(candidate); + if((index >= 0)) { + delete seq[index]; + } + } + } +}; +var pythonium_create_class = function(name, bases, attrs) { + var mro; + attrs.__name__ = name; + attrs.__metaclass__ = __type; + attrs.__bases__ = bases; + mro = pythonium_mro(bases); + mro.splice(0, 0, attrs); + attrs.__mro__ = mro; + return attrs; +}; +var lookup = function(object, attr) { + var object_attr,class_attr; + object_attr = object[attr]; + if((object_attr != undefined)) { + if((object_attr&&({}.toString.call(object_attr) == "[object Function]"))) { + var method_wrapper = function() { + var args; + args = Array.prototype.slice.call(arguments); + args.splice(0, 0, object); + return object_attr.apply(undefined, args); + }; + return method_wrapper; + } + return object_attr; + } + else { + var iterator_base = object.__class__.__mro__; + for (var base_iterator_index=0; base_iterator_index < iterator_base.length; base_iterator_index++) { + var base = iterator_base[base_iterator_index]; + class_attr = base[attr]; + if((class_attr != undefined)) { + if(({}.toString.call(class_attr) == "[object Function]")) { + var method_wrapper = function() { + var args; + args = Array.prototype.slice.call(arguments); + args.splice(0, 0, object); + return class_attr.apply(undefined, args); + }; + return method_wrapper; + } + return class_attr; + } + } + } +}; +var pythonium_object_get_attribute = function(object, attr) { + var getattr,r; + r = lookup(object, attr); + if((r != undefined)) { + return r; + } + else { + getattr = lookup(object, "__getattr__"); + if(getattr) { + return getattr(attr); + } + else { + throw AttributeError; + } + } +}; +__object.__getattribute__ = pythonium_object_get_attribute; +var pythonium_get_attribute = function(object, attr) { + var getattribute; + if(object.__class__) { + getattribute = lookup(object, "__getattribute__"); + return getattribute(attr); + } + attr = object[attr]; + if(attr) { + if(({}.toString.call(attr) == "[object Function]")) { + var method_wrapper = function() { + return attr.apply(object, arguments); + }; + return method_wrapper; + } + else { + return attr; + } + } +}; +var pythonium_set_attribute = function(object, attr, value) { + object[attr] = value; +}; +var range = function(a, b) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 1 > varkwargs_start) { + b = __kwargs.b || __NONE; + } else { + b = b || __kwargs.b || __NONE; + } + /* END unpacking arguments */ + var end,index,out; + /* BEGIN function */ + if (pythonium_is_true(b)) { + index = a; + end = b; + } + else { + index = pythonium_call(int, 0); + end = a; + } + out = pythonium_call(list); + while(pythonium_is_true((pythonium_get_attribute(index, "__lt__")(end)))) { + pythonium_call(pythonium_get_attribute(out, "append"), index); + index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); + } + return out; +}; +var repr = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__repr__")); +}; +var print = function() { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + var args = __args.splice(0); + args = pythonium_call(list, args); + /* END unpacking arguments */ + var out,r; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(args), "__next__"); + while(true) { + var arg = pythonium_call(__next__); + r = pythonium_call(repr, arg); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_get_attribute(r, "jsobject")); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(console, "log"), "apply"), console, pythonium_get_attribute(out, "jsobject")); +}; +var map = function(func, objects) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(objects), "__next__"); + while(true) { + var obj = pythonium_call(__next__); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_call(func, obj)); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return out; +}; +var jstype = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_get_attribute(obj, "jsobject"); +}; +/* class definition _True */ +var __init__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", true); +}; +var __and__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __TRUE; +}; +var __is__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __FALSE; +}; +var _True = pythonium_create_class("_True", [__object], { + __init__: __init__, + __and__: __and__, + __or__: __or__, + __is__: __is__, + __neg__: __neg__, +}); +/* class definition _False */ +var __init__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", false); +}; +var __and__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __FALSE; +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === True)) { + return __TRUE; + } + return __FALSE; +}; +var __is__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __TRUE; +}; +var _False = pythonium_create_class("_False", [__object], { + __init__: __init__, + __and__: __and__, + __or__: __or__, + __is__: __is__, + __neg__: __neg__, +}); +__TRUE = pythonium_call(_True); +__FALSE = pythonium_call(_False); +/* class definition StopIteration */ +/* pass */ +var StopIteration = pythonium_create_class("StopIteration", [__object], { +}); +var iter = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__iter__")); +}; +var next = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__next__")); +}; +var len = function(obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(obj, "__len__")); +}; +/* class definition ListIterator */ +var __init__ = function(self, obj) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "list", obj); + pythonium_set_attribute(self, "index", pythonium_call(int, 0)); + pythonium_set_attribute(self, "length", pythonium_call(len, obj)); +}; +var __next__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__eq__")(pythonium_get_attribute(self, "length"))))) { + throw StopIteration; + } + pythonium_set_attribute(self, "index", (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__add__"), pythonium_call(int, 1)))); + return pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "list"), '__getitem__'), (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__sub__"), pythonium_call(int, 1)))); +}; +var ListIterator = pythonium_create_class("ListIterator", [__object], { + __init__: __init__, + __next__: __next__, +}); +/* class definition list */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 1 > varkwargs_start) { + jsobject = __kwargs.jsobject || __NONE; + } else { + jsobject = jsobject || __kwargs.jsobject || __NONE; + } + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(jsobject)) { + pythonium_set_attribute(self, "jsobject", jsobject); + } + else { + pythonium_set_attribute(self, "jsobject", []); + } +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var s; + /* BEGIN function */ + s = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "["), "__add__"), pythonium_call(pythonium_get_attribute(pythonium_call(str, ", "), "join"), self))), "__add__"), pythonium_call(str, "]"))); + return s; +}; +var append = function(self, item) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + jsobject.push(item); +}; +var insert = function(self, index, item) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "splice"), index, pythonium_call(int, 0), item); +}; +var __setitem__ = function(self, index, value) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(index, "jsobject"); + jsobject[index] = value; +}; +var __getitem__ = function(self, s) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var index,jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(s, "jsobject"); + return jsobject[index]; +}; +var __len__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var length,jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + length = jsobject.length; + return pythonium_call(int, length); +}; +var __iter__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(ListIterator, self); +}; +var list = pythonium_create_class("list", [__object], { + __init__: __init__, + __repr__: __repr__, + append: append, + insert: insert, + __setitem__: __setitem__, + __getitem__: __getitem__, + __len__: __len__, + __iter__: __iter__, +}); +/* class definition float */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return self; +}; +var __div__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(float, a / b); +}; +var __sub__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(float, a - b); +}; +var __eq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { + return __TRUE; + } + return __FALSE; +}; +var float = pythonium_create_class("float", [__object], { + __init__: __init__, + __repr__: __repr__, + __div__: __div__, + __sub__: __sub__, + __eq__: __eq__, +}); +/* class definition _None */ +var __and__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + return __TRUE; + } + return __FALSE; +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + return __TRUE; + } + return __FALSE; +}; +var __is__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + if (pythonium_is_true(other === self)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return __TRUE; +}; +var _None = pythonium_create_class("_None", [__object], { + __and__: __and__, + __or__: __or__, + __is__: __is__, + __neg__: __neg__, +}); +__NONE = pythonium_call(_None); +/* class definition iterator */ +var __init__ = function(self, list) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + /* pass */ +}; +var iterator = pythonium_create_class("iterator", [__object], { + __init__: __init__, +}); +/* class definition slice */ +var __init__ = function(self, start, step, end) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "start", start); + pythonium_set_attribute(self, "step", step); + pythonium_set_attribute(self, "end", end); +}; +var slice = pythonium_create_class("slice", [__object], { + __init__: __init__, +}); +/* class definition Exception */ +var __init__ = function(self, message) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "message", message); +}; +var Exception = pythonium_create_class("Exception", [__object], { + __init__: __init__, +}); +/* class definition TypeError */ +/* pass */ +var TypeError = pythonium_create_class("TypeError", [Exception], { +}); +/* class definition AttributeError */ +/* pass */ +var AttributeError = pythonium_create_class("AttributeError", [Exception], { +}); +/* class definition int */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return self; +}; +var __add__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(int, a + b); +}; +var __sub__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(int, a - b); +}; +var __lt__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a < b)) { + return __TRUE; + } + return __FALSE; +}; +var __lte__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a <= b)) { + return __TRUE; + } + return __FALSE; +}; +var __mul__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,c,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a * b; + return pythonium_call(int, c); +}; +var __or__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,c,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a || b; + return pythonium_call(int, c); +}; +var __eq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { + return __TRUE; + } + return __FALSE; +}; +var __neg__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + return pythonium_call(int, -jsobject); +}; +var __div__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(int, a / b); +}; +var int = pythonium_create_class("int", [__object], { + __init__: __init__, + __repr__: __repr__, + __add__: __add__, + __sub__: __sub__, + __lt__: __lt__, + __lte__: __lte__, + __mul__: __mul__, + __or__: __or__, + __eq__: __eq__, + __neg__: __neg__, + __div__: __div__, +}); +/* class definition dict */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out,key_repr,value_repr; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(pythonium_call(pythonium_get_attribute(self, "keys"))), "__next__"); + while(true) { + var key = pythonium_call(__next__); + key_repr = pythonium_call(repr, key); + value_repr = pythonium_call(repr, pythonium_call(pythonium_get_attribute(self, "get"), key)); + pythonium_call(pythonium_get_attribute(out, "append"), (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(key_repr, "__add__"), pythonium_call(str, ": "))), "__add__"), value_repr))); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "{"), "__add__"), pythonium_call(pythonium_get_attribute(pythonium_call(str, ", "), "join"), out))), "__add__"), pythonium_call(str, "}"))); +}; +var get = function(self, key, d) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = {}; + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 2 > varkwargs_start) { + d = __kwargs.d || __NONE; + } else { + d = d || __kwargs.d || __NONE; + } + /* END unpacking arguments */ + var jsobject,attr; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + key = pythonium_get_attribute(key, "jsobject"); + attr = jsobject[key]; + if (pythonium_is_true((pythonium_get_attribute(__NONE, "__isnot__")(attr)))) { + return attr; + } + else { + return d; + } +}; +var __setitem__ = function(self, key, value) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "__setitem__"), key, value); +}; +var keys = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(map, str, pythonium_call(list, pythonium_call(pythonium_get_attribute(Object, "keys"), pythonium_get_attribute(self, "jsobject")))); +}; +var items = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var out; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next__ = pythonium_get_attribute(iter(pythonium_call(pythonium_get_attribute(self, "keys"))), "__next__"); + while(true) { + var key = pythonium_call(__next__); + pythonium_call(pythonium_get_attribute(out, "append"), pythonium_call(list, [key, pythonium_call(pythonium_get_attribute(self, "get"), key)])); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return out; +}; +var dict = pythonium_create_class("dict", [__object], { + __init__: __init__, + __repr__: __repr__, + get: get, + __setitem__: __setitem__, + keys: keys, + items: items, +}); +/* class definition str */ +var __init__ = function(self, jsobject) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", jsobject); +}; +var __repr__ = function(self) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return self; +}; +var join = function(self, objects) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var obj,index,out,L; + /* BEGIN function */ + L = pythonium_call(len, objects); + if (pythonium_is_true(pythonium_call(pythonium_get_attribute(L, "__neg__")))) { + return pythonium_call(str, ""); + } + out = pythonium_call(pythonium_get_attribute(objects, '__getitem__'), pythonium_call(int, 0)); + index = pythonium_call(int, 1); + while(pythonium_is_true((pythonium_get_attribute(index, "__lt__")(L)))) { + obj = pythonium_call(pythonium_get_attribute(objects, '__getitem__'), index); + out = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(out, "__add__"), self)), "__add__"), obj)); + index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); + } + return out; +}; +var __add__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + return pythonium_call(str, a + b); +}; +var __lte__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a <= b)) { + return __TRUE; + } + return __FALSE; +}; +var __gte__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a >= b)) { + return __TRUE; + } + return __FALSE; +}; +var __gt__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a > b)) { + return __TRUE; + } + return __FALSE; +}; +var __eq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var a,b; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { + return __TRUE; + } + return __FALSE; +}; +var __getitem__ = function(self, index) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + var c,jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(index, "jsobject"); + c = jsobject[index]; + return pythonium_call(str, c); +}; +var __neq__ = function(self, other) { + /* BEGIN unpacking arguments */ + var __args = Array.prototype.slice.call(arguments); + /* END unpacking arguments */ + /* BEGIN function */ + return pythonium_call(pythonium_get_attribute(pythonium_call(pythonium_get_attribute(self, "__eq__"), other), "__neg__")); +}; +var str = pythonium_create_class("str", [__object], { + __init__: __init__, + __repr__: __repr__, + join: join, + __add__: __add__, + __lte__: __lte__, + __gte__: __gte__, + __gt__: __gt__, + __eq__: __eq__, + __getitem__: __getitem__, + __neq__: __neq__, +}); From 8d8acc7e06881740ed1ed151987929915ba2f539 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 21:52:19 +0100 Subject: [PATCH 027/160] web console: jinja is not needed --- web-console/wsgi.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/web-console/wsgi.py b/web-console/wsgi.py index a7ffb38..4d480fa 100755 --- a/web-console/wsgi.py +++ b/web-console/wsgi.py @@ -11,8 +11,6 @@ import html5lib from webob import Request from webob import Response -from jinja2 import Environment -from jinja2 import FileSystemLoader from fileserver import file_response from pythonium.veloce import Veloce From 3138aa35688d90d09945228bad42fb7b29e9f7f7 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 21:59:11 +0100 Subject: [PATCH 028/160] web console: update README --- web-console/README.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web-console/README.rst b/web-console/README.rst index b44a65d..71f6258 100644 --- a/web-console/README.rst +++ b/web-console/README.rst @@ -9,7 +9,11 @@ And install requirements:: pip install -r requirements.txt -You will need **python 3** environment! +You will need **python 3**! + +Use the following command to generate the default settings file:: + + echo "ROOT_URL = ''" > settings.py Run the server with the following command:: From 5ba91cdf9717b193fd041496d3bd8e6c80bd1054 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 21:59:46 +0100 Subject: [PATCH 029/160] update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 33c8257..5d36792 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ tmp/ core/tmp/ pystone/build/ +web-console/settings.py # C extensions *.so From e15e6e72fd37826deeb6e10af9b92a90109ce5ad Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 22:00:16 +0100 Subject: [PATCH 030/160] web console: add ROOT_URL support --- web-console/wsgi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web-console/wsgi.py b/web-console/wsgi.py index 4d480fa..99d4be1 100755 --- a/web-console/wsgi.py +++ b/web-console/wsgi.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 +import json import random import string -import json +import resource from ast import parse from logging import getLogger from traceback import print_exc @@ -16,8 +17,7 @@ from pythonium.veloce import Veloce from pythonium.pythonium import Pythonium - -import resource +from settings import ROOT_URL resource.setrlimit(resource.RLIMIT_AS, (1000 * 1048576, -1)) @@ -29,7 +29,7 @@ def __init__(self): self.handlers = dict() def register(self, view, path): - self.handlers[path] = view + self.handlers[ROOT_URL + path] = view def __call__(self, environ, start_response): try: From 494c78b0aa998dc93f883f8b909403c6e00fb227 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 22:14:41 +0100 Subject: [PATCH 031/160] web console: add cookie domain, make settings optional --- web-console/wsgi.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web-console/wsgi.py b/web-console/wsgi.py index 99d4be1..78b208e 100755 --- a/web-console/wsgi.py +++ b/web-console/wsgi.py @@ -17,7 +17,7 @@ from pythonium.veloce import Veloce from pythonium.pythonium import Pythonium -from settings import ROOT_URL +import settings resource.setrlimit(resource.RLIMIT_AS, (1000 * 1048576, -1)) @@ -29,7 +29,7 @@ def __init__(self): self.handlers = dict() def register(self, view, path): - self.handlers[ROOT_URL + path] = view + self.handlers[getattr(settings, 'ROOT_URL', '') + path] = view def __call__(self, environ, start_response): try: @@ -84,7 +84,7 @@ def compile(app, request): token = request.cookies.get('token', None) if token is None: token = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(512)) - response.set_cookie('token', token) + response.set_cookie('token', token, domain=getattr(settings, 'COOKIE_DOMAIN', None)) POST = request.POST mode = POST['mode'] python = POST['python'] @@ -132,7 +132,7 @@ def compiled(app, request): page = cache[token] except: response = static('howto.html')(app, request) - response.delete_cookie('token') + response.delete_cookie('token', domain==getattr(settings, 'COOKIE_DOMAIN', None)) return response return Response(page, 200) From 502f925bc913146c298ba67d68642dd3da5adb7c Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 22:14:43 +0100 Subject: [PATCH 032/160] webconsole: settings is not needed anymore --- web-console/README.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/web-console/README.rst b/web-console/README.rst index 71f6258..a38511b 100644 --- a/web-console/README.rst +++ b/web-console/README.rst @@ -11,10 +11,6 @@ And install requirements:: You will need **python 3**! -Use the following command to generate the default settings file:: - - echo "ROOT_URL = ''" > settings.py - Run the server with the following command:: python3 wsgi.py From d45212aa53d97fb3cd4ad9bf08e0c0980d5ad6c9 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 22:28:40 +0100 Subject: [PATCH 033/160] web console: python 3.3+ is required --- web-console/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-console/README.rst b/web-console/README.rst index a38511b..287cbe1 100644 --- a/web-console/README.rst +++ b/web-console/README.rst @@ -9,7 +9,7 @@ And install requirements:: pip install -r requirements.txt -You will need **python 3**! +You will need **python 3.3** or superior! Run the server with the following command:: From 79fb8a8f5987677a0251273465bf88784d5728ee Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 22:46:05 +0100 Subject: [PATCH 034/160] web console: fix paths --- web-console/index.html | 12 ++++++------ web-console/js/app.py | 2 +- web-console/wsgi.py | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/web-console/index.html b/web-console/index.html index 782e44b..b2a6388 100644 --- a/web-console/index.html +++ b/web-console/index.html @@ -3,7 +3,7 @@ Pythonium Web Console - + @@ -16,10 +16,10 @@
- - - - - + + + + + diff --git a/web-console/js/app.py b/web-console/js/app.py index 2a7ecb8..244c009 100644 --- a/web-console/js/app.py +++ b/web-console/js/app.py @@ -11,7 +11,7 @@ def reload_iframe(): def compile(): mode = jQuery("select").val() jQuery.ajax({ - url: '/compile', + url: 'compile', type: 'POST', data: {css: editors["css"].getValue(), html: editors["html"].getValue(), python:editors["python"].getValue(), mode: mode}, }).done(reload_iframe) diff --git a/web-console/wsgi.py b/web-console/wsgi.py index 78b208e..162bafc 100755 --- a/web-console/wsgi.py +++ b/web-console/wsgi.py @@ -113,7 +113,7 @@ def compile(app, request): if mode == 'compliant': script = Element("script") script.set('type', 'text/javascript') - script.set('src', '/js/pythonium.js') + script.set('src', 'js/pythonium.js') script.text = "/* nothing */" body.insert(0, script) page = tostring(html) From 99c1c5aadf3c7d79bad4c095743bf44c51f4575a Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 23:38:02 +0100 Subject: [PATCH 035/160] pythonium: typofix in code handling namespacing method definitions --- pythonium/pythonium.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pythonium/pythonium.py b/pythonium/pythonium.py index 95d21f4..95cdd72 100644 --- a/pythonium/pythonium.py +++ b/pythonium/pythonium.py @@ -144,9 +144,10 @@ def visit_Global(self, node): return '' def _is_inside_method_definition(self): + sys.stderr.write("{}\n".format(self._def_stack)) if len(self._def_stack) >= 2: if isinstance(self._def_stack[-2], ClassDefNode): - if isinstance(self._def_stack[-1], FunctionDef): + if isinstance(self._def_stack[-1], FunctionDefNode): return True return False From ac0f6978e012c71cbd43e30407ee9215edd2d7bd Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 23:40:41 +0100 Subject: [PATCH 036/160] fix nested generator definition if a generator was defined in a function both function were dubbed as generator functions --- pythonium/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pythonium/utils.py b/pythonium/utils.py index 5d2c733..5f38e80 100644 --- a/pythonium/utils.py +++ b/pythonium/utils.py @@ -5,3 +5,7 @@ class YieldSearch(NodeVisitor): def visit_Yield(self, node): self.has_yield = True + + def visit_FunctionDef(self, node): + pass # do not visit nest function definition to determine + # if a function has a yield or not... From 2e302c03d612504766e67203bff5f1fbe7002dbc Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 6 Dec 2013 23:47:54 +0100 Subject: [PATCH 037/160] pythonium: small optimisation, avoid declaring __args if it's not needed --- pythonium/pythonium.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pythonium/pythonium.py b/pythonium/pythonium.py index 95cdd72..867be30 100644 --- a/pythonium/pythonium.py +++ b/pythonium/pythonium.py @@ -144,7 +144,6 @@ def visit_Global(self, node): return '' def _is_inside_method_definition(self): - sys.stderr.write("{}\n".format(self._def_stack)) if len(self._def_stack) >= 2: if isinstance(self._def_stack[-2], ClassDefNode): if isinstance(self._def_stack[-1], FunctionDefNode): @@ -190,7 +189,7 @@ def visit_FunctionDef(self, node): # unpack arguments self.writer.write('/* BEGIN unpacking arguments */') - if varargs or varkwargs != '__kwargs' or kwargs: + if varargs or (varkwargs and varkwargs == '__kwargs') or kwargs: self.writer.write('var __args = Array.prototype.slice.call(arguments);') if varkwargs and (varkwargs != '__kwargs' or kwargs): self.writer.write('if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) {') From df3056d7fb40ff7f0608f09ec62787346eaa3f2c Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sat, 7 Dec 2013 00:22:36 +0100 Subject: [PATCH 038/160] pythonium: rework from ... import ... and import ... removed support for __all__ instead all is populated with all module object --- pythonium/pythonium.py | 83 +++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/pythonium/pythonium.py b/pythonium/pythonium.py index 867be30..2d0709d 100644 --- a/pythonium/pythonium.py +++ b/pythonium/pythonium.py @@ -47,7 +47,7 @@ def __init__(self): super().__init__() self.dependencies = [] self._def_stack = [] - self.__all__ = None + self.__all__ = [] self.writer = Writer() self._uuid = -1 @@ -115,6 +115,26 @@ def visit_List(self, node): else: return 'pythonium_call(list)' + def visit_alias(self, node): + out = '' + name = node.name + asname = node.asname + if not asname: + asname = name + path = [] + for module in name.split('.')[:-1]: + path.append(module) + path_to_module = '.'.join(path) + self.writer.write("var {} = typeof({}) == 'undefined' ? {{}} : {}".format(path_to_module, path_to_module, path_to_module)) + path.append(asname.split('.')[-1]) + path = '/'.join(path) + self.writer.write('var {} = require("{}");'.format(asname, path)) + + path = '/'.join(name.split('.')) + self.dependencies.append('/' + path) # relative to project root + + + def visit_ImportFrom(self, node): if len(node.names) > 1: raise NotImplemented @@ -126,16 +146,16 @@ def visit_ImportFrom(self, node): if not asname: asname = name modules = '/'.join(node.module.split('.')) - path = modules + '/' + name + path = modules if node.level == 0: - self.writer.write('var {} = require("{}");'.format(asname, path)) + self.writer.write('var {} = require("{}").{};'.format(asname, path, name)) self.dependencies.append('/' + path) # relative to project root elif node.level == 1: - self.writer.write('var {} = require.toUrl("./{}");'.format(asname, path)) + self.writer.write('var {} = require.toUrl("./{}").{};'.format(asname, path, name)) self.dependencies.append('./' + path) # relative to current file else: path = '../' * node.level + path - self.writer.write('var {} = require.toUrl("{}");'.format(asname, path)) + self.writer.write('var {} = require.toUrl("{}").{};'.format(asname, path, name)) self.dependencies.append(path) # relative to current file return out @@ -155,6 +175,8 @@ def _is_inside_class_definition(self): def visit_FunctionDef(self, node): # 'name', 'args', 'body', 'decorator_list', 'returns' + if len(self._def_stack) == 0: # module level definition must be exported + self.__all__.append(node.name) self._def_stack.append(FunctionDefNode(node.name)) args, kwargs, varargs, varkwargs = self.visit(node.args) @@ -495,9 +517,13 @@ def visit_Delete(self, node): def visit_Assign(self, node): value = self.visit(node.value) + if len(self._def_stack) == 0: # module level definition must be exported + export = True + else: + export = False if len(node.targets) == 1 and not isinstance(node.targets[0], Tuple): - target = node.targets[0] if isinstance(target, Attribute): + target = node.targets[0] self.writer.write('pythonium_set_attribute({}, "{}", {});'.format( self.visit(target.value), target.attr.replace('__DOLLAR__', '$'), @@ -513,6 +539,8 @@ def visit_Assign(self, node): return else: target = self.visit(target) + if export: + self.__all__.append(target) self.writer.write('{} = {};'.format(target, value)) return @@ -520,6 +548,8 @@ def visit_Assign(self, node): for target in node.targets: if isinstance(target, Tuple): targets = map(self.visit, target.elts) + if export: + self.__all__.extends(targets) for index, target in enumerate(targets): self.writer.write('{} = __assignement[{}];\n'.format(target, index)) else: @@ -533,24 +563,13 @@ def visit_Assign(self, node): )) else: target = self.visit(target) - if target == '__all__': - if isinstance(node.value, Name): - self.__all__ = value - elif isinstance(node.value, Str): - self.__all__ = node.value.s - elif isinstance(node.value, List): - if isinstance(node.value.elts[0], Name): - self.__all__ = list(map(self.visit, node.value.elts)) - else: - self.__all__ = list(map(lambda x: x.s, node.value.elts)) - else: - raise NotImplementedError + if self._def_stack and isinstance(self._def_stack[-1], ClassDefNode): + name = '__{}_{}'.format(self._def_stack[-1].name, target) else: - if self._def_stack and isinstance(self._def_stack[-1], ClassDefNode): - name = '__{}_{}'.format(self._def_stack[-1].name, target) - else: - name = target - self.writer.write('{} = __assignement;'.format(name)) + name = target + if export: + self.__all__.extends(name) + self.writer.write('{} = __assignement;'.format(name)) if self._def_stack and isinstance(self._def_stack[-1], ClassDefNode): return target, name @@ -642,6 +661,8 @@ def visit_Lambda(self, node): def visit_ClassDef(self, node): # 'name', 'bases', 'keywords', 'starargs', 'kwargs', 'body', 'decorator_lis't + if len(self._def_stack) == 0: # module level definition must be exported + self.__all__.append(node.name) if len(node.bases) == 0: bases = ['__object'] else: @@ -677,19 +698,15 @@ def pythonium_generate_js(filepath, requirejs=False, root_path=None, output=None with open(os.path.join(dirname, basename)) as f: input = parse(f.read()) tree = parse(input) - python_core = Pythonium() - python_core.visit(tree) - script = python_core.writer.value() + pythonium = Pythonium() + pythonium.visit(tree) + script = pythonium.writer.value() if requirejs: out = 'define(function(require) {\n' out += script - if isinstance(python_core.__all__, str): - out += '\nreturn {};\n'.format(python_core.__all__) - elif python_core.__all__: - public = '{{{}}}'.format(', '.join(map(lambda x: '{}: {}'.format(x[0], x[1]), zip(python_core.__all__, python_core.__all__)))) - out += '\nreturn {};\n'.format(public) - else: - raise Exception('__all__ is not defined!') + all = map(lambda x: "'{}': {}".format(x, x), pythonium.__all__) + all = '{{{}}}'.format(', '.join(all)) + out += 'return {}'.format(all) out += '\n})\n' script = out if deep: From 6eb2ef6b5842c0488eb7d75cb3d53eeddb688015 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sat, 7 Dec 2013 00:41:12 +0100 Subject: [PATCH 039/160] generate runtime.py before the remaining --- pythonium/main.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pythonium/main.py b/pythonium/main.py index 9b4fdd6..9ca6e72 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -32,14 +32,20 @@ def main(argv=None): args = docopt(__doc__, argv, version='pythonium ' + __version__) if args['--generate']: # call ourself for each file in pythonium.lib: - veloce_libfiles = ['runtime.py'] from pythonium import lib + + # runtime is built separatly + # it must appear first in the file + # and it must be built using veloce mode + path = lib.__path__[0] + argv = ['--veloce', os.path.join(path, 'runtime.py')] + main(argv) for path in lib.__path__: for name in os.listdir(path): if name.endswith('.py'): + if name == 'runtime.py': + continue argv = [os.path.join(path, name)] - if name in veloce_libfiles: - argv.insert(0, '--veloce') main(argv) return From 0a372438d1d7ae97aa6fef6a828da091a7809c6f Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sat, 7 Dec 2013 00:44:49 +0100 Subject: [PATCH 040/160] update README.rst --- README.rst | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/README.rst b/README.rst index a888fa4..137a997 100644 --- a/README.rst +++ b/README.rst @@ -7,8 +7,8 @@ Read the `tutorial `_ + You will need Python 3 to run the translator. Refer to your operating system documentation to know how to do it (most Linux distributions have Python 3 readily available). Then you can use pip to install the stable translator: @@ -61,7 +61,7 @@ The above package installs a ``pythonium`` command that has the following option What? (2 minutes) ================= -Pythonium will exist in two flavors, each with their own strengths and performance characteristics. As you go down the list the more features you'll have, and performance will, of course, decrease with sophistication (but not much): +Pythonium exists in two flavors, each with their own strengths and performance characteristics. As you go down the list the more features you'll have, and performance will, of course, decrease with sophistication (but not much): - Pythonium **Veloce** @@ -85,19 +85,6 @@ Also there is `cookbook Date: Sat, 7 Dec 2013 00:51:35 +0100 Subject: [PATCH 041/160] web console: left to right is not right to left --- web-console/howto.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-console/howto.html b/web-console/howto.html index 36907f1..293b82b 100644 --- a/web-console/howto.html +++ b/web-console/howto.html @@ -1,6 +1,6 @@

how-to

-

Start coding in the above panes. They are from right to left, html, css and python code that will be compiled using the mode you choose in the combo box that is in the header.

+

Start coding in the above panes. They are from left to right, html, css and python code that will be compiled using the mode you choose in the combo box that is in the header.

If you leave the page your work will be lost!

From 53db9320990a73bc9e78ff668ac70e3e90727bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Ljunglo=CC=88f?= Date: Sat, 7 Dec 2013 12:33:00 +0100 Subject: [PATCH 042/160] Added comments describing the AST structure, and NotImplemented for missing visit-functions --- pythonium/pythonium.py | 163 ++++++++++++++++++++++++++++++++++++++++- pythonium/veloce.py | 163 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 324 insertions(+), 2 deletions(-) diff --git a/pythonium/pythonium.py b/pythonium/pythonium.py index 2d0709d..ce3fbec 100644 --- a/pythonium/pythonium.py +++ b/pythonium/pythonium.py @@ -60,9 +60,70 @@ def visit(self, node): sys.stderr.write(">>> {} {}\n".format(node.__class__.__name__, node._fields)) return super().visit(node) + ###################################################################### + # mod = Module | Interactive | Expression | Suite + # + # stmt = FunctionDef | ClassDef | Return | Delete | Assign | AugAssign + # | For | While | If | With | Raise | Try | Assert | Import | ImportFrom + # | Global | Nonlocal | Expr | Pass | Break | Continue + # + # expr = BoolOp | BinOp | UnaryOp | Lambda | IfExp | Dict | Set + # | ListComp | SetComp | DictComp | GeneratorExp | Yield | YieldFrom + # | Compare | Call | Num | Str | Bytes | Ellipsis | Attribute + # | Subscript | Starred | Name | List | Tuple + # + # expr_context = Load | Store | Del | AugLoad | AugStore | Param + # + # slice = Slice | ExtSlice | Index + # + # boolop = And | Or + # + # operator = Add | Sub | Mult | Div | Mod | Pow | LShift | RShift + # | BitOr | BitXor | BitAnd | FloorDiv + # + # unaryop = Invert | Not | UAdd | USub + # + # cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn + # + # comprehension = (expr target, expr iter, expr* ifs) + # + # excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body) + # + # arguments = (arg* args, identifier? vararg, expr? varargannotation, + # arg* kwonlyargs, identifier? kwarg, expr? kwargannotation, + # expr* defaults, expr* kw_defaults) + # + # arg = (identifier arg, expr? annotation) + # + # keyword = (identifier arg, expr value) + # + # alias = (identifier name, identifier? asname) + # + # withitem = (expr context_expr, expr? optional_vars) + ###################################################################### + + # Interactive(stmt* body) + visit_Interactive = NotImplemented + + # Expression(expr body) + visit_Expression = NotImplemented + + # Suite(stmt* body) + visit_Suite = NotImplemented + + # expr_context = Load | Store | Del | AugLoad | AugStore | Param + visit_Load = NotImplemented + visit_Store = NotImplemented + visit_Del = NotImplemented + visit_AugLoad = NotImplemented + visit_AugStore = NotImplemented + visit_Param = NotImplemented + + # Pass def visit_Pass(self, node): self.writer.write('/* pass */') + # Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) def visit_Try(self, node): self.writer.write('try {') self.writer.push() @@ -71,10 +132,11 @@ def visit_Try(self, node): self.writer.write('}') list(map(self.visit, node.handlers)) + # Raise(expr? exc, expr? cause) def visit_Raise(self, node): - self.writer.write('throw {};'.format(self.visit(node.exc))) + # ExceptHandler(expr? type, identifier? name, stmt* body) def visit_ExceptHandler(self, node): # 'type', 'name', 'body' if node.type: @@ -92,15 +154,25 @@ def visit_ExceptHandler(self, node): self.writer.pull() self.writer.write('}') + # Yield(expr? value) def visit_Yield(self, node): return 'yield {}'.format(self.visit(node.value)) + + # YieldFrom(expr value) + visit_YieldFrom = NotImplemented + # In def visit_In(self, node): return '__in__' + # NotIn + visit_NotIn = NotImplemented + + # Module(stmt* body) def visit_Module(self, node): list(map(self.visit, node.body)) + # Tuple(expr* elts, expr_context ctx) def visit_Tuple(self, node): args = ', '.join(map(self.visit, node.elts)) if args: @@ -108,6 +180,7 @@ def visit_Tuple(self, node): else: return 'pythonium_call(list)' + # List(expr* elts, expr_context ctx) def visit_List(self, node): args = ', '.join(map(self.visit, node.elts)) if args: @@ -115,6 +188,10 @@ def visit_List(self, node): else: return 'pythonium_call(list)' + # Set(expr* elts) + visit_Set = NotImplemented + + # alias = (identifier name, identifier? asname) def visit_alias(self, node): out = '' name = node.name @@ -133,8 +210,10 @@ def visit_alias(self, node): path = '/'.join(name.split('.')) self.dependencies.append('/' + path) # relative to project root + # Import(alias* names) + visit_Import = NotImplemented - + # ImportFrom(identifier? module, alias* names, int? level) def visit_ImportFrom(self, node): if len(node.names) > 1: raise NotImplemented @@ -159,10 +238,14 @@ def visit_ImportFrom(self, node): self.dependencies.append(path) # relative to current file return out + # Global(identifier* names) def visit_Global(self, node): # handled in visit_FunctionDef return '' + # Nonlocal(identifier* names) + visit_Nonlocal = NotImplemented + def _is_inside_method_definition(self): if len(self._def_stack) >= 2: if isinstance(self._def_stack[-2], ClassDefNode): @@ -173,6 +256,7 @@ def _is_inside_method_definition(self): def _is_inside_class_definition(self): return isinstance(self._def_stack[-1], ClassDefNode) + # FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns) def visit_FunctionDef(self, node): # 'name', 'args', 'body', 'decorator_list', 'returns' if len(self._def_stack) == 0: # module level definition must be exported @@ -289,18 +373,27 @@ def retrieve_vars(body, vars=None): self._def_stack.pop() return node.name, name + # Slice(expr? lower, expr? upper, expr? step) def visit_Slice(self, node): start = self.visit(node.lower) if node.lower else 'undefined' end = self.visit(node.upper) if node.upper else 'undefined' step = self.visit(node.step) if node.step else 'undefined' return 'slice({}, {}, {})'.format(start, step, end) + # Index(expr value) def visit_Index(self, node): return self.visit(node.value) + # ExtSlice(slice* dims) + visit_ExtSlice = NotImplemented + + # Subscript(expr value, slice slice, expr_context ctx) def visit_Subscript(self, node): return "pythonium_call(pythonium_get_attribute({}, '__getitem__'), {})".format(self.visit(node.value), self.visit(node.slice)) + # arguments = (arg* args, identifier? vararg, expr? varargannotation, + # arg* kwonlyargs, identifier? kwarg, expr? kwargannotation, + # expr* defaults, expr* kw_defaults) def visit_arguments(self, node): # 'args', 'vararg', 'varargannotation', 'kwonlyargs', 'kwarg', 'kwargannotation', 'defaults', 'kw_defaults' args = list(map(lambda x: x.arg, node.args)) @@ -311,6 +404,10 @@ def visit_arguments(self, node): kwargs = dict(zip(args[-len(defaults):], defaults)) return args, kwargs, vararg, varkwargs + # arg = (identifier arg, expr? annotation) + visit_arg = NotImplemented + + # Name(identifier id, expr_context ctx) def visit_Name(self, node): if node.id == 'None': return '__NONE' @@ -322,16 +419,19 @@ def visit_Name(self, node): return 'null' return node.id.replace('__DOLLAR__', '$') + # Attribute(expr value, identifier attr, expr_context ctx) def visit_Attribute(self, node): name = self.visit(node.value) attr = node.attr.replace('__DOLLAR__', '$') return 'pythonium_get_attribute({}, "{}")'.format(name, attr) + # keyword = (identifier arg, expr value) def visit_keyword(self, node): if isinstance(node.arg, str): return node.arg, self.visit(node.value) return self.visit(node.arg), self.visit(node.value) + # Call(expr func, expr* args, keyword* keywords, expr? starargs, expr? kwargs) def visit_Call(self, node): name = self.visit(node.func) if name == 'instanceof': @@ -391,6 +491,7 @@ def visit_Call(self, node): args.insert(0, name) return 'pythonium_call({})'.format(', '.join(args)) + # ListComp(expr elt, comprehension* generators) def visit_ListComp(self, node): # 'elt', 'generators' comprehension = '__comp{}__'.format(self.uuid()) @@ -403,6 +504,16 @@ def visit_ListComp(self, node): self.writer.write('}') return comprehension + # SetComp(expr elt, comprehension* generators) + visit_SetComp = NotImplemented + + # DictComp(expr key, expr value, comprehension* generators) + visit_DictComp = NotImplemented + + # GeneratorExp(expr elt, comprehension* generators) + visit_GeneratorExp = NotImplemented + + # comprehension = (expr target, expr iter, expr* ifs) def visit_comprehension(self, node): # 'target', 'iter', 'ifs' iterator = '__iterator{}__'.format(self.uuid()) @@ -414,6 +525,7 @@ def visit_comprehension(self, node): if node.ifs: self.writer.write('if(!{}) {{ continue; }}'.format(' && '.join(map(self.visit, node.ifs)))) + # While(expr test, stmt* body, stmt* orelse) def visit_While(self, node): self.writer.write('while(pythonium_is_true({})) {{'.format(self.visit(node.test))) self.writer.push() @@ -421,16 +533,22 @@ def visit_While(self, node): self.writer.pull() self.writer.write('}') + # AugAssign(expr target, operator op, expr value) def visit_AugAssign(self, node): target = self.visit(node.target) self.writer.write('{} = pythonium_call(pythonium_get_attribute({}, "{}"), {});'.format(target, target, self.visit(node.op), self.visit(node.value))) + # Str(string s) def visit_Str(self, node): s = node.s.replace('\n', '\\n') if '"' in s: return "pythonium_call(str, '{}')".format(s) return 'pythonium_call(str, "{}")'.format(s) + # Bytes(bytes s) + visit_Bytes = NotImplemented + + # BinOp(expr left, operator op, expr right) def visit_BinOp(self, node): left = self.visit(node.left) op = self.visit(node.op) @@ -443,6 +561,8 @@ def visit_Mult(self, node): def visit_Add(self, node): return '__add__' + visit_UAdd = NotImplemented + def visit_Sub(self, node): return '__sub__' @@ -452,6 +572,10 @@ def visit_USub(self, node): def visit_Div(self, node): return '__div__' + visit_FloorDiv = NotImplemented + visit_Pow = NotImplemented + visit_Invert = NotImplemented + def visit_Mod(self, node): return '__mod__' @@ -494,6 +618,7 @@ def visit_Num(self, node): else: return 'pythonium_call(int, {})'.format(str(node.n)) + # Num(object n) def visit_Is(self, node): return '__is__' @@ -503,6 +628,7 @@ def visit_Not(self, node): def visit_IsNot(self, node): return '__isnot__' + # UnaryOp(unaryop op, expr operand) def visit_UnaryOp(self, node): return 'pythonium_call(pythonium_get_attribute({}, "{}"))'.format(self.visit(node.operand), self.visit(node.op)) @@ -512,9 +638,11 @@ def visit_And(self, node): def visit_Or(self, node): return '__or__' + # Delete(expr* targets) def visit_Delete(self, node): raise NotImplementedError + # Assign(expr* targets, expr value) def visit_Assign(self, node): value = self.visit(node.value) if len(self._def_stack) == 0: # module level definition must be exported @@ -573,13 +701,16 @@ def visit_Assign(self, node): if self._def_stack and isinstance(self._def_stack[-1], ClassDefNode): return target, name + # Expr(expr value) def visit_Expr(self, node): self.writer.write(self.visit(node.value) + ';') + # Return(expr? value) def visit_Return(self, node): if node.value: self.writer.write('return {};'.format(self.visit(node.value))) + # Compare(expr left, cmpop* ops, expr* comparators) def visit_Compare(self, node): def merge(a, b, c): if a and b: @@ -596,6 +727,7 @@ def merge(a, b, c): c = '(pythonium_get_attribute({}, "{}")({}))'.format(next(iter), op, c) return c + # BoolOp(boolop op, expr* values) def visit_BoolOp(self, node): op = self.visit(node.op) out = self.visit(node.values[0]) @@ -604,6 +736,10 @@ def visit_BoolOp(self, node): out = 'pythonium_call(pythonium_get_attribute({}, "{}"), {})'.format(v, op, out) return out + # Assert(expr test, expr? msg) + visit_Assert = NotImplemented + + # If(expr test, stmt* body, stmt* orelse) def visit_If(self, node): test = self.visit(node.test) self.writer.write('if (pythonium_is_true({})) {{'.format(test)) @@ -618,6 +754,16 @@ def visit_If(self, node): self.writer.pull() self.writer.write('}') + # IfExp(expr test, expr body, expr orelse) + visit_IfExp = NotImplemented + + # Ellipsis + visit_Ellipsis = NotImplemented + + # Starred(expr value, expr_context ctx) + visit_Starred = NotImplemented + + # Dict(expr* keys, expr* values) def visit_Dict(self, node): keys = [] values = [] @@ -633,6 +779,13 @@ def visit_Dict(self, node): else: return "pythonium_create_dict()" + # With(withitem* items, stmt* body) + visit_With = NotImplemented + + # withitem = (expr context_expr, expr? optional_vars) + visit_withitem = NotImplemented + + # For(expr target, expr iter, stmt* body, stmt* orelse) def visit_For(self, node): # support only arrays target = node.target.id @@ -649,16 +802,21 @@ def visit_For(self, node): self.writer.pull() self.writer.write('} catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }}') + # Continue def visit_Continue(self, node): self.writer.write('continue;') + # Break def visit_Break(self, node): self.writer.write('break;') + # Lambda(arguments args, expr body) def visit_Lambda(self, node): args = ', '.join(map(self.visit, node.args.args)) return '(function ({}) {{{}}})'.format(args, self.visit(node.body)) + # ClassDef(identifier name, expr* bases, keyword* keywords, + # expr? starargs, expr? kwargs, stmt* body, expr* decorator_list) def visit_ClassDef(self, node): # 'name', 'bases', 'keywords', 'starargs', 'kwargs', 'body', 'decorator_lis't if len(self._def_stack) == 0: # module level definition must be exported @@ -686,6 +844,7 @@ def visit_ClassDef(self, node): self.writer.write('});') self._def_stack.pop() + def pythonium_generate_js(filepath, requirejs=False, root_path=None, output=None, deep=None): dirname = os.path.abspath(os.path.dirname(filepath)) if not root_path: diff --git a/pythonium/veloce.py b/pythonium/veloce.py index 880c984..effacc1 100644 --- a/pythonium/veloce.py +++ b/pythonium/veloce.py @@ -54,9 +54,70 @@ def visit(self, node): sys.stderr.write(">>> {} {}\n".format(node.__class__.__name__, node._fields)) return super().visit(node) + ###################################################################### + # mod = Module | Interactive | Expression | Suite + # + # stmt = FunctionDef | ClassDef | Return | Delete | Assign | AugAssign + # | For | While | If | With | Raise | Try | Assert | Import | ImportFrom + # | Global | Nonlocal | Expr | Pass | Break | Continue + # + # expr = BoolOp | BinOp | UnaryOp | Lambda | IfExp | Dict | Set + # | ListComp | SetComp | DictComp | GeneratorExp | Yield | YieldFrom + # | Compare | Call | Num | Str | Bytes | Ellipsis | Attribute + # | Subscript | Starred | Name | List | Tuple + # + # expr_context = Load | Store | Del | AugLoad | AugStore | Param + # + # slice = Slice | ExtSlice | Index + # + # boolop = And | Or + # + # operator = Add | Sub | Mult | Div | Mod | Pow | LShift | RShift + # | BitOr | BitXor | BitAnd | FloorDiv + # + # unaryop = Invert | Not | UAdd | USub + # + # cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn + # + # comprehension = (expr target, expr iter, expr* ifs) + # + # excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body) + # + # arguments = (arg* args, identifier? vararg, expr? varargannotation, + # arg* kwonlyargs, identifier? kwarg, expr? kwargannotation, + # expr* defaults, expr* kw_defaults) + # + # arg = (identifier arg, expr? annotation) + # + # keyword = (identifier arg, expr value) + # + # alias = (identifier name, identifier? asname) + # + # withitem = (expr context_expr, expr? optional_vars) + ###################################################################### + + # Interactive(stmt* body) + visit_Interactive = NotImplemented + + # Expression(expr body) + visit_Expression = NotImplemented + + # Suite(stmt* body) + visit_Suite = NotImplemented + + # expr_context = Load | Store | Del | AugLoad | AugStore | Param + visit_Load = NotImplemented + visit_Store = NotImplemented + visit_Del = NotImplemented + visit_AugLoad = NotImplemented + visit_AugStore = NotImplemented + visit_Param = NotImplemented + + # Pass def visit_Pass(self, node): self.writer.write('/* pass */') + # Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody) def visit_Try(self, node): self.writer.write('try {') self.writer.push() @@ -69,27 +130,50 @@ def visit_Try(self, node): self.writer.pull() self.writer.write('}') + # Raise(expr? exc, expr? cause) def visit_Raise(self, node): self.writer.write('throw {};'.format(self.visit(node.exc))) + # ExceptHandler(expr? type, identifier? name, stmt* body) def visit_ExceptHandler(self, node): list(map(self.visit, node.body)) + # Yield(expr? value) def visit_Yield(self, node): return 'yield {}'.format(self.visit(node.value)) + # YieldFrom(expr value) + visit_YieldFrom = NotImplemented + + # In def visit_In(self, node): return ' in ' + # NotIn + visit_NotIn = NotImplemented + + # Module(stmt* body) def visit_Module(self, node): list(map(self.visit, node.body)) + # Tuple(expr* elts, expr_context ctx) def visit_Tuple(self, node): return '[{}]'.format(', '.join(map(self.visit, node.elts))) + # List(expr* elts, expr_context ctx) def visit_List(self, node): return '[{}]'.format(', '.join(map(self.visit, node.elts))) + # Set(expr* elts) + visit_Set = NotImplemented + + # alias = (identifier name, identifier? asname) + visit_alias = NotImplemented + + # Import(alias* names) + visit_Import = NotImplemented + + # ImportFrom(identifier? module, alias* names, int? level) def visit_ImportFrom(self, node): if len(node.names) > 1: raise NotImplemented @@ -114,10 +198,15 @@ def visit_ImportFrom(self, node): self.dependencies.append(path) # relative to current file return out + # Global(identifier* names) def visit_Global(self, node): # handled in visit_FunctionDef return '' + # Nonlocal(identifier* names) + visit_Nonlocal = NotImplemented + + # FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns) def visit_FunctionDef(self, node): # 'name', 'args', 'body', 'decorator_list', 'returns' self._function_stack.append(node.name) @@ -210,18 +299,27 @@ def retrieve_vars(body, vars=None): self.writer.write('{} = {}({});'.format(node.name, decorator, node.name)) self._function_stack.pop() + # Slice(expr? lower, expr? upper, expr? step) def visit_Slice(self, node): start = self.visit(node.lower) if node.lower else 'undefined' end = self.visit(node.upper) if node.upper else 'undefined' step = self.visit(node.step) if node.step else 'undefined' return 'slice({}, {}, {})'.format(start, step, end) + # Index(expr value) def visit_Index(self, node): return self.visit(node.value) + # ExtSlice(slice* dims) + visit_ExtSlice = NotImplemented + + # Subscript(expr value, slice slice, expr_context ctx) def visit_Subscript(self, node): return '{}[{}]'.format(self.visit(node.value), self.visit(node.slice)) + # arguments = (arg* args, identifier? vararg, expr? varargannotation, + # arg* kwonlyargs, identifier? kwarg, expr? kwargannotation, + # expr* defaults, expr* kw_defaults) def visit_arguments(self, node): # 'args', 'vararg', 'varargannotation', 'kwonlyargs', 'kwarg', 'kwargannotation', 'defaults', 'kw_defaults' args = list(map(lambda x: x.arg, node.args)) @@ -232,6 +330,10 @@ def visit_arguments(self, node): kwargs = dict(zip(args[-len(defaults):], defaults)) return args, kwargs, vararg, varkwargs + # arg = (identifier arg, expr? annotation) + visit_arg = NotImplemented + + # Name(identifier id, expr_context ctx) def visit_Name(self, node): if node.id == 'None': return 'undefined' @@ -245,16 +347,19 @@ def visit_Name(self, node): return 'null' return node.id.replace('__DOLLAR__', '$') + # Attribute(expr value, identifier attr, expr_context ctx) def visit_Attribute(self, node): name = self.visit(node.value) attr = node.attr.replace('__DOLLAR__', '$') return '{}.{}'.format(name, attr) + # keyword = (identifier arg, expr value) def visit_keyword(self, node): if isinstance(node.arg, str): return node.arg, self.visit(node.value) return self.visit(node.arg), self.visit(node.value) + # Call(expr func, expr* args, keyword* keywords, expr? starargs, expr? kwargs) def visit_Call(self, node): name = self.visit(node.func) if name == 'instanceof': @@ -317,6 +422,7 @@ def visit_Call(self, node): args.append(node.kwargs.id) return '{}({})'.format(name, ', '.join(args)) + # ListComp(expr elt, comprehension* generators) def visit_ListComp(self, node): # 'elt', 'generators' comprehension = '__comp{}__'.format(self.uuid()) @@ -329,6 +435,16 @@ def visit_ListComp(self, node): self.writer.write('}') return comprehension + # SetComp(expr elt, comprehension* generators) + visit_SetComp = NotImplemented + + # DictComp(expr key, expr value, comprehension* generators) + visit_DictComp = NotImplemented + + # GeneratorExp(expr elt, comprehension* generators) + visit_GeneratorExp = NotImplemented + + # comprehension = (expr target, expr iter, expr* ifs) def visit_comprehension(self, node): # 'target', 'iter', 'ifs' iterator = '__iterator{}__'.format(self.uuid()) @@ -340,6 +456,7 @@ def visit_comprehension(self, node): if node.ifs: self.writer.write('if(!{}) {{ continue; }}'.format(' && '.join(map(self.visit, node.ifs)))) + # While(expr test, stmt* body, stmt* orelse) def visit_While(self, node): self.writer.write('while({}) {{'.format(self.visit(node.test))) self.writer.push() @@ -347,16 +464,22 @@ def visit_While(self, node): self.writer.pull() self.writer.write('}') + # AugAssign(expr target, operator op, expr value) def visit_AugAssign(self, node): target = self.visit(node.target) self.writer.write('{} = {} {} {};'.format(target, target, self.visit(node.op), self.visit(node.value))) + # Str(string s) def visit_Str(self, node): s = node.s.replace('\n', '\\n') if '"' in s: return "'{}'".format(s) return '"{}"'.format(s) + # Bytes(bytes s) + visit_Bytes = NotImplemented + + # BinOp(expr left, operator op, expr right) def visit_BinOp(self, node): left = self.visit(node.left) op = self.visit(node.op) @@ -369,6 +492,8 @@ def visit_Mult(self, node): def visit_Add(self, node): return '+' + visit_UAdd = NotImplemented + def visit_Sub(self, node): return '-' @@ -378,6 +503,10 @@ def visit_USub(self, node): def visit_Div(self, node): return '/' + visit_FloorDiv = NotImplemented + visit_Pow = NotImplemented + visit_Invert = NotImplemented + def visit_Mod(self, node): return '%' @@ -414,6 +543,7 @@ def visit_Eq(self, node): def visit_NotEq(self, node): return '!=' + # Num(object n) def visit_Num(self, node): return str(node.n) @@ -426,6 +556,7 @@ def visit_Not(self, node): def visit_IsNot(self, node): return '!==' + # UnaryOp(unaryop op, expr operand) def visit_UnaryOp(self, node): return self.visit(node.op) + self.visit(node.operand) @@ -435,11 +566,13 @@ def visit_And(self, node): def visit_Or(self, node): return '||' + # Delete(expr* targets) def visit_Delete(self, node): for target in node.targets: target = self.visit(target) self.writer.write('delete {};'.format(target)) + # Assign(expr* targets, expr value) def visit_Assign(self, node): value = self.visit(node.value) if len(node.targets) == 1 and not isinstance(node.targets[0], Tuple): @@ -472,13 +605,16 @@ def visit_Assign(self, node): else: self.writer.write('{} = __assignement;'.format(target)) + # Expr(expr value) def visit_Expr(self, node): self.writer.write(self.visit(node.value) + ';') + # Return(expr? value) def visit_Return(self, node): if node.value: self.writer.write('return {};'.format(self.visit(node.value))) + # Compare(expr left, cmpop* ops, expr* comparators) def visit_Compare(self, node): def merge(a, b, c): if a and b: @@ -495,10 +631,15 @@ def merge(a, b, c): c = '({} {} {})'.format(next(iter), op, c) return c + # BoolOp(boolop op, expr* values) def visit_BoolOp(self, node): op = self.visit(node.op) return '({})'.format(op.join([self.visit(v) for v in node.values])) + # Assert(expr test, expr? msg) + visit_Assert = NotImplemented + + # If(expr test, stmt* body, stmt* orelse) def visit_If(self, node): test = self.visit(node.test) self.writer.write('if({}) {{'.format(test)) @@ -513,6 +654,16 @@ def visit_If(self, node): self.writer.pull() self.writer.write('}') + # IfExp(expr test, expr body, expr orelse) + visit_IfExp = NotImplemented + + # Ellipsis + visit_Ellipsis = NotImplemented + + # Starred(expr value, expr_context ctx) + visit_Starred = NotImplemented + + # Dict(expr* keys, expr* values) def visit_Dict(self, node): a = [] for i in range(len(node.keys)): @@ -522,6 +673,13 @@ def visit_Dict(self, node): b = ','.join(a) return '{{{}}}'.format(b) + # With(withitem* items, stmt* body) + visit_With = NotImplemented + + # withitem = (expr context_expr, expr? optional_vars) + visit_withitem = NotImplemented + + # For(expr target, expr iter, stmt* body, stmt* orelse) def visit_For(self, node): # support only arrays target = node.target.id @@ -537,16 +695,21 @@ def visit_For(self, node): self.writer.pull() self.writer.write('}') + # Continue def visit_Continue(self, node): self.writer.write('continue;') + # Break def visit_Break(self, node): self.writer.write('break;') + # Lambda(arguments args, expr body) def visit_Lambda(self, node): args = ', '.join(map(self.visit, node.args.args)) return '(function ({}) {{{}}})'.format(args, self.visit(node.body)) + # ClassDef(identifier name, expr* bases, keyword* keywords, + # expr? starargs, expr? kwargs, stmt* body, expr* decorator_list) def visit_ClassDef(self, node): # 'name', 'bases', 'keywords', 'starargs', 'kwargs', 'body', 'decorator_lis't if len(node.bases) > 1: From c6f9d11a73dba8d9daf7ff9f2cbdf868c47b62e2 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 11:45:24 +0100 Subject: [PATCH 043/160] added a README in monkey-tests --- monkey-tests/README.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 monkey-tests/README.rst diff --git a/monkey-tests/README.rst b/monkey-tests/README.rst new file mode 100644 index 0000000..fd7ee5d --- /dev/null +++ b/monkey-tests/README.rst @@ -0,0 +1 @@ +Edit ``test.py`` and run ``make`` to test the program with nodejs. From c9272d1ae6ee2305c74df1609348261c2b62ea32 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 11:58:31 +0100 Subject: [PATCH 044/160] compliant: some fixes in builtins, repr, hash, jstype especially dict --- pythonium/lib/bool.py | 12 +++++++++ pythonium/lib/builtins.py | 26 +++++++++++++++++--- pythonium/lib/dict.py | 49 ++++++++++++++++++++++++++----------- pythonium/lib/exceptions.py | 12 +++++++++ pythonium/lib/float.py | 3 +++ pythonium/lib/int.py | 6 +++++ pythonium/lib/list.py | 34 ++++++++++++------------- pythonium/lib/runtime.py | 20 ++++++++++++++- pythonium/lib/str.py | 15 +++++++++++- pythonium/pythonium.py | 6 ++--- 10 files changed, 141 insertions(+), 42 deletions(-) diff --git a/pythonium/lib/bool.py b/pythonium/lib/bool.py index 58d1625..f7c2c41 100644 --- a/pythonium/lib/bool.py +++ b/pythonium/lib/bool.py @@ -3,6 +3,12 @@ class _True: def __init__(self): self.jsobject = JS('true') + def __jstype__(self): + return self.jsobject + + def __repr__(self): + return "True" + def __and__(self, other): if JS('other === self'): return True @@ -25,6 +31,12 @@ class _False: def __init__(self): self.jsobject = JS('false') + def __jstype__(self): + return self.jsobject + + def __repr__(self): + return "False" + def __and__(self, other): return False diff --git a/pythonium/lib/builtins.py b/pythonium/lib/builtins.py index 2638a91..42a0beb 100644 --- a/pythonium/lib/builtins.py +++ b/pythonium/lib/builtins.py @@ -20,8 +20,9 @@ def print(*args): out = list() for arg in args: r = repr(arg) # returns a str object - out.append(r.jsobject) - console.log.apply(console, out.jsobject) + out.append(jstype(r)) + out = jstype(out) + JS('console.log.apply(console, out)') def map(func, objects): @@ -31,5 +32,22 @@ def map(func, objects): return out def jstype(obj): - # XXX: fallback to __jstype__ method when it doesn't exist - return obj.jsobject + return obj.__jstype__() + + +def hash(obj): + return obj.__hash__() + +def iter(obj): + return obj.__iter__() + + +def next(obj): + return obj.__next__() + + +def len(obj): + return obj.__len__() + + + diff --git a/pythonium/lib/dict.py b/pythonium/lib/dict.py index d448e2b..5892930 100644 --- a/pythonium/lib/dict.py +++ b/pythonium/lib/dict.py @@ -1,34 +1,55 @@ class dict: - # only support str, int, float as keys - def __init__(self, jsobject): - self.jsobject = jsobject + def __init__(self, jsobject=None): + # Since JavaScript objects can only have string as keys + # storing the original object keys is needed + # to be able to answer the ``dict.keys`` and other methods + if jsobject: + self.keys = map(str, list(Object.keys(self.jsobject))) + self.jsobject = JSObject() + else: + self.keys = list() + self.jsobject = JSObject() + + def __hash__(self): + raise TypeError("unhashable type: 'dict'") + + def __jstype__(self): + raise NotImplementedError def __repr__(self): out = [] for key in self.keys(): key_repr = repr(key) - value_repr = repr(self.get(key)) + value_repr = repr(self[key]) out.append(key_repr + ': ' + value_repr) return "{" + ", ".join(out) + "}" def get(self, key, d=None): - jsobject = self.jsobject - key = key.jsobject - attr = JS('jsobject[key]') - if None is not attr: - return attr - else: - return d + if key in self.keys: + h = jstype(hash(key)) + jsobject = self.jsobject + return JS('jsobject[h]') + return d + + def __getitem__(self, key): + if key in self.keys: + h = jstype(hash(key)) + jsobject = self.jsobject + return JS('jsobject[h]') + raise KeyError(key) def __setitem__(self, key, value): - self.jsobject[key] = value + h = jstype(hash(key)) + jsobject = self.jsobject + JS('jsobject[h] = value') + self.keys.append(key) def keys(self): - return map(str, list(Object.keys(self.jsobject))) + return self.keys def items(self): out = list() for key in self.keys(): - out.append([key, self.get(key)]) + out.append([key, self[key]]) return out diff --git a/pythonium/lib/exceptions.py b/pythonium/lib/exceptions.py index 4b35c30..b1fe942 100644 --- a/pythonium/lib/exceptions.py +++ b/pythonium/lib/exceptions.py @@ -10,3 +10,15 @@ class TypeError(Exception): class AttributeError(Exception): pass + + +class KeyError(Exception): + pass + + +class StopIteration(Exception): + pass + + +class NotImplementedError(Exception): + pass diff --git a/pythonium/lib/float.py b/pythonium/lib/float.py index eb7d298..ea3fe10 100644 --- a/pythonium/lib/float.py +++ b/pythonium/lib/float.py @@ -3,6 +3,9 @@ class float: def __init__(self, jsobject): self.jsobject = jsobject + def __hash__(self): + return str(self.jsobject) + def __repr__(self): return self diff --git a/pythonium/lib/int.py b/pythonium/lib/int.py index 2b09bd9..302e559 100644 --- a/pythonium/lib/int.py +++ b/pythonium/lib/int.py @@ -3,6 +3,12 @@ class int: def __init__(self, jsobject): self.jsobject = jsobject + def __hash__(self): + return str(self.jsobject) + + def __jstype__(self): + return self.jsobject + def __repr__(self): return self diff --git a/pythonium/lib/list.py b/pythonium/lib/list.py index f2428d2..05438e3 100644 --- a/pythonium/lib/list.py +++ b/pythonium/lib/list.py @@ -1,19 +1,3 @@ -class StopIteration: - pass - - -def iter(obj): - return obj.__iter__() - - -def next(obj): - return obj.__next__() - - -def len(obj): - return obj.__len__() - - class ListIterator: def __init__(self, obj): @@ -36,9 +20,14 @@ def __init__(self, jsobject=None): else: self.jsobject = JSArray() + def __hash__(self): + raise TypeError("unhashable type: 'list'") + def __repr__(self): - s = "[" + ", ".join(self) + "]" - return s + return "[" + ", ".join(map(repr, self)) + "]" + + def __jstype__(self): + return NotImplementedError def append(self, item): jsobject = self.jsobject @@ -54,7 +43,7 @@ def __setitem__(self, index, value): def __getitem__(self, s): jsobject = self.jsobject - index = s.jsobject + index = jstype(s) return JS('jsobject[index]') def __len__(self): @@ -64,3 +53,10 @@ def __len__(self): def __iter__(self): return ListIterator(self) + + def __contains__(self, obj): + for item in self: + if obj == item: + return True + return False + diff --git a/pythonium/lib/runtime.py b/pythonium/lib/runtime.py index 32d88aa..1628053 100644 --- a/pythonium/lib/runtime.py +++ b/pythonium/lib/runtime.py @@ -6,7 +6,7 @@ __object.__metaclass__ = __type -__ARGUMENTS_PADDING__ = {ARGUMENTS_PADDING:"YES IT IS!"} +__ARGUMENTS_PADDING__ = {ARGUMENTS_PADDING: "YES IT IS!"} def __isnot__(self, other): @@ -15,6 +15,23 @@ def __isnot__(self, other): __object.__isnot__ = __isnot__ +def __hash__(me): + uid = lookup(me, 'uid') + if not uid: + uid = __object._uid + __object._uid += 1 + self.__uid__ = uid + return pythonium_call(str, '{' + uid) +__object._uid = 1 +__object.__hash__ = __hash__ + + +def __rcontains__(me, other): + contains = lookup(other, '__contains__') + return contains(me) +__object.__rcontains__ = __rcontains__; + + def issubclass(klass, other): if klass is other: return True @@ -168,6 +185,7 @@ def pythonium_object_get_attribute(object, attr): if getattr: return getattr(attr) else: + console.trace(object, attr) raise AttributeError __object.__getattribute__ = pythonium_object_get_attribute diff --git a/pythonium/lib/str.py b/pythonium/lib/str.py index b5e9174..5df2d15 100644 --- a/pythonium/lib/str.py +++ b/pythonium/lib/str.py @@ -4,7 +4,20 @@ def __init__(self, jsobject): self.jsobject = jsobject def __repr__(self): - return self + if "'" in self: + return '"' + self + '"' + return "'" + self + "'" + + def __jstype__(self): + return self.jsobject + + def __hash__(self): + return '"' + self + + def __contains__(self, s): + if int(self.jsobject.indexOf(jstype(s))) != -1: + return True + return False def join(self, objects): L = len(objects) diff --git a/pythonium/pythonium.py b/pythonium/pythonium.py index 2d0709d..9eff8dd 100644 --- a/pythonium/pythonium.py +++ b/pythonium/pythonium.py @@ -96,7 +96,7 @@ def visit_Yield(self, node): return 'yield {}'.format(self.visit(node.value)) def visit_In(self, node): - return '__in__' + return '__rcontains__' def visit_Module(self, node): list(map(self.visit, node.body)) @@ -246,7 +246,7 @@ def visit_FunctionDef(self, node): self.writer.write('if (varkwargs_start) {{ {}.splice(varkwargs_start - {}) }}'.format(varargs, len(args))) self.writer.write('{} = pythonium_call(list, {});'.format(varargs, varargs)) if varkwargs and varkwargs != '__kwargs': - self.writer.write('{} = pythonium_call(dict, {});'.format(varkwargs, varkwargs)) + self.writer.write('{} = pythonium_call(dict, __ARGUMENTS_PADDING__, {});'.format(varkwargs, varkwargs)) self.writer.write('/* END unpacking arguments */') # check for variable creation use var if not global @@ -522,8 +522,8 @@ def visit_Assign(self, node): else: export = False if len(node.targets) == 1 and not isinstance(node.targets[0], Tuple): + target = node.targets[0] if isinstance(target, Attribute): - target = node.targets[0] self.writer.write('pythonium_set_attribute({}, "{}", {});'.format( self.visit(target.value), target.attr.replace('__DOLLAR__', '$'), From 25b97664ffbdbed2892370502b2580d0fec57daf Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 12:01:00 +0100 Subject: [PATCH 045/160] compliant: rename ``JS`` function to ``jscode`` ``JS`` is not explicit at least ``jscode`` is more explicit --- pythonium/pythonium.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pythonium/pythonium.py b/pythonium/pythonium.py index 9eff8dd..f4ff568 100644 --- a/pythonium/pythonium.py +++ b/pythonium/pythonium.py @@ -129,12 +129,9 @@ def visit_alias(self, node): path.append(asname.split('.')[-1]) path = '/'.join(path) self.writer.write('var {} = require("{}");'.format(asname, path)) - path = '/'.join(name.split('.')) self.dependencies.append('/' + path) # relative to project root - - def visit_ImportFrom(self, node): if len(node.names) > 1: raise NotImplemented @@ -366,7 +363,7 @@ def visit_Call(self, node): else: out = '' return '[{}]'.format(out) - elif name == 'JS': + elif name == 'jscode': return node.args[0].s else: if node.args: From 171c68159f67b044f787a07eb48c441f3433ca14 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 12:02:42 +0100 Subject: [PATCH 046/160] add monky-tests/test.py to .gitignore so that it's never updated again --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5d36792..b6ea0d4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ tmp/ core/tmp/ pystone/build/ web-console/settings.py +monkey-tests/test.py # C extensions *.so From 068f3e90133603466a0ac8bab8dea08ad8d83a89 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 12:25:23 +0100 Subject: [PATCH 047/160] removed monkey-tests/test.py --- monkey-tests/test.py | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/monkey-tests/test.py b/monkey-tests/test.py index 18d2cc5..6e7034d 100644 --- a/monkey-tests/test.py +++ b/monkey-tests/test.py @@ -1,20 +1 @@ -def range(a, b=None): - if b: - index = a - end = b - else: - index = 0 - end = a - out = list() - print(index, end) - while index < end: - print('ok') - out.append(index) - index += 1 - return out - -LOOPS = range(0) - -print(LOOPS.jsobject) -for i in LOOPS: - print(i.jsobject) +console.log(new(Date)(1, 2, 3)) From a423709102338b084d669075b0ffa439beb0abfa Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 12:25:55 +0100 Subject: [PATCH 048/160] compliant: ``new`` has new syntax ``new`` now takes only one argument, the constructor that must be called. The arguments of the constructor are passed in another call. For instance:: new(Date)(1, 2, 3) This looks better than the old syntax. Also the constructor arguments in this case ``1, 2, 3`` are run through Veloce, it means that it will call the constructor with JavaScript types. If it's not what you meant you can use the following trick:: a = 1 b = 2 c = 3 new(Date)(a, b, c) In the above example a, b and c are Python types. Also since Veloce know nothing about Pythonium compliant OO system. If you want to pass attributes to the constructor you need to do it outside of the call statment:: a = some_object.method() b = some_other_object.property c = jscode('3') new(Date)(a, b, c) --- pythonium/pythonium.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/pythonium/pythonium.py b/pythonium/pythonium.py index f4ff568..69d0cba 100644 --- a/pythonium/pythonium.py +++ b/pythonium/pythonium.py @@ -16,7 +16,7 @@ from ast import NodeVisitor from .utils import YieldSearch - +from .veloce import Veloce ClassDefNode = namedtuple('ClassDef', 'name') FunctionDefNode = namedtuple('FunctionDef', 'name') @@ -354,8 +354,7 @@ def visit_Call(self, node): elif name == 'new': args = list(map(self.visit, node.args)) object = args[0] - args = ', '.join(args[1:]) - return 'new {}({})'.format(object, args) + return 'new {}'.format(object, args) elif name == 'JSArray': if node.args: args = map(self.visit, node.args) @@ -366,6 +365,22 @@ def visit_Call(self, node): elif name == 'jscode': return node.args[0].s else: + # is it a call to new? + try: + if node.func.func.id == 'new': + # Do not convert arguments to Python + if node.args: + veloce = Veloce() + args = [veloce.visit(e) for e in node.args] + args = [e for e in args if e] + else: + args = [] + # use native call since constructors don't have apply method + return '{}({})'.format(name, ', '.join(args)) + except AttributeError: + # it is not + pass + if node.args: args = [self.visit(e) for e in node.args] args = [e for e in args if e] From 53eaa924a66c1b2920cc533c3c869ff5ea6719c3 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 12:34:28 +0100 Subject: [PATCH 049/160] replace JS call by jscode calls --- pythonium/lib/bool.py | 12 ++++++------ pythonium/lib/builtins.py | 2 +- pythonium/lib/dict.py | 6 +++--- pythonium/lib/float.py | 6 +++--- pythonium/lib/int.py | 18 +++++++++--------- pythonium/lib/list.py | 8 ++++---- pythonium/lib/none.py | 2 +- pythonium/lib/runtime.py | 2 +- pythonium/lib/str.py | 12 ++++++------ 9 files changed, 34 insertions(+), 34 deletions(-) diff --git a/pythonium/lib/bool.py b/pythonium/lib/bool.py index f7c2c41..eb4d99b 100644 --- a/pythonium/lib/bool.py +++ b/pythonium/lib/bool.py @@ -1,7 +1,7 @@ class _True: def __init__(self): - self.jsobject = JS('true') + self.jsobject = jscode('true') def __jstype__(self): return self.jsobject @@ -10,7 +10,7 @@ def __repr__(self): return "True" def __and__(self, other): - if JS('other === self'): + if jscode('other === self'): return True return False @@ -18,7 +18,7 @@ def __or__(self, other): return True def __is__(self, other): - if JS('other === self'): + if jscode('other === self'): return True return False @@ -29,7 +29,7 @@ def __neg__(self): class _False: def __init__(self): - self.jsobject = JS('false') + self.jsobject = jscode('false') def __jstype__(self): return self.jsobject @@ -41,12 +41,12 @@ def __and__(self, other): return False def __or__(self, other): - if JS('other === True'): + if jscode('other === True'): return True return False def __is__(self, other): - if JS('other === self'): + if jscode('other === self'): return True return False diff --git a/pythonium/lib/builtins.py b/pythonium/lib/builtins.py index 42a0beb..1f17152 100644 --- a/pythonium/lib/builtins.py +++ b/pythonium/lib/builtins.py @@ -22,7 +22,7 @@ def print(*args): r = repr(arg) # returns a str object out.append(jstype(r)) out = jstype(out) - JS('console.log.apply(console, out)') + jscode('console.log.apply(console, out)') def map(func, objects): diff --git a/pythonium/lib/dict.py b/pythonium/lib/dict.py index 5892930..ab267cb 100644 --- a/pythonium/lib/dict.py +++ b/pythonium/lib/dict.py @@ -29,20 +29,20 @@ def get(self, key, d=None): if key in self.keys: h = jstype(hash(key)) jsobject = self.jsobject - return JS('jsobject[h]') + return jscode('jsobject[h]') return d def __getitem__(self, key): if key in self.keys: h = jstype(hash(key)) jsobject = self.jsobject - return JS('jsobject[h]') + return jscode('jsobject[h]') raise KeyError(key) def __setitem__(self, key, value): h = jstype(hash(key)) jsobject = self.jsobject - JS('jsobject[h] = value') + jscode('jsobject[h] = value') self.keys.append(key) def keys(self): diff --git a/pythonium/lib/float.py b/pythonium/lib/float.py index ea3fe10..2cffe74 100644 --- a/pythonium/lib/float.py +++ b/pythonium/lib/float.py @@ -12,16 +12,16 @@ def __repr__(self): def __div__(self, other): a = self.jsobject b = other.jsobject - return float(JS('a / b')) + return float(jscode('a / b')) def __sub__(self, other): a = self.jsobject b = other.jsobject - return float(JS('a - b')) + return float(jscode('a - b')) def __eq__(self, other): a = self.jsobject b = other.jsobject - if JS('a == b'): + if jscode('a == b'): return True return False diff --git a/pythonium/lib/int.py b/pythonium/lib/int.py index 302e559..4a30bc4 100644 --- a/pythonium/lib/int.py +++ b/pythonium/lib/int.py @@ -15,51 +15,51 @@ def __repr__(self): def __add__(self, other): a = self.jsobject b = other.jsobject - return int(JS('a + b')) + return int(jscode('a + b')) def __sub__(self, other): a = self.jsobject b = other.jsobject - return int(JS('a - b')) + return int(jscode('a - b')) def __lt__(self, other): a = self.jsobject b = other.jsobject - if JS('a < b'): + if jscode('a < b'): return True return False def __lte__(self, other): a = self.jsobject b = other.jsobject - if JS('a <= b'): + if jscode('a <= b'): return True return False def __mul__(self, other): a = self.jsobject b = other.jsobject - c = JS('a * b') + c = jscode('a * b') return int(c) def __or__(self, other): a = self.jsobject b = other.jsobject - c = JS('a || b') + c = jscode('a || b') return int(c) def __eq__(self, other): a = self.jsobject b = other.jsobject - if JS('a == b'): + if jscode('a == b'): return True return False def __neg__(self): jsobject = self.jsobject - return int(JS('-jsobject')) + return int(jscode('-jsobject')) def __div__(self, other): a = self.jsobject b = other.jsobject - return int(JS('a / b')) + return int(jscode('a / b')) diff --git a/pythonium/lib/list.py b/pythonium/lib/list.py index 05438e3..e83d8cc 100644 --- a/pythonium/lib/list.py +++ b/pythonium/lib/list.py @@ -31,7 +31,7 @@ def __jstype__(self): def append(self, item): jsobject = self.jsobject - JS('jsobject.push(item)') + jscode('jsobject.push(item)') def insert(self, index, item): self.jsobject.splice(index, 0, item) @@ -39,16 +39,16 @@ def insert(self, index, item): def __setitem__(self, index, value): jsobject = self.jsobject index = index.jsobject - JS('jsobject[index] = value') + jscode('jsobject[index] = value') def __getitem__(self, s): jsobject = self.jsobject index = jstype(s) - return JS('jsobject[index]') + return jscode('jsobject[index]') def __len__(self): jsobject = self.jsobject - length = JS('jsobject.length') + length = jscode('jsobject.length') return int(length) def __iter__(self): diff --git a/pythonium/lib/none.py b/pythonium/lib/none.py index 9ecabd4..11ad491 100644 --- a/pythonium/lib/none.py +++ b/pythonium/lib/none.py @@ -11,7 +11,7 @@ def __or__(self, other): return False def __is__(self, other): - if JS('other === self'): + if jscode('other === self'): return True return False diff --git a/pythonium/lib/runtime.py b/pythonium/lib/runtime.py index 1628053..7c2ebd4 100644 --- a/pythonium/lib/runtime.py +++ b/pythonium/lib/runtime.py @@ -58,7 +58,7 @@ def pythonium_create_dict(keys, values): def pythonium_is_true(v): if v is __FALSE or v is False: return False - if v is __TRUE or (JS('v !== undefined') and v != __NONE): + if v is __TRUE or (jscode('v !== undefined') and v != __NONE): return True if isinstance(v, int): if pythonium_get_attribute(v, 'jsobject') == 0: diff --git a/pythonium/lib/str.py b/pythonium/lib/str.py index 5df2d15..4b915f1 100644 --- a/pythonium/lib/str.py +++ b/pythonium/lib/str.py @@ -34,40 +34,40 @@ def join(self, objects): def __add__(self, other): a = self.jsobject b = other.jsobject - return str(JS('a + b')) + return str(jscode('a + b')) def __lte__(self, other): a = self.jsobject b = other.jsobject - if JS('a <= b'): + if jscode('a <= b'): return True return False def __gte__(self, other): a = self.jsobject b = other.jsobject - if JS('a >= b'): + if jscode('a >= b'): return True return False def __gt__(self, other): a = self.jsobject b = other.jsobject - if JS('a > b'): + if jscode('a > b'): return True return False def __eq__(self, other): a = self.jsobject b = other.jsobject - if JS('a == b'): + if jscode('a == b'): return True return False def __getitem__(self, index): jsobject = self.jsobject index = index.jsobject - c = JS('jsobject[index]') + c = jscode('jsobject[index]') return str(c) def __neq__(self, other): From 116e34c336f726bb605878c9ebc44cfe54ddd00f Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 12:49:18 +0100 Subject: [PATCH 050/160] removed monkey-tests/test.py --- monkey-tests/test.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 monkey-tests/test.py diff --git a/monkey-tests/test.py b/monkey-tests/test.py deleted file mode 100644 index 6e7034d..0000000 --- a/monkey-tests/test.py +++ /dev/null @@ -1 +0,0 @@ -console.log(new(Date)(1, 2, 3)) From e776874b6426293a250d108cf6408e7a7abf4531 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 12:49:35 +0100 Subject: [PATCH 051/160] monkey-tests: add a veloce rule in Makefile --- monkey-tests/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/monkey-tests/Makefile b/monkey-tests/Makefile index e10635c..9af5e6d 100644 --- a/monkey-tests/Makefile +++ b/monkey-tests/Makefile @@ -7,4 +7,8 @@ all: build build: mkdir build +veloce: + pythonium -V test.py > build/test.py.js + nodejs --harmony build/test.py.js + From cb683f40fee18343137a527ab8808dfbc344ec24 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 12:59:13 +0100 Subject: [PATCH 052/160] 0.5.0 version bump --- pythonium/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonium/main.py b/pythonium/main.py index 9ca6e72..54963a3 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -25,7 +25,7 @@ from .veloce import veloce_generate_js from .pythonium import pythonium_generate_js -__version__ = '0.4.7' +__version__ = '0.5.0' def main(argv=None): From 158d6401f15aa4a4f511b10fc33f8bce941badca Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 13:05:59 +0100 Subject: [PATCH 053/160] added CHANGELOG file --- CHANGELOG | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 CHANGELOG diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..0968067 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,8 @@ +0.5.0 + - Web Console available online @ http://hypermove.net/pythonium-web-console/ + - Fix runtests.py: avoid envoy, made it work on Windows (Peter Ljunglöf) + - Clean up main function (Peter Ljunglöf) + - Fixed namespaced method definitions. Previously defining a method FOO would override any previous definition of function FOO. + - Rework from ... import ... and import ... + - Renamed ``JS`` function to ``jscode`` + - ``new`` function as a new syntax ``new(Date)(1, 2, 3)`` cf. https://github.com/pythonium/pythonium/commit/a423709102338b084d669075b0ffa439beb0abfa From 55e3c511bc9d0236016da46f96893a4a09cb0228 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 13:09:59 +0100 Subject: [PATCH 054/160] update CHANGELOG --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 0968067..fc53dce 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,3 +6,6 @@ - Rework from ... import ... and import ... - Renamed ``JS`` function to ``jscode`` - ``new`` function as a new syntax ``new(Date)(1, 2, 3)`` cf. https://github.com/pythonium/pythonium/commit/a423709102338b084d669075b0ffa439beb0abfa + - added ``jstype`` function which returns a javascript objects equivalent to Python object (missing implementation for list and dict) + - ``print`` was defined in ``lib/builtins.py`` and must be used to log Python objects. ``console.log(fuuuu)`` must be used to log JavaScript objects. + - rework ``dict`` so that it works more like CPython one. From b1bfe9fa34f880b8f71781396c1eba0cbf9523bc Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 13:34:02 +0100 Subject: [PATCH 055/160] update CHANGELOG --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index fc53dce..75582c6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,3 +9,4 @@ - added ``jstype`` function which returns a javascript objects equivalent to Python object (missing implementation for list and dict) - ``print`` was defined in ``lib/builtins.py`` and must be used to log Python objects. ``console.log(fuuuu)`` must be used to log JavaScript objects. - rework ``dict`` so that it works more like CPython one. + - fixed a bug where if two functions were nested and the nested function was a generator both functions were dubbed generators From 5e9d1afea95db377fa24a7791cfa70ca2509b3e4 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 13:46:25 +0100 Subject: [PATCH 056/160] veloce: replace JS by jscode --- pythonium/veloce.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonium/veloce.py b/pythonium/veloce.py index effacc1..7c52427 100644 --- a/pythonium/veloce.py +++ b/pythonium/veloce.py @@ -397,7 +397,7 @@ def visit_Call(self, node): else: out = '' return '[{}]'.format(out) - elif name == 'JS': + elif name == 'jscode': return node.args[0].s elif name == 'print': args = [self.visit(e) for e in node.args] From e63154e58a7be6b2e306b573c022af6b47269ef4 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 14:17:19 +0100 Subject: [PATCH 057/160] compliant: add __iter__ to dict to iterate over keys --- pythonium/lib/dict.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pythonium/lib/dict.py b/pythonium/lib/dict.py index ab267cb..c72a736 100644 --- a/pythonium/lib/dict.py +++ b/pythonium/lib/dict.py @@ -32,6 +32,9 @@ def get(self, key, d=None): return jscode('jsobject[h]') return d + def __iter__(self): + return ListIterator(self.keys()) + def __getitem__(self, key): if key in self.keys: h = jstype(hash(key)) From b795ac87d4267c3fdb6ef01289db15358371a50f Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 14:17:53 +0100 Subject: [PATCH 058/160] tests: iterating over a dict is not supported in veloce --- tests/for-loop.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/for-loop.py b/tests/for-loop.py index e7546b9..99c4fc6 100644 --- a/tests/for-loop.py +++ b/tests/for-loop.py @@ -7,9 +7,3 @@ for i in [1,2,3,4,5,6,7,8,9,0]: print(i) -print("# looping over a dict") -d = {'a':1, 'b':2, 'c':3} -for k in d: - print(k, ":", d[k]) - - From b7aa7392360b09ad78489f02f2c252e2c53ccf67 Mon Sep 17 00:00:00 2001 From: Dirk Krause Date: Sun, 8 Dec 2013 14:46:55 +0100 Subject: [PATCH 059/160] Added minimal Three.JS example --- examples/threejs/README.MD | 7 +++++++ examples/threejs/app.js | 32 +++++++++++++++++++++++++++++++ examples/threejs/app.py | 38 +++++++++++++++++++++++++++++++++++++ examples/threejs/index.html | 19 +++++++++++++++++++ 4 files changed, 96 insertions(+) create mode 100644 examples/threejs/README.MD create mode 100644 examples/threejs/app.js create mode 100644 examples/threejs/app.py create mode 100644 examples/threejs/index.html diff --git a/examples/threejs/README.MD b/examples/threejs/README.MD new file mode 100644 index 0000000..8803cb6 --- /dev/null +++ b/examples/threejs/README.MD @@ -0,0 +1,7 @@ +Minimal Three.JS example +======================== + + + pythonium -V app.py -o app.js + + diff --git a/examples/threejs/app.js b/examples/threejs/app.js new file mode 100644 index 0000000..11e47b9 --- /dev/null +++ b/examples/threejs/app.js @@ -0,0 +1,32 @@ +var __assignement = [undefined, undefined, undefined]; +camera = __assignement[0]; +scene = __assignement[1]; +renderer = __assignement[2]; +var __assignement = [undefined, undefined, undefined]; +geometry = __assignement[0]; +material = __assignement[1]; +mesh = __assignement[2]; +var init = function() { + scene = new THREE.Scene(); + camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000); + camera.position.z = 500; + scene.add(camera); + geometry = new THREE.CubeGeometry(200, 200, 200); + material = new THREE.MeshNormalMaterial(); + mesh = new THREE.Mesh(geometry, material); + scene.add(mesh); + renderer = new THREE.CanvasRenderer(); + renderer.setSize(window.innerWidth, window.innerHeight); + document.body.appendChild(renderer.domElement); +}; +var animate = function() { + requestAnimationFrame(animate); + render(); +}; +var render = function() { + mesh.rotation.x = mesh.rotation.x + 0.01; + mesh.rotation.y = mesh.rotation.y + 0.02; + renderer.render(scene, camera); +}; +init(); +animate(); diff --git a/examples/threejs/app.py b/examples/threejs/app.py new file mode 100644 index 0000000..12847ff --- /dev/null +++ b/examples/threejs/app.py @@ -0,0 +1,38 @@ +camera, scene, renderer = None, None, None +geometry, material, mesh = None, None, None + +def init(): + global camera, scene, renderer, geometry, material, mesh + scene = JS('new THREE.Scene()') + + camera = JS('new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000)') + camera.position.z = 500 + scene.add(camera) + + geometry = JS('new THREE.CubeGeometry(200, 200, 200)') + material = JS('new THREE.MeshNormalMaterial()') + + mesh = JS('new THREE.Mesh(geometry, material)') + scene.add(mesh) + + renderer = JS('new THREE.CanvasRenderer()') + renderer.setSize(window.innerWidth, window.innerHeight) + + document.body.appendChild(renderer.domElement); + + +def animate(): + global camera, scene, renderer, geometry, material, mesh + requestAnimationFrame(animate); + render() + +def render(): + global camera, scene, renderer, geometry, material, mesh + mesh.rotation.x += 0.01 + mesh.rotation.y += 0.02 + + renderer.render(scene, camera) + +init() +animate() + diff --git a/examples/threejs/index.html b/examples/threejs/index.html new file mode 100644 index 0000000..3ba23c0 --- /dev/null +++ b/examples/threejs/index.html @@ -0,0 +1,19 @@ + + + + + three.js ~ example ~ Mr.doob + + + + + + + + + + + + + + From 21fd87a1e8adf30366ef07d4bea97f385e9a7e13 Mon Sep 17 00:00:00 2001 From: Dirk Krause Date: Sun, 8 Dec 2013 14:48:32 +0100 Subject: [PATCH 060/160] Delete README.MD --- examples/threejs/README.MD | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 examples/threejs/README.MD diff --git a/examples/threejs/README.MD b/examples/threejs/README.MD deleted file mode 100644 index 8803cb6..0000000 --- a/examples/threejs/README.MD +++ /dev/null @@ -1,7 +0,0 @@ -Minimal Three.JS example -======================== - - - pythonium -V app.py -o app.js - - From dd731a99db19217605d681ebe74eb6478173e21a Mon Sep 17 00:00:00 2001 From: Dirk Krause Date: Sun, 8 Dec 2013 14:50:24 +0100 Subject: [PATCH 061/160] Added readme --- examples/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 examples/README.md diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..8771784 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,8 @@ +Minimal Three.JS example +======================== + +To convert the app.py file to Javascript, enter: + + pythonium -V app.py -o app.js + + From 494e9d0b9685b3ce1411c4a415abc963905fa093 Mon Sep 17 00:00:00 2001 From: Dirk Krause Date: Sun, 8 Dec 2013 14:51:39 +0100 Subject: [PATCH 062/160] Added readme --- examples/threejs/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 examples/threejs/README.md diff --git a/examples/threejs/README.md b/examples/threejs/README.md new file mode 100644 index 0000000..8771784 --- /dev/null +++ b/examples/threejs/README.md @@ -0,0 +1,8 @@ +Minimal Three.JS example +======================== + +To convert the app.py file to Javascript, enter: + + pythonium -V app.py -o app.js + + From f9246094c06fa7c9d3160c0e995e642ce85517f5 Mon Sep 17 00:00:00 2001 From: Dirk Krause Date: Sun, 8 Dec 2013 14:52:23 +0100 Subject: [PATCH 063/160] Delete README.md --- examples/README.md | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 examples/README.md diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 8771784..0000000 --- a/examples/README.md +++ /dev/null @@ -1,8 +0,0 @@ -Minimal Three.JS example -======================== - -To convert the app.py file to Javascript, enter: - - pythonium -V app.py -o app.js - - From ef7034362a4defe02bbfb6b91dc61398f21a6d89 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 17:51:14 +0100 Subject: [PATCH 064/160] UNSTABLE - Make it possible to run tests for compliant mode --- pythonium/lib/bool.py | 2 +- pythonium/lib/builtins.py | 6 +- pythonium/lib/dict.py | 15 ++-- pythonium/lib/int.py | 9 ++ pythonium/lib/list.py | 13 +-- pythonium/lib/runtime.py | 14 +-- pythonium/lib/str.py | 10 ++- pythonium/pythonium.py | 61 +++++++------ runtests.py | 90 ++++++++++++-------- tests/{print.py => compliant-print.py} | 0 tests/unpack-function-parameters.py | 10 --- tests/unpack-function-parameters.py.expected | 5 -- 12 files changed, 122 insertions(+), 113 deletions(-) rename tests/{print.py => compliant-print.py} (100%) delete mode 100644 tests/unpack-function-parameters.py delete mode 100644 tests/unpack-function-parameters.py.expected diff --git a/pythonium/lib/bool.py b/pythonium/lib/bool.py index eb4d99b..d383480 100644 --- a/pythonium/lib/bool.py +++ b/pythonium/lib/bool.py @@ -41,7 +41,7 @@ def __and__(self, other): return False def __or__(self, other): - if jscode('other === True'): + if jscode('other === __TRUE'): return True return False diff --git a/pythonium/lib/builtins.py b/pythonium/lib/builtins.py index 1f17152..89ec480 100644 --- a/pythonium/lib/builtins.py +++ b/pythonium/lib/builtins.py @@ -19,10 +19,8 @@ def repr(obj): def print(*args): out = list() for arg in args: - r = repr(arg) # returns a str object - out.append(jstype(r)) - out = jstype(out) - jscode('console.log.apply(console, out)') + out.append(repr(arg)) + jscode('console.log.apply(console, jstype(out))') def map(func, objects): diff --git a/pythonium/lib/dict.py b/pythonium/lib/dict.py index c72a736..a3b7dbf 100644 --- a/pythonium/lib/dict.py +++ b/pythonium/lib/dict.py @@ -1,15 +1,10 @@ class dict: - def __init__(self, jsobject=None): - # Since JavaScript objects can only have string as keys - # storing the original object keys is needed - # to be able to answer the ``dict.keys`` and other methods - if jsobject: - self.keys = map(str, list(Object.keys(self.jsobject))) - self.jsobject = JSObject() - else: - self.keys = list() - self.jsobject = JSObject() + def __init__(self, **kwargs): + self._keys = list() + self._jsobject = JSObject() + for key in kwargs.keys(): + self[key] = kwargs[key] def __hash__(self): raise TypeError("unhashable type: 'dict'") diff --git a/pythonium/lib/int.py b/pythonium/lib/int.py index 4a30bc4..053cea0 100644 --- a/pythonium/lib/int.py +++ b/pythonium/lib/int.py @@ -3,6 +3,12 @@ class int: def __init__(self, jsobject): self.jsobject = jsobject + def __not__(self): + jsobject = self.jsobject + if jscode('jsobject == 0'): + return True + return False + def __hash__(self): return str(self.jsobject) @@ -55,6 +61,9 @@ def __eq__(self, other): return True return False + def __neq__(self, other): + return not self.__eq__(other) + def __neg__(self): jsobject = self.jsobject return int(jscode('-jsobject')) diff --git a/pythonium/lib/list.py b/pythonium/lib/list.py index e83d8cc..df0c397 100644 --- a/pythonium/lib/list.py +++ b/pythonium/lib/list.py @@ -14,11 +14,8 @@ def __next__(self): class list: - def __init__(self, jsobject=None): - if jsobject: - self.jsobject = jsobject - else: - self.jsobject = JSArray() + def __init__(self): + self.jsobject = JSArray() def __hash__(self): raise TypeError("unhashable type: 'list'") @@ -27,7 +24,11 @@ def __repr__(self): return "[" + ", ".join(map(repr, self)) + "]" def __jstype__(self): - return NotImplementedError + out = JSArray() + for item in self: + item = jstype(item) + jscode('out.push(item)') + return out def append(self, item): jsobject = self.jsobject diff --git a/pythonium/lib/runtime.py b/pythonium/lib/runtime.py index 7c2ebd4..428d538 100644 --- a/pythonium/lib/runtime.py +++ b/pythonium/lib/runtime.py @@ -43,18 +43,6 @@ def issubclass(klass, other): return False -def pythonium_create_dict(keys, values): - out = {} - max = keys.length - index = 0 - while index < max: - key = keys[index].jsobject - value = values[index] - out[key] = value - index += 1 - return pythonium_call(dict, out, None) - - def pythonium_is_true(v): if v is __FALSE or v is False: return False @@ -185,7 +173,7 @@ def pythonium_object_get_attribute(object, attr): if getattr: return getattr(attr) else: - console.trace(object, attr) + console.trace('AttributeError', attr, object) raise AttributeError __object.__getattribute__ = pythonium_object_get_attribute diff --git a/pythonium/lib/str.py b/pythonium/lib/str.py index 4b915f1..7bda752 100644 --- a/pythonium/lib/str.py +++ b/pythonium/lib/str.py @@ -4,9 +4,7 @@ def __init__(self, jsobject): self.jsobject = jsobject def __repr__(self): - if "'" in self: - return '"' + self + '"' - return "'" + self + "'" + return self def __jstype__(self): return self.jsobject @@ -19,6 +17,9 @@ def __contains__(self, s): return True return False + def __iter__(self): + return ListIterator(self) + def join(self, objects): L = len(objects) if not L: @@ -36,6 +37,9 @@ def __add__(self, other): b = other.jsobject return str(jscode('a + b')) + def __len__(self): + return int(self.jsobject.length) + def __lte__(self, other): a = self.jsobject b = other.jsobject diff --git a/pythonium/pythonium.py b/pythonium/pythonium.py index b5e16cf..e5db2f0 100644 --- a/pythonium/pythonium.py +++ b/pythonium/pythonium.py @@ -42,6 +42,13 @@ def value(self): class Pythonium(NodeVisitor): + + @classmethod + def translate(cls, code): + translator = cls() + ast = parse(code) + translator.visit(ast) + return translator.writer.value() def __init__(self): super().__init__() @@ -184,7 +191,9 @@ def visit_Tuple(self, node): def visit_List(self, node): args = ', '.join(map(self.visit, node.elts)) if args: - return 'pythonium_call(list, [{}])'.format(args) + self.writer.write('var __a_list = pythonium_call(list);') + self.writer.write('__a_list.jsobject = [{}];'.format(args)) + return '__a_list' else: return 'pythonium_call(list)' @@ -271,7 +280,6 @@ def visit_FunctionDef(self, node): all_parameters.append(varkwargs) all_parameters = set(all_parameters) - __args = ', '.join(args) if self._is_inside_method_definition(): name = '__{}_{}'.format(self._def_stack[-2].name, node.name) else: @@ -284,6 +292,8 @@ def visit_FunctionDef(self, node): if getattr(searcher, 'has_yield', False): has_yield = True break + + __args = ', '.join(args) if has_yield: self.writer.write('var {} = function*({}) {{'.format(name, __args)) else: @@ -324,10 +334,11 @@ def visit_FunctionDef(self, node): if varkwargs != '__kwargs': self.writer.write('delete {}.{};'.format(varkwargs, keyword)) if varargs: - self.writer.write('var {} = __args.splice({});'.format(varargs, len(args))) + self.writer.write('__args = __args.splice({});'.format(len(args))) if varkwargs and (varkwargs != '__kwargs' or kwargs): - self.writer.write('if (varkwargs_start) {{ {}.splice(varkwargs_start - {}) }}'.format(varargs, len(args))) - self.writer.write('{} = pythonium_call(list, {});'.format(varargs, varargs)) + self.writer.write('if (varkwargs_start) {{ __args.splice(varkwargs_start - {}) }}'.format(len(args))) + self.writer.write('var {} = pythonium_call(list);'.format(varargs)) + self.writer.write('{}.jsobject = __args;'.format(varargs)) if varkwargs and varkwargs != '__kwargs': self.writer.write('{} = pythonium_call(dict, {});'.format(varkwargs, varkwargs)) self.writer.write('/* END unpacking arguments */') @@ -482,28 +493,23 @@ def visit_Call(self, node): except AttributeError: # it is not pass - + + # positional args if node.args: args = [self.visit(e) for e in node.args] args = [e for e in args if e] else: args = [] - if node.keywords and not node.kwargs: - keywords = '__kwargs{}__'.format(self.uuid()) - _ = ', '.join(map(lambda x: '{}: {}'.format(x[0], x[1]), map(self.visit, node.keywords))) - self.writer.write('var {} = {{{}}};'.format(keywords, _)) - args.append('__ARGUMENTS_PADDING__') - args.append(keywords) - elif node.kwargs and not node.keywords: - args.append('__ARGUMENTS_PADDING__') - args.append(node.kwargs.id) - elif node.kwargs and node.keywords: - for key, value in map(self.visit, node.keywords): - self.writer.write('{}.{} = {};'.format(node.kwargs.id, key, value)) - args.append('__ARGUMENTS_PADDING__') - args.append(node.kwargs.id) args.insert(0, name) - return 'pythonium_call({})'.format(', '.join(args)) + call_arguments = 'call_arguments{}'.format(self.uuid()) + self.writer.write('var {} = [{}];'.format(call_arguments, ', '.join(args))) + # variable arguments aka. starargs + if node.starargs: + varargs = self.visit(node.starargs) + code = "for i in {}: jscode('{}.push(i)')".format(varargs, call_arguments) + self.writer.write(self.translate(code)) + # keywords and variable keywords arguments aka. starkwargs + return 'pythonium_call.apply(undefined, {})'.format(call_arguments) # ListComp(expr elt, comprehension* generators) def visit_ListComp(self, node): @@ -637,7 +643,7 @@ def visit_Is(self, node): return '__is__' def visit_Not(self, node): - return '__neg__' + return '__not__' def visit_IsNot(self, node): return '__isnot__' @@ -786,12 +792,13 @@ def visit_Dict(self, node): keys.append(k) v = self.visit(node.values[i]) values.append(v) - keys = "[{}]".format(", ".join(keys)) - values = "[{}]".format(", ".join(values)) if node.keys: - return "pythonium_create_dict({}, {})".format(keys, values) + self.writer.write('var __a_dict = pythonium_call(dict)') + for key, value in zip(keys, values): + self.writer.write('__a_dict.__setitem__(__a_dict, key, value);') + return '__a_dict' else: - return "pythonium_create_dict()" + return 'pythonium_call(dict)' # With(withitem* items, stmt* body) visit_With = NotImplemented @@ -809,7 +816,7 @@ def visit_For(self, node): self.writer.write('var __next__ = pythonium_get_attribute(iter({}), "__next__");'.format(iterator)) self.writer.write('while(true) {') self.writer.push() - self.writer.write('var {} = pythonium_call(__next__);'.format(target)) + self.writer.write('var {} = __next__();'.format(target)) list(map(self.visit, node.body)) self.writer.pull() self.writer.write('}') diff --git a/runtests.py b/runtests.py index 346c3a3..1343704 100755 --- a/runtests.py +++ b/runtests.py @@ -3,9 +3,17 @@ import sys import difflib from traceback import print_exc -from subprocess import check_output, STDOUT, CalledProcessError +from subprocess import PIPE +from subprocess import Popen +from subprocess import STDOUT +from subprocess import check_output +from subprocess import CalledProcessError + + +from pythonium.main import main from pythonium.veloce import veloce_generate_js +from pythonium.pythonium import pythonium_generate_js ROOT = os.path.abspath(os.path.dirname(__file__)) @@ -29,46 +37,60 @@ def compare_output(expected, result): TMPDIR = os.path.join(TESTS_ROOT, 'tmp') try: os.mkdir(TMPDIR) except OSError: pass + - for test in os.listdir(TESTS_ROOT): - if test.endswith('.py'): - test_ctr += 1 - filepath = os.path.join(TESTS_ROOT, test) - exec_script = os.path.join(TMPDIR, test + 'exec.js') - with open(exec_script, 'w') as f: - try: - veloce_generate_js(filepath, output=f) - except Exception as exc: - print_exc() - print('< Translating {} failed with the above exception.'.format(test)) - continue + # XXX: this force to install pythonium before running tests + PYTHONIUMJS = Popen(["pythonium", "--generate"], stdout=PIPE).communicate()[0].decode('utf-8') - try: - result = check_output(['nodejs', exec_script], stderr=STDOUT) - except CalledProcessError as err: - print(err.output.decode(errors='replace')) - print('< {} ERROR :('.format(test)) - continue + for mode in ('veloce', 'compliant'): + print('* running tests for {} mode'.format(mode)) + for test in os.listdir(TESTS_ROOT): + if test.endswith('.py'): + # compliant mode must run any code even code written for veloce mode + # but veloce mode can not run compliant tests + if test.startswith('compliant-') and mode != 'compliant': + continue + test_ctr += 1 + filepath = os.path.join(TESTS_ROOT, test) + exec_script = os.path.join(TMPDIR, test + 'exec.js') + with open(exec_script, 'w') as f: + try: + if mode =='veloce': + veloce_generate_js(filepath, output=f) + else: + f.write(PYTHONIUMJS) + pythonium_generate_js(filepath, output=f) + except Exception as exc: + print_exc() + print('< Translating {} in mode {} failed with the above exception.'.format(test, mode)) + continue - expected_file = os.path.join(TESTS_ROOT, test+'.expected') - if os.path.exists(expected_file): - with open(expected_file, 'br') as f: - expected = f.read() - else: try: - expected = check_output(['python3', filepath], stderr=STDOUT) + result = check_output(['nodejs', exec_script], stderr=STDOUT) except CalledProcessError as err: print(err.output.decode(errors='replace')) - print('< {} PYTHON ERROR :('.format(test)) + print('< {} ERROR in mode {} :('.format(test, mode)) continue - diffs = compare_output(expected, result) - if diffs: - for line in diffs: - print(line) - print('< {} FAILED :('.format(test)) - else: - ok_ctr += 1 - print('< {} PASS :)'.format(test)) + expected_file = os.path.join(TESTS_ROOT, test+'.expected') + if os.path.exists(expected_file): + with open(expected_file, 'br') as f: + expected = f.read() + else: + try: + expected = check_output(['python3', filepath], stderr=STDOUT) + except CalledProcessError as err: + print(err.output.decode(errors='replace')) + print('< {} PYTHON ERROR :('.format(test)) + continue + + diffs = compare_output(expected, result) + if diffs: + for line in diffs: + print(line) + print('< {} FAILED in mode {} :('.format(test, mode)) + else: + ok_ctr += 1 + print('< {} PASS in mode {} :)'.format(test, mode)) print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) diff --git a/tests/print.py b/tests/compliant-print.py similarity index 100% rename from tests/print.py rename to tests/compliant-print.py diff --git a/tests/unpack-function-parameters.py b/tests/unpack-function-parameters.py deleted file mode 100644 index 745d198..0000000 --- a/tests/unpack-function-parameters.py +++ /dev/null @@ -1,10 +0,0 @@ -def func(a, b, c, d=1, f=2, *args, **kwargs): - print(a) - a = 1 - print(a, b, c, d, f) - print(args[0]) - print(args[1]) - print(kwargs) - -kwargs = {"foo": "bar"} -func(42, 43, 44, 45, 46, 100, 102, key="value", **kwargs) diff --git a/tests/unpack-function-parameters.py.expected b/tests/unpack-function-parameters.py.expected deleted file mode 100644 index 4940388..0000000 --- a/tests/unpack-function-parameters.py.expected +++ /dev/null @@ -1,5 +0,0 @@ -42 -1 43 44 45 46 -100 -102 -{ foo: 'bar', key: 'value' } From e12f08e2c0a3767fbfa3d9519508fef2a5580035 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 19:38:56 +0100 Subject: [PATCH 065/160] rework repository layout --- pythonium/{lib => compliant}/__init__.py | 0 pythonium/{pythonium.py => compliant/compliant.py} | 4 ++-- pythonium/compliant/lib/__init__.py | 0 pythonium/{ => compliant}/lib/bool.py | 0 pythonium/{ => compliant}/lib/builtins.py | 0 pythonium/{ => compliant}/lib/dict.py | 0 pythonium/{ => compliant}/lib/exceptions.py | 0 pythonium/{ => compliant}/lib/float.py | 0 pythonium/{ => compliant}/lib/int.py | 0 pythonium/{ => compliant}/lib/iterator.py | 0 pythonium/{ => compliant}/lib/list.py | 0 pythonium/{ => compliant}/lib/none.py | 0 pythonium/{ => compliant}/lib/runtime.py | 0 pythonium/{ => compliant}/lib/slice.py | 0 pythonium/{ => compliant}/lib/str.py | 0 pythonium/main.py | 6 +++--- pythonium/veloce/__init__.py | 0 pythonium/{ => veloce}/veloce.py | 2 +- setup.py | 2 +- 19 files changed, 7 insertions(+), 7 deletions(-) rename pythonium/{lib => compliant}/__init__.py (100%) rename pythonium/{pythonium.py => compliant/compliant.py} (99%) create mode 100644 pythonium/compliant/lib/__init__.py rename pythonium/{ => compliant}/lib/bool.py (100%) rename pythonium/{ => compliant}/lib/builtins.py (100%) rename pythonium/{ => compliant}/lib/dict.py (100%) rename pythonium/{ => compliant}/lib/exceptions.py (100%) rename pythonium/{ => compliant}/lib/float.py (100%) rename pythonium/{ => compliant}/lib/int.py (100%) rename pythonium/{ => compliant}/lib/iterator.py (100%) rename pythonium/{ => compliant}/lib/list.py (100%) rename pythonium/{ => compliant}/lib/none.py (100%) rename pythonium/{ => compliant}/lib/runtime.py (100%) rename pythonium/{ => compliant}/lib/slice.py (100%) rename pythonium/{ => compliant}/lib/str.py (100%) create mode 100644 pythonium/veloce/__init__.py rename pythonium/{ => veloce}/veloce.py (99%) diff --git a/pythonium/lib/__init__.py b/pythonium/compliant/__init__.py similarity index 100% rename from pythonium/lib/__init__.py rename to pythonium/compliant/__init__.py diff --git a/pythonium/pythonium.py b/pythonium/compliant/compliant.py similarity index 99% rename from pythonium/pythonium.py rename to pythonium/compliant/compliant.py index e5db2f0..ded4f6c 100644 --- a/pythonium/pythonium.py +++ b/pythonium/compliant/compliant.py @@ -15,8 +15,8 @@ from ast import FunctionDef from ast import NodeVisitor -from .utils import YieldSearch -from .veloce import Veloce +from ..utils import YieldSearch +from ..veloce.veloce import Veloce ClassDefNode = namedtuple('ClassDef', 'name') FunctionDefNode = namedtuple('FunctionDef', 'name') diff --git a/pythonium/compliant/lib/__init__.py b/pythonium/compliant/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pythonium/lib/bool.py b/pythonium/compliant/lib/bool.py similarity index 100% rename from pythonium/lib/bool.py rename to pythonium/compliant/lib/bool.py diff --git a/pythonium/lib/builtins.py b/pythonium/compliant/lib/builtins.py similarity index 100% rename from pythonium/lib/builtins.py rename to pythonium/compliant/lib/builtins.py diff --git a/pythonium/lib/dict.py b/pythonium/compliant/lib/dict.py similarity index 100% rename from pythonium/lib/dict.py rename to pythonium/compliant/lib/dict.py diff --git a/pythonium/lib/exceptions.py b/pythonium/compliant/lib/exceptions.py similarity index 100% rename from pythonium/lib/exceptions.py rename to pythonium/compliant/lib/exceptions.py diff --git a/pythonium/lib/float.py b/pythonium/compliant/lib/float.py similarity index 100% rename from pythonium/lib/float.py rename to pythonium/compliant/lib/float.py diff --git a/pythonium/lib/int.py b/pythonium/compliant/lib/int.py similarity index 100% rename from pythonium/lib/int.py rename to pythonium/compliant/lib/int.py diff --git a/pythonium/lib/iterator.py b/pythonium/compliant/lib/iterator.py similarity index 100% rename from pythonium/lib/iterator.py rename to pythonium/compliant/lib/iterator.py diff --git a/pythonium/lib/list.py b/pythonium/compliant/lib/list.py similarity index 100% rename from pythonium/lib/list.py rename to pythonium/compliant/lib/list.py diff --git a/pythonium/lib/none.py b/pythonium/compliant/lib/none.py similarity index 100% rename from pythonium/lib/none.py rename to pythonium/compliant/lib/none.py diff --git a/pythonium/lib/runtime.py b/pythonium/compliant/lib/runtime.py similarity index 100% rename from pythonium/lib/runtime.py rename to pythonium/compliant/lib/runtime.py diff --git a/pythonium/lib/slice.py b/pythonium/compliant/lib/slice.py similarity index 100% rename from pythonium/lib/slice.py rename to pythonium/compliant/lib/slice.py diff --git a/pythonium/lib/str.py b/pythonium/compliant/lib/str.py similarity index 100% rename from pythonium/lib/str.py rename to pythonium/compliant/lib/str.py diff --git a/pythonium/main.py b/pythonium/main.py index 54963a3..052d3ab 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -22,8 +22,8 @@ import sys from docopt import docopt -from .veloce import veloce_generate_js -from .pythonium import pythonium_generate_js +from .veloce.veloce import veloce_generate_js +from .compliant.compliant import pythonium_generate_js __version__ = '0.5.0' @@ -32,7 +32,7 @@ def main(argv=None): args = docopt(__doc__, argv, version='pythonium ' + __version__) if args['--generate']: # call ourself for each file in pythonium.lib: - from pythonium import lib + from pythonium.compliant import lib # runtime is built separatly # it must appear first in the file diff --git a/pythonium/veloce/__init__.py b/pythonium/veloce/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pythonium/veloce.py b/pythonium/veloce/veloce.py similarity index 99% rename from pythonium/veloce.py rename to pythonium/veloce/veloce.py index 7c52427..3b89a92 100644 --- a/pythonium/veloce.py +++ b/pythonium/veloce/veloce.py @@ -12,7 +12,7 @@ from ast import FunctionDef from ast import NodeVisitor -from .utils import YieldSearch +from ..utils import YieldSearch class Writer: diff --git a/setup.py b/setup.py index 513dde4..8e7ea46 100755 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ author_email='amirouche.boubekki@gmail.com', url='https://github.com/pythonium/pythonium', zip_safe=False, - packages=['pythonium', 'pythonium.lib'], + packages=['pythonium', 'pythonium.compliant', 'pythonium.compliant.lib', 'pythonium.veloce'], install_requires=['docopt'], entry_points=""" [console_scripts] From 58ff397193113462943bb90a927c6025a6c39b6b Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 20:13:15 +0100 Subject: [PATCH 066/160] compliant: added assert --- pythonium/compliant/compliant.py | 29 +++++++++------- pythonium/compliant/lib/bool.py | 56 +++++++++++------------------- pythonium/compliant/lib/runtime.py | 23 ++++++++---- runtests.py | 12 +++---- tests/compliant-assert.py | 13 +++++++ 5 files changed, 73 insertions(+), 60 deletions(-) create mode 100644 tests/compliant-assert.py diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index ded4f6c..930902c 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -136,8 +136,11 @@ def visit_Try(self, node): self.writer.push() list(map(self.visit, node.body)) self.writer.pull() - self.writer.write('}') + self.writer.write('} catch (__exception__) {') + self.writer.push() list(map(self.visit, node.handlers)) + self.writer.pull() + self.writer.write('}') # Raise(expr? exc, expr? cause) def visit_Raise(self, node): @@ -145,21 +148,18 @@ def visit_Raise(self, node): # ExceptHandler(expr? type, identifier? name, stmt* body) def visit_ExceptHandler(self, node): - # 'type', 'name', 'body' if node.type: if node.name: - catch = '{} if (pythonium_is_exception({}, {}))'.format(node.name, node.name, self.visit(node.type)) + self.writer.write('var {} = __exception__;'.format(node.name)) + name = node.name else: - catch = '__exception__ if (pythonium_is_exception(__exception__, {}))'.format(self.visit(node.type)) - elif node.name: - catch = node.name - else: - catch = '__exception__' - self.writer.write('catch ({}) {{'.format(catch)) - self.writer.push() + name = '__exception__' + self.writer.write('if (pythonium_is_exception({}, {})) {{'.format(name, self.visit(node.type))) + self.writer.push() list(map(self.visit, node.body)) - self.writer.pull() - self.writer.write('}') + if node.type: + self.writer.pull() + self.writer.write('}') # Yield(expr? value) def visit_Yield(self, node): @@ -757,7 +757,10 @@ def visit_BoolOp(self, node): return out # Assert(expr test, expr? msg) - visit_Assert = NotImplemented + def visit_Assert(self, node): + test = self.visit(node.test) + msg = self.visit(node.msg) if node.msg else 'undefined' + self.writer.write('ASSERT({}, {});'.format(test, msg)) # If(expr test, stmt* body, stmt* orelse) def visit_If(self, node): diff --git a/pythonium/compliant/lib/bool.py b/pythonium/compliant/lib/bool.py index d383480..841f246 100644 --- a/pythonium/compliant/lib/bool.py +++ b/pythonium/compliant/lib/bool.py @@ -1,58 +1,44 @@ -class _True: +class bool: - def __init__(self): - self.jsobject = jscode('true') + def __init__(self, obj): + self.jsobject = pythonium_is_true(obj) def __jstype__(self): return self.jsobject def __repr__(self): - return "True" - - def __and__(self, other): - if jscode('other === self'): - return True - return False - - def __or__(self, other): - return True - - def __is__(self, other): - if jscode('other === self'): - return True - return False - - def __neg__(self): + if self.jsobject: + return 'True' return False - -class _False: - - def __init__(self): - self.jsobject = jscode('false') - - def __jstype__(self): - return self.jsobject - - def __repr__(self): - return "False" - def __and__(self, other): + if self: + if other: + return True return False def __or__(self, other): - if jscode('other === __TRUE'): + if self: + return True + if other: return True return False def __is__(self, other): - if jscode('other === self'): + if jscode('self === other'): return True return False def __neg__(self): + if self: + return False + return True + + def __not__(self): + if self: + return False return True -__TRUE = _True() -__FALSE = _False() +__TRUE = bool(jscode('true')) +__FALSE = bool(jscode('false')) diff --git a/pythonium/compliant/lib/runtime.py b/pythonium/compliant/lib/runtime.py index 428d538..837081e 100644 --- a/pythonium/compliant/lib/runtime.py +++ b/pythonium/compliant/lib/runtime.py @@ -44,15 +44,21 @@ def issubclass(klass, other): def pythonium_is_true(v): - if v is __FALSE or v is False: + if not v: return False - if v is __TRUE or (jscode('v !== undefined') and v != __NONE): + if v is True: return True - if isinstance(v, int): - if pythonium_get_attribute(v, 'jsobject') == 0: + if v is __NONE: + return False + if v is __FALSE: + return False + if isinstance(v, int) or isinstance(v, float): + if v.jsobject == 0: return False - return True - return False + length = lookup(v, '__length__') + if length and length() == 0: + return False + return True def isinstance(object, klass): @@ -195,3 +201,8 @@ def method_wrapper(): def pythonium_set_attribute(object, attr, value): object[attr] = value + + +def ASSERT(condition, message): + if not condition: + raise message or pythonium_call(str, 'Assertion failed') diff --git a/runtests.py b/runtests.py index 1343704..3444a29 100755 --- a/runtests.py +++ b/runtests.py @@ -12,8 +12,8 @@ from pythonium.main import main -from pythonium.veloce import veloce_generate_js -from pythonium.pythonium import pythonium_generate_js +from pythonium.veloce.veloce import veloce_generate_js +from pythonium.compliant.compliant import pythonium_generate_js ROOT = os.path.abspath(os.path.dirname(__file__)) @@ -62,14 +62,14 @@ def compare_output(expected, result): pythonium_generate_js(filepath, output=f) except Exception as exc: print_exc() - print('< Translating {} in mode {} failed with the above exception.'.format(test, mode)) + print('< Translating {} in {} mode failed with the above exception.'.format(test, mode)) continue try: result = check_output(['nodejs', exec_script], stderr=STDOUT) except CalledProcessError as err: print(err.output.decode(errors='replace')) - print('< {} ERROR in mode {} :('.format(test, mode)) + print('< {} ERROR in {} mode :('.format(test, mode)) continue expected_file = os.path.join(TESTS_ROOT, test+'.expected') @@ -88,9 +88,9 @@ def compare_output(expected, result): if diffs: for line in diffs: print(line) - print('< {} FAILED in mode {} :('.format(test, mode)) + print('< {} FAILED in {} mode :('.format(test, mode)) else: ok_ctr += 1 - print('< {} PASS in mode {} :)'.format(test, mode)) + print('< {} PASS in {} mode :)'.format(test, mode)) print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) diff --git a/tests/compliant-assert.py b/tests/compliant-assert.py new file mode 100644 index 0000000..0495799 --- /dev/null +++ b/tests/compliant-assert.py @@ -0,0 +1,13 @@ +assert 1 == 1, 'BAD' + +try: + assert 1 != 2, 'GOOD' +except: + print(__exception__) + +assert 2 == 2 + +try: + assert 2 != 3 +except: + print('GOOD') From d4b819c1c2022c49d4b078c23612972e606c5db5 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 20:16:03 +0100 Subject: [PATCH 067/160] renamed pythonium_generate_js to compliant_generate_js --- pythonium/compliant/compliant.py | 12 ++++++------ pythonium/main.py | 4 ++-- runtests.py | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 930902c..734cd77 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -41,7 +41,7 @@ def value(self): return self.output.getvalue() -class Pythonium(NodeVisitor): +class Compliant(NodeVisitor): @classmethod def translate(cls, code): @@ -869,7 +869,7 @@ def visit_ClassDef(self, node): self._def_stack.pop() -def pythonium_generate_js(filepath, requirejs=False, root_path=None, output=None, deep=None): +def compliant_generate_js(filepath, requirejs=False, root_path=None, output=None, deep=None): dirname = os.path.abspath(os.path.dirname(filepath)) if not root_path: root_path = dirname @@ -881,13 +881,13 @@ def pythonium_generate_js(filepath, requirejs=False, root_path=None, output=None with open(os.path.join(dirname, basename)) as f: input = parse(f.read()) tree = parse(input) - pythonium = Pythonium() - pythonium.visit(tree) - script = pythonium.writer.value() + compliant = Compliant() + compliant.visit(tree) + script = compliant.writer.value() if requirejs: out = 'define(function(require) {\n' out += script - all = map(lambda x: "'{}': {}".format(x, x), pythonium.__all__) + all = map(lambda x: "'{}': {}".format(x, x), compliant.__all__) all = '{{{}}}'.format(', '.join(all)) out += 'return {}'.format(all) out += '\n})\n' diff --git a/pythonium/main.py b/pythonium/main.py index 052d3ab..47237f9 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -23,7 +23,7 @@ from docopt import docopt from .veloce.veloce import veloce_generate_js -from .compliant.compliant import pythonium_generate_js +from .compliant.compliant import compliant_generate_js __version__ = '0.5.0' @@ -54,7 +54,7 @@ def main(argv=None): main(['--help']) return - generator = veloce_generate_js if args['--veloce'] else pythonium_generate_js + generator = veloce_generate_js if args['--veloce'] else compliant_generate_js options = {'requirejs': args['--requirejs'], 'deep': args['--deep'], } diff --git a/runtests.py b/runtests.py index 3444a29..7297c44 100755 --- a/runtests.py +++ b/runtests.py @@ -13,7 +13,7 @@ from pythonium.main import main from pythonium.veloce.veloce import veloce_generate_js -from pythonium.compliant.compliant import pythonium_generate_js +from pythonium.compliant.compliant import compliant_generate_js ROOT = os.path.abspath(os.path.dirname(__file__)) @@ -40,7 +40,7 @@ def compare_output(expected, result): # XXX: this force to install pythonium before running tests - PYTHONIUMJS = Popen(["pythonium", "--generate"], stdout=PIPE).communicate()[0].decode('utf-8') + COMPLIANTJS = Popen(["pythonium", "--generate"], stdout=PIPE).communicate()[0].decode('utf-8') for mode in ('veloce', 'compliant'): print('* running tests for {} mode'.format(mode)) @@ -58,8 +58,8 @@ def compare_output(expected, result): if mode =='veloce': veloce_generate_js(filepath, output=f) else: - f.write(PYTHONIUMJS) - pythonium_generate_js(filepath, output=f) + f.write(COMPLIANTJS) + compliant_generate_js(filepath, output=f) except Exception as exc: print_exc() print('< Translating {} in {} mode failed with the above exception.'.format(test, mode)) From cb6f11c5b791250fdbb493ade65e62484afe12a9 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 20:29:35 +0100 Subject: [PATCH 068/160] compliant: added tests for break and fixed nested loops --- pythonium/compliant/compliant.py | 19 +++++++++++-------- pythonium/compliant/lib/int.py | 14 ++++++++++++++ pythonium/compliant/lib/runtime.py | 2 +- tests/for-loop.py | 6 +++--- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 734cd77..1e40c31 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -191,9 +191,10 @@ def visit_Tuple(self, node): def visit_List(self, node): args = ', '.join(map(self.visit, node.elts)) if args: - self.writer.write('var __a_list = pythonium_call(list);') - self.writer.write('__a_list.jsobject = [{}];'.format(args)) - return '__a_list' + name = '__a_list{}'.format(self.uuid()) + self.writer.write('var {} = pythonium_call(list);'.format(name)) + self.writer.write('{}.jsobject = [{}];'.format(name, args)) + return name else: return 'pythonium_call(list)' @@ -796,10 +797,11 @@ def visit_Dict(self, node): v = self.visit(node.values[i]) values.append(v) if node.keys: - self.writer.write('var __a_dict = pythonium_call(dict)') + name = '__a_dict{}'.format(self.uuid()) + self.writer.write('var {} = pythonium_call(dict);'.format(name)) for key, value in zip(keys, values): - self.writer.write('__a_dict.__setitem__(__a_dict, key, value);') - return '__a_dict' + self.writer.write('{}.__setitem__({}, key, value);'.format(name)) + return name else: return 'pythonium_call(dict)' @@ -816,10 +818,11 @@ def visit_For(self, node): iterator = self.visit(node.iter) # iter is the python iterator self.writer.write('try {') self.writer.push() - self.writer.write('var __next__ = pythonium_get_attribute(iter({}), "__next__");'.format(iterator)) + nextname = '__next{}__'.format(self.uuid()) + self.writer.write('var {} = pythonium_get_attribute(iter({}), "__next__");'.format(nextname, iterator)) self.writer.write('while(true) {') self.writer.push() - self.writer.write('var {} = __next__();'.format(target)) + self.writer.write('var {} = {}();'.format(target, nextname)) list(map(self.visit, node.body)) self.writer.pull() self.writer.write('}') diff --git a/pythonium/compliant/lib/int.py b/pythonium/compliant/lib/int.py index 053cea0..091df3a 100644 --- a/pythonium/compliant/lib/int.py +++ b/pythonium/compliant/lib/int.py @@ -35,6 +35,20 @@ def __lt__(self, other): return True return False + def __gt__(self, other): + a = self.jsobject + b = other.jsobject + if jscode('a > b'): + return True + return False + + def __gte__(self, other): + a = self.jsobject + b = other.jsobject + if jscode('a >= b'): + return True + return False + def __lte__(self, other): a = self.jsobject b = other.jsobject diff --git a/pythonium/compliant/lib/runtime.py b/pythonium/compliant/lib/runtime.py index 837081e..b48f175 100644 --- a/pythonium/compliant/lib/runtime.py +++ b/pythonium/compliant/lib/runtime.py @@ -44,7 +44,7 @@ def issubclass(klass, other): def pythonium_is_true(v): - if not v: + if v is False: return False if v is True: return True diff --git a/tests/for-loop.py b/tests/for-loop.py index 99c4fc6..66fdf05 100644 --- a/tests/for-loop.py +++ b/tests/for-loop.py @@ -1,9 +1,9 @@ - -print("# looping over a string") for c in "abcdefghijk": print(c) -print("# looping over a list") for i in [1,2,3,4,5,6,7,8,9,0]: print(i) +for i in [1,2,3,4]: + for j in [1,2,3,4]: + print(i*j) From 17fd2e015a845cf2be390f6bca17d8903509d34f Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 20:32:45 +0100 Subject: [PATCH 069/160] compliant: added tests for break in a while loop --- tests/break-for-loop.py | 12 ++++++++++++ tests/break-while-loop.py | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/break-for-loop.py create mode 100644 tests/break-while-loop.py diff --git a/tests/break-for-loop.py b/tests/break-for-loop.py new file mode 100644 index 0000000..6b16196 --- /dev/null +++ b/tests/break-for-loop.py @@ -0,0 +1,12 @@ +for i in [1,2,3]: + print(i) + if i == 2: + break + +for i in [1,2,3]: + print(i) + for j in [3,4,5]: + print(i*j) + if i*j > 8: + print('youpla!') + break diff --git a/tests/break-while-loop.py b/tests/break-while-loop.py new file mode 100644 index 0000000..d36cb60 --- /dev/null +++ b/tests/break-while-loop.py @@ -0,0 +1,17 @@ +index = 0 +while index < 10: + index += 1 + if index / 2 == 0: + break + print(index) + + +I0 = 0 +I1 = 0 +while I0 < 10: + I0 += 1 + while I1 < 10: + I1 += 1 + if I0 * I1 > 5: + break + print(I0, I1) From f5e68e95d17795b18477319c271147eeb3a612e6 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 20:34:32 +0100 Subject: [PATCH 070/160] compliant: added tests for continue in while and for loops --- tests/continue-for-loop.py | 11 +++++++++++ tests/continue-while-loop.py | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/continue-for-loop.py create mode 100644 tests/continue-while-loop.py diff --git a/tests/continue-for-loop.py b/tests/continue-for-loop.py new file mode 100644 index 0000000..5e703f5 --- /dev/null +++ b/tests/continue-for-loop.py @@ -0,0 +1,11 @@ +for i in [1,2,3]: + print(i) + if i == 2: + continue + +for i in [1,2,3]: + print(i) + for j in [3,4,5]: + print(i*j) + if i*j > 8: + continue diff --git a/tests/continue-while-loop.py b/tests/continue-while-loop.py new file mode 100644 index 0000000..d313212 --- /dev/null +++ b/tests/continue-while-loop.py @@ -0,0 +1,17 @@ +index = 0 +while index < 10: + index += 1 + if index / 2 == 0: + continue + print(index) + + +I0 = 0 +I1 = 0 +while I0 < 10: + I0 += 1 + while I1 < 10: + I1 += 1 + if I0 * I1 > 5: + continue + print(I0, I1) From 75cf73a0034f59250704db61ba8fca1fdc621574 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 21:36:55 +0100 Subject: [PATCH 071/160] compliant: implemented del without slice support --- pythonium/compliant/compliant.py | 19 ++++++++++++------- pythonium/compliant/lib/dict.py | 26 ++++++++++++++++++-------- pythonium/compliant/lib/exceptions.py | 4 ++++ pythonium/compliant/lib/list.py | 18 ++++++++++++++++++ pythonium/compliant/lib/runtime.py | 10 +++++++++- 5 files changed, 61 insertions(+), 16 deletions(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 1e40c31..2c79520 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -305,9 +305,9 @@ def visit_FunctionDef(self, node): # unpack arguments self.writer.write('/* BEGIN unpacking arguments */') - if varargs or (varkwargs and varkwargs == '__kwargs') or kwargs: + if varargs or (varkwargs and varkwargs != '__kwargs') or kwargs: self.writer.write('var __args = Array.prototype.slice.call(arguments);') - if varkwargs and (varkwargs != '__kwargs' or kwargs): + if (varkwargs and varkwargs != '__kwargs') or kwargs: self.writer.write('if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) {') self.writer.push() self.writer.write('var {} = __args[__args.length - 1];'.format(varkwargs)) @@ -315,7 +315,7 @@ def visit_FunctionDef(self, node): self.writer.pull() self.writer.write('} else {') # no variable keywords was provided so it's empty self.writer.push() - self.writer.write('var {} = {{}};'.format(varkwargs)) + self.writer.write('var {} = pythonium_create_empty_dict();'.format(varkwargs)) self.writer.write('var varkwargs_start = undefined;') self.writer.pull() self.writer.write('}') @@ -340,8 +340,6 @@ def visit_FunctionDef(self, node): self.writer.write('if (varkwargs_start) {{ __args.splice(varkwargs_start - {}) }}'.format(len(args))) self.writer.write('var {} = pythonium_call(list);'.format(varargs)) self.writer.write('{}.jsobject = __args;'.format(varargs)) - if varkwargs and varkwargs != '__kwargs': - self.writer.write('{} = pythonium_call(dict, {});'.format(varkwargs, varkwargs)) self.writer.write('/* END unpacking arguments */') # check for variable creation use var if not global @@ -661,7 +659,14 @@ def visit_Or(self, node): # Delete(expr* targets) def visit_Delete(self, node): - raise NotImplementedError + for target in node.targets: + if isinstance(target, Subscript): + slice = self.visit(target.slice) + target = self.visit(target.value) + self.writer.write("pythonium_get_attribute({}, '__delitem__')({});".format(target, slice)) + else: + target = self.visit(target) + self.writer.write('delete {};'.format(target)) # Assign(expr* targets, expr value) def visit_Assign(self, node): @@ -800,7 +805,7 @@ def visit_Dict(self, node): name = '__a_dict{}'.format(self.uuid()) self.writer.write('var {} = pythonium_call(dict);'.format(name)) for key, value in zip(keys, values): - self.writer.write('{}.__setitem__({}, key, value);'.format(name)) + self.writer.write('{}.__class__.__setitem__({}, {}, {});'.format(name, name, key, value)) return name else: return 'pythonium_call(dict)' diff --git a/pythonium/compliant/lib/dict.py b/pythonium/compliant/lib/dict.py index a3b7dbf..1684ca5 100644 --- a/pythonium/compliant/lib/dict.py +++ b/pythonium/compliant/lib/dict.py @@ -2,7 +2,7 @@ class dict: def __init__(self, **kwargs): self._keys = list() - self._jsobject = JSObject() + self.jsobject = JSObject() for key in kwargs.keys(): self[key] = kwargs[key] @@ -14,24 +14,24 @@ def __jstype__(self): def __repr__(self): out = [] - for key in self.keys(): + for key in self._keys: key_repr = repr(key) value_repr = repr(self[key]) out.append(key_repr + ': ' + value_repr) return "{" + ", ".join(out) + "}" def get(self, key, d=None): - if key in self.keys: + if key in self._keys: h = jstype(hash(key)) jsobject = self.jsobject return jscode('jsobject[h]') return d def __iter__(self): - return ListIterator(self.keys()) + return ListIterator(self._keys) def __getitem__(self, key): - if key in self.keys: + if key in self._keys: h = jstype(hash(key)) jsobject = self.jsobject return jscode('jsobject[h]') @@ -41,13 +41,23 @@ def __setitem__(self, key, value): h = jstype(hash(key)) jsobject = self.jsobject jscode('jsobject[h] = value') - self.keys.append(key) + self._keys.append(key) def keys(self): - return self.keys + return self._keys def items(self): out = list() - for key in self.keys(): + for key in self._keys: out.append([key, self[key]]) return out + + def __delitem__(self, key): + if key in self._keys: + self._keys.remove(key) + h = jstype(hash(key)) + jsobject = self.jsobject + jscode('delete jsobject[h]') + else: + raise KeyError + diff --git a/pythonium/compliant/lib/exceptions.py b/pythonium/compliant/lib/exceptions.py index b1fe942..ea197c2 100644 --- a/pythonium/compliant/lib/exceptions.py +++ b/pythonium/compliant/lib/exceptions.py @@ -22,3 +22,7 @@ class StopIteration(Exception): class NotImplementedError(Exception): pass + + +class ValueError(Exception): + pass diff --git a/pythonium/compliant/lib/list.py b/pythonium/compliant/lib/list.py index df0c397..d728a9d 100644 --- a/pythonium/compliant/lib/list.py +++ b/pythonium/compliant/lib/list.py @@ -61,3 +61,21 @@ def __contains__(self, obj): return True return False + def pop(self): + return self.jsobject.pop() + + def index(self, obj): + index = 0 + for item in self: + if item == obj: + return index + index += 1 + raise ValueError + + def remove(self, obj): + index = self.index(obj) + jsobject = self.jsobject + jscode('jsobject.splice(jstype(index), 1)') + + def __delitem__(self, index): + self.jsobject.splice(jstype(index), 1) diff --git a/pythonium/compliant/lib/runtime.py b/pythonium/compliant/lib/runtime.py index b48f175..8f55429 100644 --- a/pythonium/compliant/lib/runtime.py +++ b/pythonium/compliant/lib/runtime.py @@ -9,9 +9,12 @@ __ARGUMENTS_PADDING__ = {ARGUMENTS_PADDING: "YES IT IS!"} +def __is__(self, other): + return (self is other) +__object.__is__ = __is__ + def __isnot__(self, other): return not (self is other) - __object.__isnot__ = __isnot__ @@ -89,6 +92,11 @@ def pythonium_call(object): else: return object.apply(object, args) +def pythonium_create_empty_dict(): + instance = {__class__: dict} + instance._keys = pythonium_call(list) + instance.jsobject = JSObject() + return instance def pythonium_mro(bases): From ab2dee7d00eeee9971d636fe4c61bed4baadea59 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 21:37:05 +0100 Subject: [PATCH 072/160] compliant: implemented del without slice support --- tests/del-items.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/del-items.py diff --git a/tests/del-items.py b/tests/del-items.py new file mode 100644 index 0000000..9bbb332 --- /dev/null +++ b/tests/del-items.py @@ -0,0 +1,3 @@ +d = {1:1} +del d[1] +print(d) From 995a2c1ac42ba177e9f881ced6bbf9e36d32fcdf Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 8 Dec 2013 21:38:49 +0100 Subject: [PATCH 073/160] compliant: added a test for if/elif/else --- tests/if-elif-else.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/if-elif-else.py diff --git a/tests/if-elif-else.py b/tests/if-elif-else.py new file mode 100644 index 0000000..1c2399c --- /dev/null +++ b/tests/if-elif-else.py @@ -0,0 +1,14 @@ +if True: + print('YEAH') + +if False: + print('BOOH') +else: + print('YEAH') + +if False: + print('BOOH') +elif False: + print('BOOH') +else: + print('YEAH') From 61ade600c1315ac8c0ab9ed170dd171f9d5f8074 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 01:06:50 +0100 Subject: [PATCH 074/160] compliant: fixed mro, repr, lambda with full signature --- pythonium/compliant/compliant.py | 118 +++++++++++++++++----------- pythonium/compliant/lib/builtins.py | 6 +- pythonium/compliant/lib/dict.py | 14 +++- pythonium/compliant/lib/float.py | 2 +- pythonium/compliant/lib/int.py | 2 +- pythonium/compliant/lib/list.py | 8 ++ pythonium/compliant/lib/runtime.py | 21 +++-- runtests.py | 1 + tests/lambda.py | 2 + 9 files changed, 113 insertions(+), 61 deletions(-) create mode 100644 tests/lambda.py diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 2c79520..18b9d67 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -300,47 +300,8 @@ def visit_FunctionDef(self, node): else: self.writer.write('var {} = function({}) {{'.format(name, __args)) self.writer.push() - if not varkwargs and kwargs: - varkwargs = '__kwargs' - # unpack arguments - self.writer.write('/* BEGIN unpacking arguments */') - if varargs or (varkwargs and varkwargs != '__kwargs') or kwargs: - self.writer.write('var __args = Array.prototype.slice.call(arguments);') - if (varkwargs and varkwargs != '__kwargs') or kwargs: - self.writer.write('if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) {') - self.writer.push() - self.writer.write('var {} = __args[__args.length - 1];'.format(varkwargs)) - self.writer.write('var varkwargs_start = __args.length - 2;') - self.writer.pull() - self.writer.write('} else {') # no variable keywords was provided so it's empty - self.writer.push() - self.writer.write('var {} = pythonium_create_empty_dict();'.format(varkwargs)) - self.writer.write('var varkwargs_start = undefined;') - self.writer.pull() - self.writer.write('}') - num_args = len(args) - for index, keyword in enumerate(kwargs.keys()): - position = num_args + index - 1 - self.writer.write('if (varkwargs_start !== undefined && {} > varkwargs_start) {{'.format(position)) - self.writer.push() - - self.writer.write('{} = {}.{} || {};'.format(keyword, varkwargs, keyword, kwargs[keyword])) - self.writer.pull() - self.writer.write('} else {') - self.writer.push() - self.writer.write('{} = {} || {}.{} || {};'.format(keyword, keyword, varkwargs, keyword, kwargs[keyword])) - self.writer.pull() - self.writer.write('}') - if varkwargs != '__kwargs': - self.writer.write('delete {}.{};'.format(varkwargs, keyword)) - if varargs: - self.writer.write('__args = __args.splice({});'.format(len(args))) - if varkwargs and (varkwargs != '__kwargs' or kwargs): - self.writer.write('if (varkwargs_start) {{ __args.splice(varkwargs_start - {}) }}'.format(len(args))) - self.writer.write('var {} = pythonium_call(list);'.format(varargs)) - self.writer.write('{}.jsobject = __args;'.format(varargs)) - self.writer.write('/* END unpacking arguments */') + self._unpack_arguments(args, kwargs, varargs, varkwargs) # check for variable creation use var if not global def retrieve_vars(body, vars=None): @@ -404,7 +365,6 @@ def visit_Subscript(self, node): # arg* kwonlyargs, identifier? kwarg, expr? kwargannotation, # expr* defaults, expr* kw_defaults) def visit_arguments(self, node): - # 'args', 'vararg', 'varargannotation', 'kwonlyargs', 'kwarg', 'kwargannotation', 'defaults', 'kw_defaults' args = list(map(lambda x: x.arg, node.args)) vararg = node.vararg kwonlyargs = node.kwonlyargs @@ -500,14 +460,27 @@ def visit_Call(self, node): else: args = [] args.insert(0, name) - call_arguments = 'call_arguments{}'.format(self.uuid()) - self.writer.write('var {} = [{}];'.format(call_arguments, ', '.join(args))) # variable arguments aka. starargs if node.starargs: varargs = self.visit(node.starargs) code = "for i in {}: jscode('{}.push(i)')".format(varargs, call_arguments) self.writer.write(self.translate(code)) - # keywords and variable keywords arguments aka. starkwargs + # keywords and variable keywords arguments aka. starkwargs + if node.kwargs: + kwargs = self.visit(node.kwargs) + if node.keywords: + for key, value in map(self.visit, node.keywords): + self.writer.write('{}.__class__.__setitem__({}, pythonium_call(str, "{}"), {})'.format(kwargs, kwargs, key, value)) # XXX + elif node.keywords: + kwargs = '__pythonium_kwargs' + self.writer.write('var __pythonium_kwargs = pythonium_create_empty_dict();') + for key, value in map(self.visit, node.keywords): + self.writer.write('{}.__class__.__setitem__({}, pythonium_call(str, "{}"), {})'.format(kwargs, kwargs, key, value)) + if node.kwargs or node.keywords: + args.append('__ARGUMENTS_PADDING__') + args.append(kwargs) + call_arguments = 'call_arguments{}'.format(self.uuid()) + self.writer.write('var {} = [{}];'.format(call_arguments, ', '.join(args))) return 'pythonium_call.apply(undefined, {})'.format(call_arguments) # ListComp(expr elt, comprehension* generators) @@ -842,10 +815,63 @@ def visit_Continue(self, node): def visit_Break(self, node): self.writer.write('break;') + def _unpack_arguments(self, args, kwargs, varargs, varkwargs): + self.writer.write('/* BEGIN arguments unpacking */') + if not varkwargs and kwargs: + varkwargs = '__kwargs' + + if varargs or (varkwargs and varkwargs != '__kwargs') or kwargs: + self.writer.write('var __args = Array.prototype.slice.call(arguments);') + if (varkwargs and varkwargs != '__kwargs') or kwargs: + self.writer.write('if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) {') + self.writer.push() + self.writer.write('var {} = __args[__args.length - 1];'.format(varkwargs)) + self.writer.write('var varkwargs_start = __args.length - 2;') + self.writer.pull() + self.writer.write('} else {') # no variable keywords was provided so it's empty + self.writer.push() + self.writer.write('var {} = pythonium_create_empty_dict();'.format(varkwargs)) + self.writer.write('var varkwargs_start = undefined;') + self.writer.pull() + self.writer.write('}') + num_args = len(args) + for index, keyword in enumerate(kwargs.keys()): + position = num_args + index - 1 + self.writer.write('if (varkwargs_start !== undefined && {} > varkwargs_start) {{'.format(position)) + self.writer.push() + + self.writer.write('{} = {}.__class__.get({}, {}) || {};'.format(keyword, varkwargs, varkwargs, keyword, kwargs[keyword])) + self.writer.pull() + self.writer.write('} else {') + self.writer.push() + self.writer.write('{} = {} || {}.__class__.get({}, {}) || {};'.format(keyword, keyword, varkwargs, varkwargs, keyword, kwargs[keyword])) + self.writer.pull() + self.writer.write('}') + if varkwargs != '__kwargs': + self.writer.write('delete {}.{};'.format(varkwargs, keyword)) + if varargs: + self.writer.write('__args = __args.splice({});'.format(len(args))) + if varkwargs and (varkwargs != '__kwargs' or kwargs): + self.writer.write('if (varkwargs_start) {{ __args.splice(varkwargs_start - {}) }}'.format(len(args))) + self.writer.write('var {} = pythonium_call(tuple);'.format(varargs)) + self.writer.write('{}.jsobject = __args;'.format(varargs)) + self.writer.write('/* END arguments unpacking */') + + # Lambda(arguments args, expr body) def visit_Lambda(self, node): - args = ', '.join(map(self.visit, node.args.args)) - return '(function ({}) {{{}}})'.format(args, self.visit(node.body)) + args, kwargs, vararg, varkwargs = self.visit(node.args) + sys.stderr.write(", ".join(args)) + name = '__lambda{}'.format(self.uuid()) + self.writer.write('var {} = function({}) {{'.format(name, ', '.join(args))) + self.writer.push() + self._unpack_arguments(args, kwargs, vararg, varkwargs) + body = self.visit(node.body) + self.writer.write(body) + self.writer.pull() + self.writer.write('}') + return name + # ClassDef(identifier name, expr* bases, keyword* keywords, # expr? starargs, expr? kwargs, stmt* body, expr* decorator_list) diff --git a/pythonium/compliant/lib/builtins.py b/pythonium/compliant/lib/builtins.py index 89ec480..e35813b 100644 --- a/pythonium/compliant/lib/builtins.py +++ b/pythonium/compliant/lib/builtins.py @@ -17,10 +17,10 @@ def repr(obj): def print(*args): - out = list() + out = JSArray() for arg in args: - out.append(repr(arg)) - jscode('console.log.apply(console, jstype(out))') + out.push(jstype(repr(arg))) + jscode('console.log.apply(console, out)') def map(func, objects): diff --git a/pythonium/compliant/lib/dict.py b/pythonium/compliant/lib/dict.py index 1684ca5..4382d59 100644 --- a/pythonium/compliant/lib/dict.py +++ b/pythonium/compliant/lib/dict.py @@ -1,3 +1,12 @@ +def nest_str_with_quotes(s): + r = repr(s) + if isinstance(s, str): + if "'" in r: + r = '"' + r + '"' + else: + r = "'" + r + "'" + return r + class dict: def __init__(self, **kwargs): @@ -15,8 +24,8 @@ def __jstype__(self): def __repr__(self): out = [] for key in self._keys: - key_repr = repr(key) - value_repr = repr(self[key]) + key_repr = nest_str_with_quotes(key) + value_repr = nest_str_with_quotes(self[key]) out.append(key_repr + ': ' + value_repr) return "{" + ", ".join(out) + "}" @@ -60,4 +69,3 @@ def __delitem__(self, key): jscode('delete jsobject[h]') else: raise KeyError - diff --git a/pythonium/compliant/lib/float.py b/pythonium/compliant/lib/float.py index 2cffe74..522a3c5 100644 --- a/pythonium/compliant/lib/float.py +++ b/pythonium/compliant/lib/float.py @@ -7,7 +7,7 @@ def __hash__(self): return str(self.jsobject) def __repr__(self): - return self + return str(self.jsobject.toString()) def __div__(self, other): a = self.jsobject diff --git a/pythonium/compliant/lib/int.py b/pythonium/compliant/lib/int.py index 091df3a..d217d82 100644 --- a/pythonium/compliant/lib/int.py +++ b/pythonium/compliant/lib/int.py @@ -16,7 +16,7 @@ def __jstype__(self): return self.jsobject def __repr__(self): - return self + return str(self.jsobject.toString()) def __add__(self, other): a = self.jsobject diff --git a/pythonium/compliant/lib/list.py b/pythonium/compliant/lib/list.py index d728a9d..08751dd 100644 --- a/pythonium/compliant/lib/list.py +++ b/pythonium/compliant/lib/list.py @@ -79,3 +79,11 @@ def remove(self, obj): def __delitem__(self, index): self.jsobject.splice(jstype(index), 1) + + +class tuple(list): + + def __repr__(self): + return "(" + ", ".join(map(repr, self)) + ")" + + diff --git a/pythonium/compliant/lib/runtime.py b/pythonium/compliant/lib/runtime.py index 8f55429..0bcd13e 100644 --- a/pythonium/compliant/lib/runtime.py +++ b/pythonium/compliant/lib/runtime.py @@ -97,7 +97,7 @@ def pythonium_create_empty_dict(): instance._keys = pythonium_call(list) instance.jsobject = JSObject() return instance - + def pythonium_mro(bases): """Calculate the Method Resolution Order of bases using the C3 algorithm. @@ -110,28 +110,35 @@ def pythonium_mro(bases): return the linearization of K (the MRO of K, *including* itself). """ # based on http://code.activestate.com/recipes/577748-calculate-the-mro-of-a-class/ - seqs = [C.__mro__ for C in bases] + seqs = [C.__mro__.slice() for C in bases] seqs.push(bases.slice()) + + def cdr(l): + l = l.slice() + l = l.splice(1) + return l res = [] while True: - # non_empty = list(filter(None, seqs)) non_empty = [] for seq in seqs: empty = True + out = [] for item in seq: if item: empty = False - break + out.push(item) if not empty: - non_empty.push(seq) + non_empty.push(out) if non_empty.length == 0: # Nothing left to process, we're done. return res for seq in non_empty: # Find merge candidates among seq heads. candidate = seq[0] - not_head = [s for s in non_empty if candidate in s.splice(1)] + not_head = [] + for s in non_empty: + if candidate in cdr(s): + not_head.push(s) if not_head.length != 0: - # Reject the candidate. candidate = None else: break diff --git a/runtests.py b/runtests.py index 7297c44..7966483 100755 --- a/runtests.py +++ b/runtests.py @@ -46,6 +46,7 @@ def compare_output(expected, result): print('* running tests for {} mode'.format(mode)) for test in os.listdir(TESTS_ROOT): if test.endswith('.py'): + print('< Running {} in {} mode.'.format(test, mode)) # compliant mode must run any code even code written for veloce mode # but veloce mode can not run compliant tests if test.startswith('compliant-') and mode != 'compliant': diff --git a/tests/lambda.py b/tests/lambda.py new file mode 100644 index 0000000..442408d --- /dev/null +++ b/tests/lambda.py @@ -0,0 +1,2 @@ +x = lambda x, y, *args, **kwargs: print(x, y, args, kwargs) +x(42, 1337, 11, 100, key="value") From 5c765c3410534dd759d474f947a812db0af53326 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 01:16:35 +0100 Subject: [PATCH 075/160] compliant: fixed truth in Pythonium --- pythonium/compliant/lib/dict.py | 3 +++ pythonium/compliant/lib/runtime.py | 4 ++-- runtests.py | 2 +- tests/compliant-what-is-true.py | 13 +++++++++++++ 4 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 tests/compliant-what-is-true.py diff --git a/pythonium/compliant/lib/dict.py b/pythonium/compliant/lib/dict.py index 4382d59..a8225e1 100644 --- a/pythonium/compliant/lib/dict.py +++ b/pythonium/compliant/lib/dict.py @@ -36,6 +36,9 @@ def get(self, key, d=None): return jscode('jsobject[h]') return d + def __len__(self): + return len(self._keys) + def __iter__(self): return ListIterator(self._keys) diff --git a/pythonium/compliant/lib/runtime.py b/pythonium/compliant/lib/runtime.py index 0bcd13e..ffb1197 100644 --- a/pythonium/compliant/lib/runtime.py +++ b/pythonium/compliant/lib/runtime.py @@ -58,8 +58,8 @@ def pythonium_is_true(v): if isinstance(v, int) or isinstance(v, float): if v.jsobject == 0: return False - length = lookup(v, '__length__') - if length and length() == 0: + length = lookup(v, '__len__') + if length and length().jsobject == 0: return False return True diff --git a/runtests.py b/runtests.py index 7966483..51f335d 100755 --- a/runtests.py +++ b/runtests.py @@ -43,7 +43,7 @@ def compare_output(expected, result): COMPLIANTJS = Popen(["pythonium", "--generate"], stdout=PIPE).communicate()[0].decode('utf-8') for mode in ('veloce', 'compliant'): - print('* running tests for {} mode'.format(mode)) + print('* Running tests for {} mode'.format(mode)) for test in os.listdir(TESTS_ROOT): if test.endswith('.py'): print('< Running {} in {} mode.'.format(test, mode)) diff --git a/tests/compliant-what-is-true.py b/tests/compliant-what-is-true.py new file mode 100644 index 0000000..8e31d33 --- /dev/null +++ b/tests/compliant-what-is-true.py @@ -0,0 +1,13 @@ +if []: + print('BOOH! Empty list is true :(') +if False: + print('BOOH! False is true :(') +if None: + print('BOOH! None is ture :(') +if 0: + print('BOOH! 0 is true :(') +if 0.0: + print('BOOH! 0.0 is true :(') +if dict(): + print('BOOH! Empty dict is true :(') + print(len(dict())) From 21a7ee8355352852fc61ae8b9a9db8b5c31baafc Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 01:26:07 +0100 Subject: [PATCH 076/160] compliant: added support for IfExpr aka. SPAM if EGG else FOOBAR --- pythonium/compliant/compliant.py | 15 ++++++++++++++- tests/if-else.py | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/if-else.py diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 18b9d67..751f5c4 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -757,7 +757,20 @@ def visit_If(self, node): self.writer.write('}') # IfExp(expr test, expr body, expr orelse) - visit_IfExp = NotImplemented + def visit_IfExp(self, node): + name = '__pythonium_ifexp_{}'.format(self.uuid()) + self.writer.write('if (pythonium_is_true({})) {{'.format(self.visit(node.test))) + self.writer.push() + body = self.visit(node.body) + self.writer.write('var {} = {};'.format(name, body)) + self.writer.pull() + self.writer.write('} else {') + self.writer.push() + orelse = self.visit(node.orelse) + self.writer.write('var {} = {};'.format(name, orelse)) + self.writer.pull() + self.writer.write('}') + return name # Ellipsis visit_Ellipsis = NotImplemented diff --git a/tests/if-else.py b/tests/if-else.py new file mode 100644 index 0000000..4cb17ed --- /dev/null +++ b/tests/if-else.py @@ -0,0 +1,3 @@ +a = "WIN" if True else "FAIL" +b = "FAIL" if False else "WIN" +print(a, b) From 47c672adccc5da5533e4fee1964c208a7ab84bdc Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 01:56:22 +0100 Subject: [PATCH 077/160] compliant: added support for yield --- pythonium/compliant/lib/builtins.py | 6 ++++++ runtests.py | 2 +- tests/compliant-yield.py | 10 ++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/compliant-yield.py diff --git a/pythonium/compliant/lib/builtins.py b/pythonium/compliant/lib/builtins.py index e35813b..79cbaa4 100644 --- a/pythonium/compliant/lib/builtins.py +++ b/pythonium/compliant/lib/builtins.py @@ -41,6 +41,12 @@ def iter(obj): def next(obj): + if jscode('obj.next !== undefined'): + r = jscode('obj.next()') + if jscode('r.done'): + raise StopIteration + else: + return jscode('r.value') return obj.__next__() diff --git a/runtests.py b/runtests.py index 51f335d..442803d 100755 --- a/runtests.py +++ b/runtests.py @@ -67,7 +67,7 @@ def compare_output(expected, result): continue try: - result = check_output(['nodejs', exec_script], stderr=STDOUT) + result = check_output(['nodejs', '--harmony', exec_script], stderr=STDOUT) except CalledProcessError as err: print(err.output.decode(errors='replace')) print('< {} ERROR in {} mode :('.format(test, mode)) diff --git a/tests/compliant-yield.py b/tests/compliant-yield.py new file mode 100644 index 0000000..5e06f8e --- /dev/null +++ b/tests/compliant-yield.py @@ -0,0 +1,10 @@ +def func(): + index = 0 + while index < 3: + yield index + index += 1 + +gen = func() +print(next(gen)) +print(next(gen)) +print(next(gen)) From 45b39ed5276c7e586bf3c9ba1afd6b49ea956847 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 12:15:15 +0100 Subject: [PATCH 078/160] added a HACKING file --- HACKING | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 HACKING diff --git a/HACKING b/HACKING new file mode 100644 index 0000000..5f1f5d7 --- /dev/null +++ b/HACKING @@ -0,0 +1,9 @@ +HACKING +####### + +Requirements +============ + +- Python 3.3+ +- nodejs, works with 0.10.21 +- a recent browser (optional) \ No newline at end of file From 1122aaad19bf788057beff06ad77b584cd3c2a0c Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:11:16 +0100 Subject: [PATCH 079/160] runtests.py: add the mode name in the generated exec.js script --- runtests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtests.py b/runtests.py index 442803d..0333c48 100755 --- a/runtests.py +++ b/runtests.py @@ -53,7 +53,7 @@ def compare_output(expected, result): continue test_ctr += 1 filepath = os.path.join(TESTS_ROOT, test) - exec_script = os.path.join(TMPDIR, test + 'exec.js') + exec_script = os.path.join(TMPDIR, test + 'exec-{}.js'.format(mode)) with open(exec_script, 'w') as f: try: if mode =='veloce': From 3ee08a5b67793849d57c014f9b4c1ff9d35eba8d Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:19:42 +0100 Subject: [PATCH 080/160] runtests.py: you do not need to install pythonium to run the test suite --- runtests.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/runtests.py b/runtests.py index 0333c48..6841d52 100755 --- a/runtests.py +++ b/runtests.py @@ -2,6 +2,7 @@ import os import sys import difflib +from io import StringIO from traceback import print_exc from subprocess import PIPE @@ -35,13 +36,17 @@ def compare_output(expected, result): if __name__ == '__main__': ok_ctr = test_ctr = 0 TMPDIR = os.path.join(TESTS_ROOT, 'tmp') - try: os.mkdir(TMPDIR) - except OSError: pass + try: + os.mkdir(TMPDIR) + except OSError: + pass + + stdout = sys.stdout + sys.stdout = StringIO() + main(['--generate']) + COMPLIANTJS = sys.stdout.getvalue() + sys.stdout = stdout - - # XXX: this force to install pythonium before running tests - COMPLIANTJS = Popen(["pythonium", "--generate"], stdout=PIPE).communicate()[0].decode('utf-8') - for mode in ('veloce', 'compliant'): print('* Running tests for {} mode'.format(mode)) for test in os.listdir(TESTS_ROOT): @@ -53,7 +58,11 @@ def compare_output(expected, result): continue test_ctr += 1 filepath = os.path.join(TESTS_ROOT, test) - exec_script = os.path.join(TMPDIR, test + 'exec-{}.js'.format(mode)) + if not test.startswith('compliant-'): + ext = 'exec-{}.js'.format(mode) + else: + ext = 'exec.js'.format(mode) + exec_script = os.path.join(TMPDIR, test + ext) with open(exec_script, 'w') as f: try: if mode =='veloce': From 1909a473f2f3a3835b977a379062bebf46ffcd81 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:20:18 +0100 Subject: [PATCH 081/160] cosmit --- runtests.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/runtests.py b/runtests.py index 6841d52..d3adceb 100755 --- a/runtests.py +++ b/runtests.py @@ -1,17 +1,14 @@ #!/usr/bin/env python3 import os import sys -import difflib +import difflib from io import StringIO from traceback import print_exc -from subprocess import PIPE -from subprocess import Popen from subprocess import STDOUT from subprocess import check_output from subprocess import CalledProcessError - from pythonium.main import main from pythonium.veloce.veloce import veloce_generate_js from pythonium.compliant.compliant import compliant_generate_js From 88c43f6cb62d99acdcdb3180adfb96710a6c33a4 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:22:24 +0100 Subject: [PATCH 082/160] HACKING.rst: update --- HACKING.rst | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 HACKING.rst diff --git a/HACKING.rst b/HACKING.rst new file mode 100644 index 0000000..4695fa6 --- /dev/null +++ b/HACKING.rst @@ -0,0 +1,108 @@ +HACKING +####### + +Requirements +============ + +- Python 3.3+ +- nodejs, tested with 0.11.9 +- a recent browser (optional) + +Installing nodejs +----------------- + +cli dance in a **Python 2** environment, the build system does not support Python 3:: + + git clone --depth 1 https://github.com/joyent/node.git + cd node + git checkout v0.11.9 + python2 configure + make + make install + +Installing Python 3.3 +--------------------- + +Download and install ``pythonz``:: + + curl -kL https://raw.github.com/saghul/pythonz/master/pythonz-install | bash + +Please add the following line to the end of your ``~/.bashrc``:: + + [[ -s $HOME/.pythonz/etc/bashrc ]] && source $HOME/.pythonz/etc/bashrc + +Then install python 3:: + + pythonz install 3.3.2 + +``pythonium`` usage +=================== + +Compliant mode +-------------- + +Create ``pythonium.js`` with ``pythonium -g > pythonium.js``. + +Translate your ``app.py`` with ``pythonium app.py > app.py.js`` include both in your html page or use the following command to execute the script in nodejs:: + + cat pythonium.js app.py.js | nodejs + + +Development workflow +==================== + +Add a test in ``./tests/`` prepend the name with ``compliant-`` if you are developping for the compliant mode, for instance:: + + compliant-yield-from.py + +Execute ``runtests.py`` to have the results. Depending on how it failed you can: + +- run the python script with python3 +- run the generated ``exec.js`` file in ``./tests/tmp/`` for instance for ``compliant-yield-from.py`` the generated file will be ``./tests/tmp/compliant-yield-from.pyexec.js`` + but if the test can be run in both modes like ``for-loop.py`` two files will be generated ``./tests/tmp/for-loop.pyexec-veloce.js`` and ``./tests/tmp/for-loop.pyexec-compliant.js`` + + +Internals +========= + +As you may already know there is two modes in pythonium, *veloce* and *compliant*. Compliant +mode is the default in ``pythonium`` command, to use *veloce* mode you need to provide de +``-V`` or ``--veloce`` option. + +Veloce mode +----------- + +Veloce is *Python syntax with JavaScript semantic*. The Veloce compiler transforms Python code +to JavaScript with minimal addition and modification to the abstract syntax tree. Additions or modification +of the abstract syntax tree are done to support features of Python that are not supported as-is by JavaScript. +Most of them are “syntaxic sugar”. + +Veloce provide an object system similar to Python via classy.js. That said there is a known gotcha, inherited +from the implementation of JavaScript prototype inheritance. If you assign a method to a variable, ``self`` in the context +of the “method” called through the variable will be the ``window`` object. + +The following:: + + caller(an_object.method) + +Does not work as expected. Instead one must define a ``wrap`` function that feeds the method context with the correct value of ``this``:: + + def wrap(object, method): + def wrapped(): + return method.apply(object, arguments) + return wrapped + +The previous code, must be written as follow:: + + caller(wrap(an_object, an_object.method)) + +This can not be automated in Veloce, but it's done in compliant mode. + +Translations +^^^^^^^^^^^^ + +Compliant mode +-------------- + +Translations +^^^^^^^^^^^^ From 7099e62053bcca204f9824961f3fa7fdeabb3801 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:23:13 +0100 Subject: [PATCH 083/160] removed HACKING, was replaced by HACKING.rst --- HACKING | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 HACKING diff --git a/HACKING b/HACKING deleted file mode 100644 index 5f1f5d7..0000000 --- a/HACKING +++ /dev/null @@ -1,9 +0,0 @@ -HACKING -####### - -Requirements -============ - -- Python 3.3+ -- nodejs, works with 0.10.21 -- a recent browser (optional) \ No newline at end of file From 997e3b99de09090be4469e6ebd4296599c1fc405 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:31:45 +0100 Subject: [PATCH 084/160] added .travis.yml --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..8e042d1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ + +script: "./runtests.py" +node_js: + - "0.11.9" +python: + - "3.3" \ No newline at end of file From 1a6dc0bf0072c915bfeef0c7e1905b6917a7c055 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:34:45 +0100 Subject: [PATCH 085/160] travis: update --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8e042d1..9148613 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ - -script: "./runtests.py" node_js: - "0.11.9" python: - - "3.3" \ No newline at end of file + - "3.3" +script: "./runtests.py" From 8eada68f5fc250cc42f53e02b89c22e4d72c9fdb Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:38:05 +0100 Subject: [PATCH 086/160] travis: update --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9148613..413e2f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ +language: node_js node_js: - - "0.11.9" -python: - - "3.3" + - "0.11" +before_install: +- sudo apt-get update +- sudo apt-get install python3 script: "./runtests.py" From 52d852aedaab61a0afcff0972388db5125580755 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:40:06 +0100 Subject: [PATCH 087/160] travis: update --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 413e2f2..a1941e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,6 @@ node_js: - "0.11" before_install: - sudo apt-get update -- sudo apt-get install python3 +- sudo apt-get install python3 python3-pip +- sudo pip3 install doctopt script: "./runtests.py" From 560ff9b1b574a0066ba7530242090707019b429a Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:43:26 +0100 Subject: [PATCH 088/160] travis: update --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a1941e9..660eeae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,6 @@ node_js: - "0.11" before_install: - sudo apt-get update -- sudo apt-get install python3 python3-pip -- sudo pip3 install doctopt +- sudo apt-get install python3 +- sudo easy_install-3.3 doctopt script: "./runtests.py" From 72a4d831d8ee8e43993774a1ce471e19bc39c446 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:44:18 +0100 Subject: [PATCH 089/160] runtests.py: return correct exit code in case of failure --- runtests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtests.py b/runtests.py index d3adceb..0b94616 100755 --- a/runtests.py +++ b/runtests.py @@ -101,3 +101,5 @@ def compare_output(expected, result): print('< {} PASS in {} mode :)'.format(test, mode)) print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) + if (ok_ctr - test_ctr) != 0: + return sys.exit(1) From d145a3a5c4e41867e0ba3199b3363492e862775f Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:45:20 +0100 Subject: [PATCH 090/160] README.rst: add travis link --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 137a997..fc837d2 100644 --- a/README.rst +++ b/README.rst @@ -1,6 +1,8 @@ Pythonium ######### +.. image:: https://travis-ci.org/pythonium/pythonium.png?branch=master :target: https://travis-ci.org/pythonium/pythonium + **tldr**: Python 3 to Javascript translator written in Python that produces fast portable javascript code. Read the `tutorial `_. From 1a796fb762b4ea06e08ec04482276915cbdaef64 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:47:10 +0100 Subject: [PATCH 091/160] travis: update --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 660eeae..3e6a54e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,5 @@ node_js: before_install: - sudo apt-get update - sudo apt-get install python3 -- sudo easy_install-3.3 doctopt +- sudo easy_install-3.2 doctopt script: "./runtests.py" From 005eaab12782ff77783a3a7f2dac4b2e6fec45d2 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:49:08 +0100 Subject: [PATCH 092/160] HACKING: FIXME --- HACKING.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/HACKING.rst b/HACKING.rst index 4695fa6..f581938 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -47,6 +47,11 @@ Translate your ``app.py`` with ``pythonium app.py > app.py.js`` include both in cat pythonium.js app.py.js | nodejs +Veloce mode +----------- + +FIXME + Development workflow ==================== @@ -101,8 +106,14 @@ This can not be automated in Veloce, but it's done in compliant mode. Translations ^^^^^^^^^^^^ +FIXME + Compliant mode -------------- +FIXME + Translations ^^^^^^^^^^^^ + +FIXME From 9d8cfe57ce7829af381d3789fb18ff8bbe1e5092 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:50:19 +0100 Subject: [PATCH 093/160] README: small update --- README.rst | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/README.rst b/README.rst index fc837d2..af04645 100644 --- a/README.rst +++ b/README.rst @@ -83,9 +83,10 @@ Pythonium exists in two flavors, each with their own strengths and performance c - Support of ``from ... import ...`` via `requirejs `_ - Support of single inheritance classes via `classy `_ [1][2] -Also there is `cookbook `_. +[1] Nested class definition are not supported +[2] Calling super method is done with ``super(arg0, arg1, arg2, ...)`` -- Pythonium **Compliant** 100% compliant with CPython 3 +- Pythonium **Compliant** All the above and 100% compliant with CPython 3 How? (1 minute) =============== @@ -99,19 +100,11 @@ Want to help? (30 seconds) - `Follow the project on twitter `_ - `Join the mailling list `_ -Documentation -============= - -Documentation is available in the `wiki `_. - Licensing ========= LGPL 2.1 or later -- [1] Nested class definition are not supported -- [2] Calling super method is done with ``super(arg0, arg1, arg2, ...)`` - .. image:: https://d2weczhvl823v0.cloudfront.net/pythonium/pythonium/trend.png :alt: Bitdeli badge :target: https://bitdeli.com/free From eef231a33bb8d8850e817f596c4eb2c089c0cf49 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:53:33 +0100 Subject: [PATCH 094/160] travis: update --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3e6a54e..3d848a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,6 @@ node_js: - "0.11" before_install: - sudo apt-get update -- sudo apt-get install python3 -- sudo easy_install-3.2 doctopt +- sudo apt-get install python3 python3-setuptools +- sudo easy_install3 docopt script: "./runtests.py" From b48c269cbd856e5b88ca025ed0c3fd8db0570d64 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 13:55:35 +0100 Subject: [PATCH 095/160] runtests: return is not required --- runtests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtests.py b/runtests.py index 0b94616..0043dcd 100755 --- a/runtests.py +++ b/runtests.py @@ -102,4 +102,4 @@ def compare_output(expected, result): print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) if (ok_ctr - test_ctr) != 0: - return sys.exit(1) + sys.exit(1) From ec025f514b98a4710ef6bfe1b05b19ec9de04cc6 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 16:32:16 +0100 Subject: [PATCH 096/160] runtests: replace nodejs command by node --- runtests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtests.py b/runtests.py index 0043dcd..4aedab7 100755 --- a/runtests.py +++ b/runtests.py @@ -73,7 +73,7 @@ def compare_output(expected, result): continue try: - result = check_output(['nodejs', '--harmony', exec_script], stderr=STDOUT) + result = check_output(['node', '--harmony', exec_script], stderr=STDOUT) except CalledProcessError as err: print(err.output.decode(errors='replace')) print('< {} ERROR in {} mode :('.format(test, mode)) From 5c6effe75d9f6ae46991b15604bd1cec902916c9 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 19:10:05 +0100 Subject: [PATCH 097/160] rework repository layout --- pythonium/compliant/{lib => builtins}/__init__.py | 0 pythonium/compliant/{lib => builtins}/bool.py | 0 pythonium/compliant/{lib => builtins}/dict.py | 0 pythonium/compliant/{lib => builtins}/exceptions.py | 0 pythonium/compliant/{lib => builtins}/float.py | 0 .../compliant/{lib/builtins.py => builtins/func.py} | 0 pythonium/compliant/{lib => builtins}/int.py | 0 pythonium/compliant/{lib => builtins}/iterator.py | 0 pythonium/compliant/{lib => builtins}/list.py | 0 pythonium/compliant/{lib => builtins}/none.py | 0 pythonium/compliant/{lib => builtins}/slice.py | 0 pythonium/compliant/{lib => builtins}/str.py | 0 pythonium/compliant/{lib => }/runtime.py | 0 pythonium/main.py | 11 ++++++----- 14 files changed, 6 insertions(+), 5 deletions(-) rename pythonium/compliant/{lib => builtins}/__init__.py (100%) rename pythonium/compliant/{lib => builtins}/bool.py (100%) rename pythonium/compliant/{lib => builtins}/dict.py (100%) rename pythonium/compliant/{lib => builtins}/exceptions.py (100%) rename pythonium/compliant/{lib => builtins}/float.py (100%) rename pythonium/compliant/{lib/builtins.py => builtins/func.py} (100%) rename pythonium/compliant/{lib => builtins}/int.py (100%) rename pythonium/compliant/{lib => builtins}/iterator.py (100%) rename pythonium/compliant/{lib => builtins}/list.py (100%) rename pythonium/compliant/{lib => builtins}/none.py (100%) rename pythonium/compliant/{lib => builtins}/slice.py (100%) rename pythonium/compliant/{lib => builtins}/str.py (100%) rename pythonium/compliant/{lib => }/runtime.py (100%) diff --git a/pythonium/compliant/lib/__init__.py b/pythonium/compliant/builtins/__init__.py similarity index 100% rename from pythonium/compliant/lib/__init__.py rename to pythonium/compliant/builtins/__init__.py diff --git a/pythonium/compliant/lib/bool.py b/pythonium/compliant/builtins/bool.py similarity index 100% rename from pythonium/compliant/lib/bool.py rename to pythonium/compliant/builtins/bool.py diff --git a/pythonium/compliant/lib/dict.py b/pythonium/compliant/builtins/dict.py similarity index 100% rename from pythonium/compliant/lib/dict.py rename to pythonium/compliant/builtins/dict.py diff --git a/pythonium/compliant/lib/exceptions.py b/pythonium/compliant/builtins/exceptions.py similarity index 100% rename from pythonium/compliant/lib/exceptions.py rename to pythonium/compliant/builtins/exceptions.py diff --git a/pythonium/compliant/lib/float.py b/pythonium/compliant/builtins/float.py similarity index 100% rename from pythonium/compliant/lib/float.py rename to pythonium/compliant/builtins/float.py diff --git a/pythonium/compliant/lib/builtins.py b/pythonium/compliant/builtins/func.py similarity index 100% rename from pythonium/compliant/lib/builtins.py rename to pythonium/compliant/builtins/func.py diff --git a/pythonium/compliant/lib/int.py b/pythonium/compliant/builtins/int.py similarity index 100% rename from pythonium/compliant/lib/int.py rename to pythonium/compliant/builtins/int.py diff --git a/pythonium/compliant/lib/iterator.py b/pythonium/compliant/builtins/iterator.py similarity index 100% rename from pythonium/compliant/lib/iterator.py rename to pythonium/compliant/builtins/iterator.py diff --git a/pythonium/compliant/lib/list.py b/pythonium/compliant/builtins/list.py similarity index 100% rename from pythonium/compliant/lib/list.py rename to pythonium/compliant/builtins/list.py diff --git a/pythonium/compliant/lib/none.py b/pythonium/compliant/builtins/none.py similarity index 100% rename from pythonium/compliant/lib/none.py rename to pythonium/compliant/builtins/none.py diff --git a/pythonium/compliant/lib/slice.py b/pythonium/compliant/builtins/slice.py similarity index 100% rename from pythonium/compliant/lib/slice.py rename to pythonium/compliant/builtins/slice.py diff --git a/pythonium/compliant/lib/str.py b/pythonium/compliant/builtins/str.py similarity index 100% rename from pythonium/compliant/lib/str.py rename to pythonium/compliant/builtins/str.py diff --git a/pythonium/compliant/lib/runtime.py b/pythonium/compliant/runtime.py similarity index 100% rename from pythonium/compliant/lib/runtime.py rename to pythonium/compliant/runtime.py diff --git a/pythonium/main.py b/pythonium/main.py index 47237f9..a1b2231 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -32,19 +32,20 @@ def main(argv=None): args = docopt(__doc__, argv, version='pythonium ' + __version__) if args['--generate']: # call ourself for each file in pythonium.lib: - from pythonium.compliant import lib + from pythonium import compliant + from pythonium.compliant import builtins # runtime is built separatly # it must appear first in the file # and it must be built using veloce mode - path = lib.__path__[0] + path = compliant.__path__[0] argv = ['--veloce', os.path.join(path, 'runtime.py')] main(argv) - for path in lib.__path__: + + # compile builtins + for path in builtins.__path__: for name in os.listdir(path): if name.endswith('.py'): - if name == 'runtime.py': - continue argv = [os.path.join(path, name)] main(argv) return From bd669284484827d1ad33d93e4e53bd1e435f501e Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 19:15:17 +0100 Subject: [PATCH 098/160] runtests: small fix --- runtests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtests.py b/runtests.py index 4aedab7..e175f53 100755 --- a/runtests.py +++ b/runtests.py @@ -48,11 +48,11 @@ def compare_output(expected, result): print('* Running tests for {} mode'.format(mode)) for test in os.listdir(TESTS_ROOT): if test.endswith('.py'): - print('< Running {} in {} mode.'.format(test, mode)) # compliant mode must run any code even code written for veloce mode # but veloce mode can not run compliant tests if test.startswith('compliant-') and mode != 'compliant': continue + print('< Running {} in {} mode.'.format(test, mode)) test_ctr += 1 filepath = os.path.join(TESTS_ROOT, test) if not test.startswith('compliant-'): From 182fd20cfc802770ab56e3675d3275006ce1f947 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 19:19:13 +0100 Subject: [PATCH 099/160] compliant: builtins: implement abs --- pythonium/compliant/builtins/float.py | 67 +++++++++++++++++++++++++-- pythonium/compliant/builtins/func.py | 5 +- pythonium/compliant/builtins/int.py | 13 ++++-- 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/pythonium/compliant/builtins/float.py b/pythonium/compliant/builtins/float.py index 522a3c5..7c7630a 100644 --- a/pythonium/compliant/builtins/float.py +++ b/pythonium/compliant/builtins/float.py @@ -8,11 +8,15 @@ def __hash__(self): def __repr__(self): return str(self.jsobject.toString()) - - def __div__(self, other): - a = self.jsobject - b = other.jsobject - return float(jscode('a / b')) + + def __neg__(self): + jsobject = self.jsobject + return int(jscode('-self.jsobject')) + + def __abs__(self): + if self < 0: + return -self + return self def __sub__(self, other): a = self.jsobject @@ -25,3 +29,56 @@ def __eq__(self, other): if jscode('a == b'): return True return False + + def __add__(self, other): + a = self.jsobject + b = other.jsobject + return int(jscode('a + b')) + + def __lt__(self, other): + a = self.jsobject + b = other.jsobject + if jscode('a < b'): + return True + return False + + def __gt__(self, other): + a = self.jsobject + b = other.jsobject + if jscode('a > b'): + return True + return False + + def __gte__(self, other): + a = self.jsobject + b = other.jsobject + if jscode('a >= b'): + return True + return False + + def __lte__(self, other): + a = self.jsobject + b = other.jsobject + if jscode('a <= b'): + return True + return False + + def __mul__(self, other): + a = self.jsobject + b = other.jsobject + c = jscode('a * b') + return int(c) + + def __or__(self, other): + a = self.jsobject + b = other.jsobject + c = jscode('a || b') + return int(c) + + def __neq__(self, other): + return not self.__eq__(other) + + def __div__(self, other): + a = self.jsobject + b = other.jsobject + return int(jscode('a / b')) diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index 79cbaa4..b188b8f 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -49,9 +49,8 @@ def next(obj): return jscode('r.value') return obj.__next__() - def len(obj): return obj.__len__() - - +def abs(obj): + return obj.__abs__() diff --git a/pythonium/compliant/builtins/int.py b/pythonium/compliant/builtins/int.py index d217d82..5887319 100644 --- a/pythonium/compliant/builtins/int.py +++ b/pythonium/compliant/builtins/int.py @@ -9,6 +9,15 @@ def __not__(self): return True return False + def __abs__(self): + if self < 0: + return -self + return self + + def __neg__(self): + jsobject = self.jsobject + return int(jscode('-self.jsobject')) + def __hash__(self): return str(self.jsobject) @@ -78,10 +87,6 @@ def __eq__(self, other): def __neq__(self, other): return not self.__eq__(other) - def __neg__(self): - jsobject = self.jsobject - return int(jscode('-jsobject')) - def __div__(self, other): a = self.jsobject b = other.jsobject From ccdf25b77855c9794db696d2088ab91d4689fa46 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 19:23:10 +0100 Subject: [PATCH 100/160] compliant: builtins: implement all --- pythonium/compliant/builtins/bool.py | 2 +- pythonium/compliant/builtins/func.py | 11 +++++++++++ pythonium/compliant/builtins/list.py | 3 +++ pythonium/compliant/builtins/none.py | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/pythonium/compliant/builtins/bool.py b/pythonium/compliant/builtins/bool.py index 841f246..be060a6 100644 --- a/pythonium/compliant/builtins/bool.py +++ b/pythonium/compliant/builtins/bool.py @@ -9,7 +9,7 @@ def __jstype__(self): def __repr__(self): if self.jsobject: return 'True' - return False + return 'False' def __and__(self, other): if self: diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index b188b8f..33b68e8 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -29,6 +29,7 @@ def map(func, objects): out.append(func(obj)) return out + def jstype(obj): return obj.__jstype__() @@ -36,6 +37,7 @@ def jstype(obj): def hash(obj): return obj.__hash__() + def iter(obj): return obj.__iter__() @@ -49,8 +51,17 @@ def next(obj): return jscode('r.value') return obj.__next__() + def len(obj): return obj.__len__() + def abs(obj): return obj.__abs__() + + +def all(iterable): + for element in iterable: + if not element: + return False + return True diff --git a/pythonium/compliant/builtins/list.py b/pythonium/compliant/builtins/list.py index 08751dd..187ec09 100644 --- a/pythonium/compliant/builtins/list.py +++ b/pythonium/compliant/builtins/list.py @@ -5,6 +5,9 @@ def __init__(self, obj): self.index = 0 self.length = len(obj) + def __iter__(self): + return self + def __next__(self): if self.index == self.length: raise StopIteration diff --git a/pythonium/compliant/builtins/none.py b/pythonium/compliant/builtins/none.py index 11ad491..6b204c4 100644 --- a/pythonium/compliant/builtins/none.py +++ b/pythonium/compliant/builtins/none.py @@ -18,5 +18,8 @@ def __is__(self, other): def __neg__(self): return True + def __not__(self): + return True + __NONE = _None() From d0b44a43becc0415145eebefb7e6b2ca5e918a65 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 19:24:56 +0100 Subject: [PATCH 101/160] tests: missing tests from two previous commits --- tests/compliant-abs.py | 7 +++++++ tests/compliant-all.py | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/compliant-abs.py create mode 100644 tests/compliant-all.py diff --git a/tests/compliant-abs.py b/tests/compliant-abs.py new file mode 100644 index 0000000..6b81ac3 --- /dev/null +++ b/tests/compliant-abs.py @@ -0,0 +1,7 @@ +a = abs(-2) +b = abs(2) +c = abs(-2.2) +d = abs(3.3) +e = abs(0) +f = abs(-0) +print(a, b, c, d, e, f) diff --git a/tests/compliant-all.py b/tests/compliant-all.py new file mode 100644 index 0000000..a27cf65 --- /dev/null +++ b/tests/compliant-all.py @@ -0,0 +1,8 @@ +print(all([1, 2, 3, 4, 5, 6])) +print(all([])) +print(all([0])) +print(all([1, 2, None])) +print(all([1, 2, None])) +print(all([1, 2, False])) +print(all([True, True, True])) +print(all([True, True, False])) From 9c13fd68b229a9f8ba3906b3683d5a41df2a82e3 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 19:33:17 +0100 Subject: [PATCH 102/160] tests: rework repository --- runtests.py | 126 ++++++++++-------- tests/{compliant-abs.py => compliant/abs.py} | 0 tests/{compliant-all.py => compliant/all.py} | 0 .../assert.py} | 0 .../print.py} | 0 .../what-is-true.py} | 0 .../yield.py} | 0 7 files changed, 67 insertions(+), 59 deletions(-) rename tests/{compliant-abs.py => compliant/abs.py} (100%) rename tests/{compliant-all.py => compliant/all.py} (100%) rename tests/{compliant-assert.py => compliant/assert.py} (100%) rename tests/{compliant-print.py => compliant/print.py} (100%) rename tests/{compliant-what-is-true.py => compliant/what-is-true.py} (100%) rename tests/{compliant-yield.py => compliant/yield.py} (100%) diff --git a/runtests.py b/runtests.py index e175f53..81f2f8a 100755 --- a/runtests.py +++ b/runtests.py @@ -4,6 +4,7 @@ import difflib from io import StringIO from traceback import print_exc +from itertools import chain from subprocess import STDOUT from subprocess import check_output @@ -16,6 +17,18 @@ ROOT = os.path.abspath(os.path.dirname(__file__)) TESTS_ROOT = os.path.join(ROOT, 'tests') +COMPLIANT_TESTS_ROOT = os.path.join(TESTS_ROOT, 'compliant') + +# generate pythonium compliant library +stdout = sys.stdout +sys.stdout = StringIO() +main(['--generate']) +COMPLIANTJS = sys.stdout.getvalue() +sys.stdout = stdout + + +# init counts +ok_ctr = test_ctr = 0 def compare_output(expected, result): @@ -30,76 +43,71 @@ def compare_output(expected, result): return list(diffs) +def run(test, filepath, mode): + global ok_ctr, test_ctr + print('< Running {} in {} mode.'.format(test, mode)) + test_ctr += 1 + ext = 'exec-{}.js'.format(mode) + exec_script = os.path.join(TMPDIR, test + ext) + with open(exec_script, 'w') as f: + try: + if mode =='veloce': + veloce_generate_js(filepath, output=f) + else: + f.write(COMPLIANTJS) + compliant_generate_js(filepath, output=f) + except Exception as exc: + print_exc() + print('< Translating {} in {} mode failed with the above exception.'.format(test, mode)) + return + + try: + result = check_output(['node', '--harmony', exec_script], stderr=STDOUT) + except CalledProcessError as err: + print(err.output.decode(errors='replace')) + print('< {} ERROR in {} mode :('.format(test, mode)) + return + + expected_file = os.path.join(TESTS_ROOT, test+'.expected') + if os.path.exists(expected_file): + with open(expected_file, 'br') as f: + expected = f.read() + else: + try: + expected = check_output(['python3', filepath], stderr=STDOUT) + except CalledProcessError as err: + print(err.output.decode(errors='replace')) + print('< {} PYTHON ERROR :('.format(test)) + return + + diffs = compare_output(expected, result) + if diffs: + for line in diffs: + print(line) + print('< {} FAILED in {} mode :('.format(test, mode)) + else: + ok_ctr += 1 + print('< {} PASS in {} mode :)'.format(test, mode)) + + if __name__ == '__main__': - ok_ctr = test_ctr = 0 + TMPDIR = os.path.join(TESTS_ROOT, 'tmp') try: os.mkdir(TMPDIR) except OSError: pass - - stdout = sys.stdout - sys.stdout = StringIO() - main(['--generate']) - COMPLIANTJS = sys.stdout.getvalue() - sys.stdout = stdout - + for mode in ('veloce', 'compliant'): print('* Running tests for {} mode'.format(mode)) for test in os.listdir(TESTS_ROOT): if test.endswith('.py'): - # compliant mode must run any code even code written for veloce mode - # but veloce mode can not run compliant tests - if test.startswith('compliant-') and mode != 'compliant': - continue - print('< Running {} in {} mode.'.format(test, mode)) - test_ctr += 1 filepath = os.path.join(TESTS_ROOT, test) - if not test.startswith('compliant-'): - ext = 'exec-{}.js'.format(mode) - else: - ext = 'exec.js'.format(mode) - exec_script = os.path.join(TMPDIR, test + ext) - with open(exec_script, 'w') as f: - try: - if mode =='veloce': - veloce_generate_js(filepath, output=f) - else: - f.write(COMPLIANTJS) - compliant_generate_js(filepath, output=f) - except Exception as exc: - print_exc() - print('< Translating {} in {} mode failed with the above exception.'.format(test, mode)) - continue - - try: - result = check_output(['node', '--harmony', exec_script], stderr=STDOUT) - except CalledProcessError as err: - print(err.output.decode(errors='replace')) - print('< {} ERROR in {} mode :('.format(test, mode)) - continue - - expected_file = os.path.join(TESTS_ROOT, test+'.expected') - if os.path.exists(expected_file): - with open(expected_file, 'br') as f: - expected = f.read() - else: - try: - expected = check_output(['python3', filepath], stderr=STDOUT) - except CalledProcessError as err: - print(err.output.decode(errors='replace')) - print('< {} PYTHON ERROR :('.format(test)) - continue - - diffs = compare_output(expected, result) - if diffs: - for line in diffs: - print(line) - print('< {} FAILED in {} mode :('.format(test, mode)) - else: - ok_ctr += 1 - print('< {} PASS in {} mode :)'.format(test, mode)) - + run(test, filepath, mode) + for test in os.listdir(COMPLIANT_TESTS_ROOT): + if test.endswith('.py'): + filepath = os.path.join(COMPLIANT_TESTS_ROOT, test) + run(test, filepath, mode) print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) if (ok_ctr - test_ctr) != 0: sys.exit(1) diff --git a/tests/compliant-abs.py b/tests/compliant/abs.py similarity index 100% rename from tests/compliant-abs.py rename to tests/compliant/abs.py diff --git a/tests/compliant-all.py b/tests/compliant/all.py similarity index 100% rename from tests/compliant-all.py rename to tests/compliant/all.py diff --git a/tests/compliant-assert.py b/tests/compliant/assert.py similarity index 100% rename from tests/compliant-assert.py rename to tests/compliant/assert.py diff --git a/tests/compliant-print.py b/tests/compliant/print.py similarity index 100% rename from tests/compliant-print.py rename to tests/compliant/print.py diff --git a/tests/compliant-what-is-true.py b/tests/compliant/what-is-true.py similarity index 100% rename from tests/compliant-what-is-true.py rename to tests/compliant/what-is-true.py diff --git a/tests/compliant-yield.py b/tests/compliant/yield.py similarity index 100% rename from tests/compliant-yield.py rename to tests/compliant/yield.py From 069f76bb3fc9a1998417bd306e6e4847e5e4a1b3 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 19:35:19 +0100 Subject: [PATCH 103/160] compliant: builtins: implement any --- pythonium/compliant/builtins/func.py | 7 +++++++ tests/compliant/any.py | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/compliant/any.py diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index 33b68e8..004b5df 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -65,3 +65,10 @@ def all(iterable): if not element: return False return True + + +def any(iterable): + for element in iterable: + if element: + return True + return False diff --git a/tests/compliant/any.py b/tests/compliant/any.py new file mode 100644 index 0000000..edfa08c --- /dev/null +++ b/tests/compliant/any.py @@ -0,0 +1,7 @@ +print(any([])) +print(any([False, False, True, False])) +print(any([False, False, False, False])) +print(any([False, None, False, False])) +print(any([True, True, True, True])) +print(any([[], {}, False, None])) +print(any([[], {}, [1], False, None])) From 3b34b95800d236efba55e0c259ab6a994a5ea1a5 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 19:39:24 +0100 Subject: [PATCH 104/160] removed useless file --- pythonium/compliant/builtins/iterator.py | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 pythonium/compliant/builtins/iterator.py diff --git a/pythonium/compliant/builtins/iterator.py b/pythonium/compliant/builtins/iterator.py deleted file mode 100644 index e56260d..0000000 --- a/pythonium/compliant/builtins/iterator.py +++ /dev/null @@ -1,4 +0,0 @@ -class iterator: - - def __init__(self, list): - pass From f1069fec54c1ffa0368fd9ebdbb85221a141e90b Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 19:57:38 +0100 Subject: [PATCH 105/160] compliant: builtins: implemented bool as func --- pythonium/compliant/builtins/bool.py | 5 ++++- pythonium/compliant/builtins/dict.py | 4 +--- tests/compliant/bool-as-a-function.py | 9 +++++++++ tests/compliant/bool-must-inherit-int.py | 2 ++ 4 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 tests/compliant/bool-as-a-function.py create mode 100644 tests/compliant/bool-must-inherit-int.py diff --git a/pythonium/compliant/builtins/bool.py b/pythonium/compliant/builtins/bool.py index be060a6..9bd49e1 100644 --- a/pythonium/compliant/builtins/bool.py +++ b/pythonium/compliant/builtins/bool.py @@ -1,7 +1,10 @@ class bool: def __init__(self, obj): - self.jsobject = pythonium_is_true(obj) + if jscode('obj !== undefined'): + self.jsobject = pythonium_is_true(obj) + else: + self.jsobject = pythonium_is_true(jscode('false')) def __jstype__(self): return self.jsobject diff --git a/pythonium/compliant/builtins/dict.py b/pythonium/compliant/builtins/dict.py index a8225e1..88f5159 100644 --- a/pythonium/compliant/builtins/dict.py +++ b/pythonium/compliant/builtins/dict.py @@ -9,11 +9,9 @@ def nest_str_with_quotes(s): class dict: - def __init__(self, **kwargs): + def __init__(self): self._keys = list() self.jsobject = JSObject() - for key in kwargs.keys(): - self[key] = kwargs[key] def __hash__(self): raise TypeError("unhashable type: 'dict'") diff --git a/tests/compliant/bool-as-a-function.py b/tests/compliant/bool-as-a-function.py new file mode 100644 index 0000000..8845d13 --- /dev/null +++ b/tests/compliant/bool-as-a-function.py @@ -0,0 +1,9 @@ +print(bool([])) +print(bool({})) +print(bool(1)) +print(bool(0)) +print(bool(True)) +print(bool()) +print(bool(False)) +print(bool([1,2,3])) +print(bool({1: 2})) diff --git a/tests/compliant/bool-must-inherit-int.py b/tests/compliant/bool-must-inherit-int.py new file mode 100644 index 0000000..2c5819d --- /dev/null +++ b/tests/compliant/bool-must-inherit-int.py @@ -0,0 +1,2 @@ +print(isinstance(True, int)) +print(isinstance(False, int)) From 9ddc7c572d2284e081c65a8c84c7ed2576909db4 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 20:13:36 +0100 Subject: [PATCH 106/160] compliant: builtins: implemented callable --- pythonium/compliant/builtins/func.py | 12 ++++++++++++ pythonium/compliant/runtime.py | 2 ++ tests/compliant/callable.py | 25 +++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 tests/compliant/callable.py diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index 004b5df..74874fe 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -72,3 +72,15 @@ def any(iterable): if element: return True return False + + +def callable(obj): + if jscode("Object.toString.call(obj) ==='[object Function]'"): + return True + if jscode('obj.next'): + return True + if obj.__class__: + return True + if jscode("lookup(obj, '__call__')"): + return True + return False diff --git a/pythonium/compliant/runtime.py b/pythonium/compliant/runtime.py index ffb1197..4002a8b 100644 --- a/pythonium/compliant/runtime.py +++ b/pythonium/compliant/runtime.py @@ -51,6 +51,8 @@ def pythonium_is_true(v): return False if v is True: return True + if v is None: + return False if v is __NONE: return False if v is __FALSE: diff --git a/tests/compliant/callable.py b/tests/compliant/callable.py new file mode 100644 index 0000000..c46416c --- /dev/null +++ b/tests/compliant/callable.py @@ -0,0 +1,25 @@ +print(callable(abs)) +print(callable(int)) +print(callable(True)) +print(callable(bool)) + +class GenerateCallable: + + def __call__(self): + return 42 + +print(callable(GenerateCallable)) +print(callable(GenerateCallable())) + +class GenerateNonCallable: + pass + +print(callable(GenerateNonCallable)) +print(callable(GenerateNonCallable())) + + +def generator(): + yield 42 + +print(callable(generator)) +print(callable(generator())) From ec3c85b78de07b0c60990d54956ec71f7aa2391c Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 20:15:15 +0100 Subject: [PATCH 107/160] compliant: builtins: added classmethod & staticmethod --- pythonium/compliant/builtins/func.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index 74874fe..7638bb5 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -84,3 +84,14 @@ def callable(obj): if jscode("lookup(obj, '__call__')"): return True return False + + +def classmethod(func): + func.classmethod = True + return func + + +def staticmethod(func): + func.staticmethod = True + return func + From eabe73e7806a99034c2610583b310ddb1d5b79bc Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 20:22:07 +0100 Subject: [PATCH 108/160] compliant: builtins: added enumerate --- pythonium/compliant/builtins/exceptions.py | 4 ++++ pythonium/compliant/builtins/func.py | 14 +++++++++++++- tests/compliant/enumerate.py | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/compliant/enumerate.py diff --git a/pythonium/compliant/builtins/exceptions.py b/pythonium/compliant/builtins/exceptions.py index ea197c2..cf3439e 100644 --- a/pythonium/compliant/builtins/exceptions.py +++ b/pythonium/compliant/builtins/exceptions.py @@ -24,5 +24,9 @@ class NotImplementedError(Exception): pass +class NotImplemented(Exception): + pass + + class ValueError(Exception): pass diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index 7638bb5..24d8d00 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -94,4 +94,16 @@ def classmethod(func): def staticmethod(func): func.staticmethod = True return func - + + +class enumerate: + + def __init__(self, iterator): + self.iterator = iterator + self.index = 0 + + def __iter__(self): + return self + + def __next__(self): + return (index, next(self.iterator) diff --git a/tests/compliant/enumerate.py b/tests/compliant/enumerate.py new file mode 100644 index 0000000..4225dab --- /dev/null +++ b/tests/compliant/enumerate.py @@ -0,0 +1 @@ +print(list(enumerate(['A', 'B', 'C']))) From c63b16b28da5cdcad326fe901a00ae1c0f9e0ae1 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 20:25:34 +0100 Subject: [PATCH 109/160] compliant: builtins: added getattr --- pythonium/compliant/builtins/func.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index 24d8d00..0814061 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -106,4 +106,15 @@ def __iter__(self): return self def __next__(self): - return (index, next(self.iterator) + return (index, next(self.iterator)) + + +def getattr(obj, attr, d): + r = lookup(obj, attr) + if jscode('r === undefined'): + if jscode('d === undefined'): + raise AttributeError + else: + return d + else: + return r From c2402abec1f59c16ab7a8017c5c589ab5951e4c3 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 20:30:08 +0100 Subject: [PATCH 110/160] compliant: builtins: rework map and range --- pythonium/compliant/builtins/func.py | 44 +++++++++++++++++++++------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index 0814061..3574cf5 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -1,10 +1,25 @@ +class range: + + def __init__(self, a, b=None): + if b: + self.index = a + self.end = b + else: + self.index = 0 + self.end = a + + def __iter__(self): + return self + + def __next__(self): + if self.index < self.end: + index = self.index + self.index += 1 + return index + raise StopIteartion + + def range(a, b=None): - if b: - index = a - end = b - else: - index = 0 - end = a out = list() while index < end: out.append(index) @@ -23,11 +38,18 @@ def print(*args): jscode('console.log.apply(console, out)') -def map(func, objects): - out = list() - for obj in objects: - out.append(func(obj)) - return out + +class map: + + def __init__(self, func, iterable): + self.func = func + self.iterable = iterable + + def __iter__(self): + return self + + def __next__(self): + return self.func(next(self.iterable)) def jstype(obj): From fa764cbf0b8210e67b6d917abfaa6bc914aba461 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 9 Dec 2013 20:58:15 +0100 Subject: [PATCH 111/160] typofix --- pythonium/compliant/builtins/func.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index 3574cf5..6e3be97 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -16,7 +16,7 @@ def __next__(self): index = self.index self.index += 1 return index - raise StopIteartion + raise StopIteration def range(a, b=None): From d0c76ecc00c4e2932722d3468255fb93edd25493 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 01:31:43 +0100 Subject: [PATCH 112/160] tests: added tests about transparent javascript calling in the two modes --- tests/compliant/transparent-javascript-calling.py | 7 +++++++ tests/compliant/transparent-javascript-calling.py.expected | 1 + tests/transparent-javascript-calling.py | 1 + tests/transparent-javascript-calling.py.expected | 1 + 4 files changed, 10 insertions(+) create mode 100644 tests/compliant/transparent-javascript-calling.py create mode 100644 tests/compliant/transparent-javascript-calling.py.expected create mode 100644 tests/transparent-javascript-calling.py create mode 100644 tests/transparent-javascript-calling.py.expected diff --git a/tests/compliant/transparent-javascript-calling.py b/tests/compliant/transparent-javascript-calling.py new file mode 100644 index 0000000..1c87afc --- /dev/null +++ b/tests/compliant/transparent-javascript-calling.py @@ -0,0 +1,7 @@ +class A: + + def __init__(self): + self.jsobject = jscode('"Héllo"') + console.log(self.jsobject.length) + +A() diff --git a/tests/compliant/transparent-javascript-calling.py.expected b/tests/compliant/transparent-javascript-calling.py.expected new file mode 100644 index 0000000..7813681 --- /dev/null +++ b/tests/compliant/transparent-javascript-calling.py.expected @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/tests/transparent-javascript-calling.py b/tests/transparent-javascript-calling.py new file mode 100644 index 0000000..a76cbee --- /dev/null +++ b/tests/transparent-javascript-calling.py @@ -0,0 +1 @@ +console.log(jstype('Héllo')) diff --git a/tests/transparent-javascript-calling.py.expected b/tests/transparent-javascript-calling.py.expected new file mode 100644 index 0000000..d63b967 --- /dev/null +++ b/tests/transparent-javascript-calling.py.expected @@ -0,0 +1 @@ +Héllo \ No newline at end of file From 266dd415d289bd49a8abd9febbf040e498eba2f2 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 01:36:45 +0100 Subject: [PATCH 113/160] compliant: wip mro --- pythonium/compliant/builtins/bool.py | 4 +- pythonium/compliant/builtins/float.py | 3 +- pythonium/compliant/builtins/func.py | 20 +++- pythonium/compliant/builtins/int.py | 3 +- pythonium/compliant/builtins/list.py | 6 +- pythonium/compliant/builtins/str.py | 23 +++-- pythonium/compliant/compliant.py | 7 +- pythonium/compliant/runtime.py | 127 +++++++++++++++----------- pythonium/veloce/veloce.py | 2 + runtests.py | 30 ++++-- tests/compliant/mro.py | 39 ++++++++ 11 files changed, 180 insertions(+), 84 deletions(-) create mode 100644 tests/compliant/mro.py diff --git a/pythonium/compliant/builtins/bool.py b/pythonium/compliant/builtins/bool.py index 9bd49e1..fabf8d3 100644 --- a/pythonium/compliant/builtins/bool.py +++ b/pythonium/compliant/builtins/bool.py @@ -4,7 +4,7 @@ def __init__(self, obj): if jscode('obj !== undefined'): self.jsobject = pythonium_is_true(obj) else: - self.jsobject = pythonium_is_true(jscode('false')) + self.jsobject = jscode('false') def __jstype__(self): return self.jsobject @@ -44,4 +44,4 @@ def __not__(self): __TRUE = bool(jscode('true')) -__FALSE = bool(jscode('false')) +__FALSE = bool() diff --git a/pythonium/compliant/builtins/float.py b/pythonium/compliant/builtins/float.py index 7c7630a..1fcd291 100644 --- a/pythonium/compliant/builtins/float.py +++ b/pythonium/compliant/builtins/float.py @@ -7,7 +7,8 @@ def __hash__(self): return str(self.jsobject) def __repr__(self): - return str(self.jsobject.toString()) + jsobject = self.jsobject + return str(jscode('jsobject.toString()')) def __neg__(self): jsobject = self.jsobject diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index 6e3be97..f9d8199 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -28,13 +28,22 @@ def range(a, b=None): def repr(obj): + if obj is object: + return "" return obj.__repr__() def print(*args): out = JSArray() for arg in args: - out.push(jstype(repr(arg))) + if jscode('arg.__class__ !== undefined'): + r = jstype(repr(arg)) + jscode('out.push(r)') + elif jscode('arg.__metaclass__ !== undefined'): + name = jscode('arg.__name__') + jscode("""out.push("")""") + else: + jscode('out.push(arg)') jscode('console.log.apply(console, out)') @@ -43,13 +52,18 @@ class map: def __init__(self, func, iterable): self.func = func - self.iterable = iterable + self.iterable = iter(iterable) def __iter__(self): return self def __next__(self): - return self.func(next(self.iterable)) + n = next(self.iterable) + r = self.func(n) + return r + + def __repr__(self): + return '' def jstype(obj): diff --git a/pythonium/compliant/builtins/int.py b/pythonium/compliant/builtins/int.py index 5887319..08628f3 100644 --- a/pythonium/compliant/builtins/int.py +++ b/pythonium/compliant/builtins/int.py @@ -25,7 +25,8 @@ def __jstype__(self): return self.jsobject def __repr__(self): - return str(self.jsobject.toString()) + jsobject = self.jsobject + return str(jscode('jsobject.toString()')) def __add__(self, other): a = self.jsobject diff --git a/pythonium/compliant/builtins/list.py b/pythonium/compliant/builtins/list.py index 187ec09..b3b16be 100644 --- a/pythonium/compliant/builtins/list.py +++ b/pythonium/compliant/builtins/list.py @@ -11,8 +11,9 @@ def __iter__(self): def __next__(self): if self.index == self.length: raise StopIteration + index = self.index self.index = self.index + 1 - return self.list[self.index - 1] + return self.list[index] class list: @@ -24,7 +25,8 @@ def __hash__(self): raise TypeError("unhashable type: 'list'") def __repr__(self): - return "[" + ", ".join(map(repr, self)) + "]" + iterable = map(repr, self) + return "[" + ", ".join(iterable) + "]" def __jstype__(self): out = JSArray() diff --git a/pythonium/compliant/builtins/str.py b/pythonium/compliant/builtins/str.py index 7bda752..cc2f7bb 100644 --- a/pythonium/compliant/builtins/str.py +++ b/pythonium/compliant/builtins/str.py @@ -13,23 +13,21 @@ def __hash__(self): return '"' + self def __contains__(self, s): - if int(self.jsobject.indexOf(jstype(s))) != -1: + jsobject = self.jsobject + s = jstype(s) + i = jscode('jsobject.indexOf(s)') + if int(i) != -1: return True return False def __iter__(self): return ListIterator(self) - def join(self, objects): - L = len(objects) - if not L: - return "" - out = objects[0] - index = 1 - while index < L: - obj = objects[index] - out = out + self + obj - index += 1 + def join(self, iterable): + iterable = iter(iterable) + out = next(iterable) + for item in iterable: + out = out + self + item return out def __add__(self, other): @@ -38,7 +36,8 @@ def __add__(self, other): return str(jscode('a + b')) def __len__(self): - return int(self.jsobject.length) + jsobject = jscode('self.jsobject') + return int(jscode('jsobject.length')) def __lte__(self, other): a = self.jsobject diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 751f5c4..8f6ec9b 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -337,10 +337,15 @@ def retrieve_vars(body, vars=None): self.writer.pull() self.writer.write('};') + if self._is_inside_method_definition(): + self.writer.write('{}.is_method = true;'.format(name)) + for decorator in node.decorator_list: decorator = self.visit(decorator) self.writer.write('{} = {}({});'.format(name, decorator, name)) self._def_stack.pop() + + self.writer.write('') return node.name, name # Slice(expr? lower, expr? upper, expr? step) @@ -893,7 +898,7 @@ def visit_ClassDef(self, node): if len(self._def_stack) == 0: # module level definition must be exported self.__all__.append(node.name) if len(node.bases) == 0: - bases = ['__object'] + bases = ['object'] else: bases = map(self.visit, node.bases) bases = '[{}]'.format(', '.join(bases)) diff --git a/pythonium/compliant/runtime.py b/pythonium/compliant/runtime.py index 4002a8b..66cd555 100644 --- a/pythonium/compliant/runtime.py +++ b/pythonium/compliant/runtime.py @@ -1,41 +1,57 @@ -__object = {__bases__: [], __name__: 'object'} -__object.__mro__ = [__object] +object = {__bases__: [], __name__: 'object'} +object.__mro__ = [object] -__type = {__bases__: [__object], __mro__: [__object], __name__: 'type'} +type = {__bases__: [object], __mro__: [object], __name__: 'type'} -__object.__metaclass__ = __type +object.__metaclass__ = type __ARGUMENTS_PADDING__ = {ARGUMENTS_PADDING: "YES IT IS!"} -def __is__(self, other): - return (self is other) -__object.__is__ = __is__ +def __is__(me, other): + return (me is other) +__is__.is_method = True +object.__is__ = __is__ -def __isnot__(self, other): - return not (self is other) -__object.__isnot__ = __isnot__ +def __isnot__(me, other): + return not (me is other) +__isnot__.is_method = True +object.__isnot__ = __isnot__ +def mro(me): + if me is object: + raw = me.__mro__ + elif me.__class__: + raw = me.__class__.__mro__ + else: + raw = me.__metaclass__.__mro__ + l = pythonium_call(list) + l.jsobject = raw.slice() + return l +mro.is_method = True +object.mro = mro def __hash__(me): uid = lookup(me, 'uid') if not uid: - uid = __object._uid - __object._uid += 1 - self.__uid__ = uid + uid = object._uid + object._uid += 1 + me.__uid__ = uid return pythonium_call(str, '{' + uid) -__object._uid = 1 -__object.__hash__ = __hash__ +__hash__.is_method = True +object._uid = 1 +object.__hash__ = __hash__ def __rcontains__(me, other): contains = lookup(other, '__contains__') return contains(me) -__object.__rcontains__ = __rcontains__; +__rcontains__.is_method = True +object.__rcontains__ = __rcontains__ -def issubclass(klass, other): +def issubclass(klass, other): if klass is other: return True if not klass.__bases__: @@ -66,9 +82,9 @@ def pythonium_is_true(v): return True -def isinstance(object, klass): - if object.__class__: - return issubclass(object.__class__, klass) +def isinstance(obj, klass): + if obj.__class__: + return issubclass(obj.__class__, klass) return False def pythonium_obj_to_js_exception(obj): @@ -83,23 +99,23 @@ def pythonium_is_exception(obj, exc): return isinstance(obj, exc) -def pythonium_call(object): +def pythonium_call(obj): args = Array.prototype.slice.call(arguments, 1) - if object.__metaclass__: - instance = {__class__: object} + if obj.__metaclass__: + instance = {__class__: obj} init = lookup(instance, '__init__') if init: init.apply(instance, args) return instance else: - return object.apply(object, args) + return obj.apply(None, args) def pythonium_create_empty_dict(): instance = {__class__: dict} instance._keys = pythonium_call(list) instance.jsobject = JSObject() return instance - + def pythonium_mro(bases): """Calculate the Method Resolution Order of bases using the C3 algorithm. @@ -111,7 +127,7 @@ def pythonium_mro(bases): Another way of looking at this, if you pass a single class K, this will return the linearization of K (the MRO of K, *including* itself). """ - # based on http://code.activestate.com/recipes/577748-calculate-the-mro-of-a-class/ + #b ased on http://code.activestate.com/recipes/577748-calculate-the-mro-of-a-class/ seqs = [C.__mro__.slice() for C in bases] seqs.push(bases.slice()) @@ -151,12 +167,12 @@ def cdr(l): # Remove candidate. index = seq.indexOf(candidate) if index >= 0: - del seq[index] + seq[index] = None def pythonium_create_class(name, bases, attrs): attrs.__name__ = name - attrs.__metaclass__ = __type + attrs.__metaclass__ = type attrs.__bases__ = bases mro = pythonium_mro(bases) mro.splice(0, 0, attrs) @@ -164,60 +180,67 @@ def pythonium_create_class(name, bases, attrs): return attrs -def lookup(object, attr): - object_attr = object[attr] - if object_attr != None: - if object_attr and {}.toString.call(object_attr) == '[object Function]': +def lookup(obj, attr): + obj_attr = obj[attr] + if obj_attr != None: + if obj_attr and {}.toString.call(obj_attr) == '[object Function]' and obj_attr.is_method and not obj_attr.bound: def method_wrapper(): args = Array.prototype.slice.call(arguments) - args.splice(0, 0, object) - return object_attr.apply(None, args) + args.splice(0, 0, obj) + return obj_attr.apply(None, args) + method_wrapper.bound = True return method_wrapper - return object_attr + return obj_attr else: - for base in object.__class__.__mro__: + if obj.__class__: + __mro__ = obj.__class__.__mro__ + else: + __mro__ = obj.__metaclass__.__mro__ + for base in __mro__: class_attr = base[attr] if class_attr != None: - if {}.toString.call(class_attr) == '[object Function]': + if {}.toString.call(class_attr) == '[object Function]' and class_attr.is_method and not class_attr.bound: def method_wrapper(): args = Array.prototype.slice.call(arguments) - args.splice(0, 0, object) + args.splice(0, 0, obj) return class_attr.apply(None, args) + method_wrapper.bound = True return method_wrapper return class_attr -def pythonium_object_get_attribute(object, attr): - r = lookup(object, attr) +def pythonium_object_get_attribute(obj, attr): + r = lookup(obj, attr) if r != None: return r else: - getattr = lookup(object, '__getattr__') + getattr = lookup(obj, '__getattr__') if getattr: return getattr(attr) else: - console.trace('AttributeError', attr, object) + console.trace('AttributeError', attr, obj) raise AttributeError +pythonium_object_get_attribute.is_method = True +object.__getattribute__ = pythonium_object_get_attribute -__object.__getattribute__ = pythonium_object_get_attribute - -def pythonium_get_attribute(object, attr): - if object.__class__: - getattribute = lookup(object, '__getattribute__') - return getattribute(attr) - attr = object[attr] +def pythonium_get_attribute(obj, attr): + if obj.__class__ or obj.__metaclass__: + getattribute = lookup(obj, '__getattribute__') + r = getattribute(attr) + return r + attr = obj[attr] if attr: if {}.toString.call(attr) == '[object Function]': def method_wrapper(): - return attr.apply(object, arguments) + return attr.apply(obj, arguments) return method_wrapper else: return attr -def pythonium_set_attribute(object, attr, value): - object[attr] = value +def pythonium_set_attribute(obj, attr, value): + obj[attr] = value def ASSERT(condition, message): diff --git a/pythonium/veloce/veloce.py b/pythonium/veloce/veloce.py index 3b89a92..75c423b 100644 --- a/pythonium/veloce/veloce.py +++ b/pythonium/veloce/veloce.py @@ -399,6 +399,8 @@ def visit_Call(self, node): return '[{}]'.format(out) elif name == 'jscode': return node.args[0].s + elif name == 'jstype': + return self.visit(node.args[0]) elif name == 'print': args = [self.visit(e) for e in node.args] s = 'console.log({})'.format(', '.join(args)) diff --git a/runtests.py b/runtests.py index 81f2f8a..465a215 100755 --- a/runtests.py +++ b/runtests.py @@ -68,7 +68,7 @@ def run(test, filepath, mode): print('< {} ERROR in {} mode :('.format(test, mode)) return - expected_file = os.path.join(TESTS_ROOT, test+'.expected') + expected_file = os.path.join(os.path.dirname(filepath), test+'.expected') if os.path.exists(expected_file): with open(expected_file, 'br') as f: expected = f.read() @@ -98,16 +98,26 @@ def run(test, filepath, mode): except OSError: pass - for mode in ('veloce', 'compliant'): - print('* Running tests for {} mode'.format(mode)) - for test in os.listdir(TESTS_ROOT): + if len(sys.argv) > 1: + for path in sys.argv[1:]: + if 'compliant' in path: + modes = ('compliant',) + else: + modes = ('veloce', 'compliant') + name = os.path.basename(path) + for mode in modes: + run(name, path, mode) + else: + for mode in ('veloce', 'compliant'): + print('* Running tests for {} mode'.format(mode)) + for test in os.listdir(TESTS_ROOT): + if test.endswith('.py'): + filepath = os.path.join(TESTS_ROOT, test) + run(test, filepath, mode) + for test in os.listdir(COMPLIANT_TESTS_ROOT): if test.endswith('.py'): - filepath = os.path.join(TESTS_ROOT, test) + filepath = os.path.join(COMPLIANT_TESTS_ROOT, test) run(test, filepath, mode) - for test in os.listdir(COMPLIANT_TESTS_ROOT): - if test.endswith('.py'): - filepath = os.path.join(COMPLIANT_TESTS_ROOT, test) - run(test, filepath, mode) - print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) + print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) if (ok_ctr - test_ctr) != 0: sys.exit(1) diff --git a/tests/compliant/mro.py b/tests/compliant/mro.py new file mode 100644 index 0000000..74c2726 --- /dev/null +++ b/tests/compliant/mro.py @@ -0,0 +1,39 @@ +print(object.mro()) + +class A: pass +class B(A): pass +class C(B): pass +class D(C): pass +print(D.mro()) + + +class F: pass +class E: pass +class D: pass +class C(D, F): pass +class B(D, E): pass +class A(B, C): pass +print(A.mro()) + + +class F: pass +class E: pass +class D: pass +class C(D, F): pass +class B(E, D): pass +class A(B, C): pass +print(A.mro()) + + +class A: pass +class B: pass +class C: pass +class D: pass +class E: pass +class K1(A, B, C): pass +class K2(D, B, E): pass +class K3(D, A): pass +class Z(K1, K2, K3): pass + +for klass in (A, B, C, D, E, K1, K2, K3, Z): + print(klass.mro()) From ce9cdc84f9817bd0eaec257b35180b7d04e52a06 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 01:40:30 +0100 Subject: [PATCH 114/160] runtests: rework output --- runtests.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/runtests.py b/runtests.py index 465a215..3b9db3c 100755 --- a/runtests.py +++ b/runtests.py @@ -45,7 +45,7 @@ def compare_output(expected, result): def run(test, filepath, mode): global ok_ctr, test_ctr - print('< Running {} in {} mode.'.format(test, mode)) + print('> Running {} in {} mode.'.format(test, mode)) test_ctr += 1 ext = 'exec-{}.js'.format(mode) exec_script = os.path.join(TMPDIR, test + ext) @@ -58,14 +58,14 @@ def run(test, filepath, mode): compliant_generate_js(filepath, output=f) except Exception as exc: print_exc() - print('< Translating {} in {} mode failed with the above exception.'.format(test, mode)) + print('< Translation failed with the above exception.') return try: result = check_output(['node', '--harmony', exec_script], stderr=STDOUT) except CalledProcessError as err: print(err.output.decode(errors='replace')) - print('< {} ERROR in {} mode :('.format(test, mode)) + print('< ERROR :(') return expected_file = os.path.join(os.path.dirname(filepath), test+'.expected') @@ -77,17 +77,17 @@ def run(test, filepath, mode): expected = check_output(['python3', filepath], stderr=STDOUT) except CalledProcessError as err: print(err.output.decode(errors='replace')) - print('< {} PYTHON ERROR :('.format(test)) + print('< PYTHON ERROR :(') return diffs = compare_output(expected, result) if diffs: for line in diffs: print(line) - print('< {} FAILED in {} mode :('.format(test, mode)) + print('< FAILED :(') else: ok_ctr += 1 - print('< {} PASS in {} mode :)'.format(test, mode)) + print('< PASS :)') if __name__ == '__main__': From 739eece3ebdb84a1bd70598f35f530ca40f3ef5b Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 08:14:04 +0100 Subject: [PATCH 115/160] compliant: small fix in returns types of builtins func defined in runtime.py --- pythonium/compliant/runtime.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pythonium/compliant/runtime.py b/pythonium/compliant/runtime.py index 66cd555..63dbe43 100644 --- a/pythonium/compliant/runtime.py +++ b/pythonium/compliant/runtime.py @@ -53,13 +53,13 @@ def __rcontains__(me, other): def issubclass(klass, other): if klass is other: - return True + return __TRUE if not klass.__bases__: - return False + return __FALSE for base in klass.__bases__: if issubclass(base, other): - return True - return False + return __TRUE + return __FALSE def pythonium_is_true(v): @@ -85,7 +85,7 @@ def pythonium_is_true(v): def isinstance(obj, klass): if obj.__class__: return issubclass(obj.__class__, klass) - return False + return __FALSE def pythonium_obj_to_js_exception(obj): def exception(): From 4a2fddbc690279c76d49099d3f22db0f0a541f85 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 12:22:37 +0100 Subject: [PATCH 116/160] runtests.py: added python tests --- runtests.py | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/runtests.py b/runtests.py index 3b9db3c..534a001 100755 --- a/runtests.py +++ b/runtests.py @@ -18,6 +18,7 @@ ROOT = os.path.abspath(os.path.dirname(__file__)) TESTS_ROOT = os.path.join(ROOT, 'tests') COMPLIANT_TESTS_ROOT = os.path.join(TESTS_ROOT, 'compliant') +PYTHON_TESTS_ROOT = os.path.join(TESTS_ROOT, 'python') # generate pythonium compliant library stdout = sys.stdout @@ -90,6 +91,20 @@ def run(test, filepath, mode): print('< PASS :)') +def run_python(test, filepath): + global ok_ctr, test_ctr + test_ctr +=1 + print('> Running python test {}.'.format(test)) + try: + expected = check_output(['python3', filepath], stderr=STDOUT) + except CalledProcessError as err: + print(err.output.decode(errors='replace')) + print('< PYTHON ERROR :(') + return + else: + print('> PASS :)') + ok_ctr += 1 + if __name__ == '__main__': TMPDIR = os.path.join(TESTS_ROOT, 'tmp') @@ -98,15 +113,19 @@ def run(test, filepath, mode): except OSError: pass + # solo mode if len(sys.argv) > 1: for path in sys.argv[1:]: - if 'compliant' in path: - modes = ('compliant',) + if 'python' in path: + run_python(path, path) else: - modes = ('veloce', 'compliant') - name = os.path.basename(path) - for mode in modes: - run(name, path, mode) + if 'compliant' in path: + modes = ('compliant',) + else: + modes = ('veloce', 'compliant') + name = os.path.basename(path) + for mode in modes: + run(name, path, mode) else: for mode in ('veloce', 'compliant'): print('* Running tests for {} mode'.format(mode)) @@ -118,6 +137,10 @@ def run(test, filepath, mode): if test.endswith('.py'): filepath = os.path.join(COMPLIANT_TESTS_ROOT, test) run(test, filepath, mode) - print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) + print('* Running python tests') + for test in os.listdir(PYTHON_TESTS_ROOT): + if test.endswith('.py'): + run_python(test, os.path.join(PYTHON_TESTS_ROOT, test)) + print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) if (ok_ctr - test_ctr) != 0: sys.exit(1) From b7d98b839c589f385574b8828f9666c8f2c69c42 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 12:23:40 +0100 Subject: [PATCH 117/160] compliant: runtime: fixed mro, full inheritance works --- pythonium/compliant/builtins/list.py | 8 -- pythonium/compliant/builtins/tuple.py | 69 ++++++++++++++ pythonium/compliant/runtime.py | 27 +++--- tests/compliant/mro.py | 24 +++-- tests/python/javascript-ready-mro.py | 125 ++++++++++++++++++++++++++ tests/python/original-mro.py | 114 +++++++++++++++++++++++ 6 files changed, 341 insertions(+), 26 deletions(-) create mode 100644 pythonium/compliant/builtins/tuple.py create mode 100644 tests/python/javascript-ready-mro.py create mode 100644 tests/python/original-mro.py diff --git a/pythonium/compliant/builtins/list.py b/pythonium/compliant/builtins/list.py index b3b16be..263f3ca 100644 --- a/pythonium/compliant/builtins/list.py +++ b/pythonium/compliant/builtins/list.py @@ -84,11 +84,3 @@ def remove(self, obj): def __delitem__(self, index): self.jsobject.splice(jstype(index), 1) - - -class tuple(list): - - def __repr__(self): - return "(" + ", ".join(map(repr, self)) + ")" - - diff --git a/pythonium/compliant/builtins/tuple.py b/pythonium/compliant/builtins/tuple.py new file mode 100644 index 0000000..3394a51 --- /dev/null +++ b/pythonium/compliant/builtins/tuple.py @@ -0,0 +1,69 @@ +class tuple: + + def __init__(self): + self.jsobject = JSArray() + + def __hash__(self): + raise TypeError("unhashable type: 'list'") + + def __repr__(self): + iterable = map(repr, self) + return "[" + ", ".join(iterable) + "]" + + def __jstype__(self): + out = JSArray() + for item in self: + item = jstype(item) + jscode('out.push(item)') + return out + + def insert(self, index, item): + self.jsobject.splice(index, 0, item) + + def __setitem__(self, index, value): + jsobject = self.jsobject + index = index.jsobject + jscode('jsobject[index] = value') + + def __getitem__(self, s): + jsobject = self.jsobject + index = jstype(s) + return jscode('jsobject[index]') + + def __len__(self): + jsobject = self.jsobject + length = jscode('jsobject.length') + return int(length) + + def __iter__(self): + return ListIterator(self) + + def __contains__(self, obj): + for item in self: + if obj == item: + return True + return False + + def pop(self): + return self.jsobject.pop() + + def index(self, obj): + index = 0 + for item in self: + if item == obj: + return index + index += 1 + raise ValueError + + def remove(self, obj): + index = self.index(obj) + jsobject = self.jsobject + jscode('jsobject.splice(jstype(index), 1)') + + def __delitem__(self, index): + self.jsobject.splice(jstype(index), 1) + + def __repr__(self): + return "(" + ", ".join(map(repr, self)) + ")" + + diff --git a/pythonium/compliant/runtime.py b/pythonium/compliant/runtime.py index 63dbe43..0333f73 100644 --- a/pythonium/compliant/runtime.py +++ b/pythonium/compliant/runtime.py @@ -25,8 +25,8 @@ def mro(me): elif me.__class__: raw = me.__class__.__mro__ else: - raw = me.__metaclass__.__mro__ - l = pythonium_call(list) + raw = me.__mro__ + l = pythonium_call(tuple) l.jsobject = raw.slice() return l mro.is_method = True @@ -127,25 +127,28 @@ def pythonium_mro(bases): Another way of looking at this, if you pass a single class K, this will return the linearization of K (the MRO of K, *including* itself). """ - #b ased on http://code.activestate.com/recipes/577748-calculate-the-mro-of-a-class/ + # based on http://code.activestate.com/recipes/577748-calculate-the-mro-of-a-class/ seqs = [C.__mro__.slice() for C in bases] seqs.push(bases.slice()) - + def cdr(l): l = l.slice() l = l.splice(1) return l + def contains(l, c): + for i in l: + if i is c: + return True + return False res = [] while True: non_empty = [] for seq in seqs: - empty = True out = [] for item in seq: if item: - empty = False out.push(item) - if not empty: + if out.length != 0: non_empty.push(out) if non_empty.length == 0: # Nothing left to process, we're done. @@ -154,7 +157,7 @@ def cdr(l): candidate = seq[0] not_head = [] for s in non_empty: - if candidate in cdr(s): + if contains(cdr(s), candidate): not_head.push(s) if not_head.length != 0: candidate = None @@ -163,11 +166,11 @@ def cdr(l): if not candidate: raise TypeError("Inconsistent hierarchy, no C3 MRO is possible") res.push(candidate) - for seq in seqs: + for seq in non_empty: # Remove candidate. - index = seq.indexOf(candidate) - if index >= 0: - seq[index] = None + if seq[0] is candidate: + seq[0] = None + seqs = non_empty def pythonium_create_class(name, bases, attrs): diff --git a/tests/compliant/mro.py b/tests/compliant/mro.py index 74c2726..6492016 100644 --- a/tests/compliant/mro.py +++ b/tests/compliant/mro.py @@ -1,10 +1,15 @@ -print(object.mro()) +print(">>>", object.__name__) +for item in object.mro(): + print(item.__name__) + class A: pass class B(A): pass class C(B): pass class D(C): pass -print(D.mro()) +print(">>>", D.__name__) +for item in D.mro(): + print(item.__name__) class F: pass @@ -13,7 +18,9 @@ class D: pass class C(D, F): pass class B(D, E): pass class A(B, C): pass -print(A.mro()) +print(">>>", A.__name__) +for item in A.mro(): + print(item.__name__) class F: pass @@ -22,7 +29,9 @@ class D: pass class C(D, F): pass class B(E, D): pass class A(B, C): pass -print(A.mro()) +print(">>>", A.__name__) +for item in A.mro(): + print(item.__name__) class A: pass @@ -35,5 +44,8 @@ class K2(D, B, E): pass class K3(D, A): pass class Z(K1, K2, K3): pass -for klass in (A, B, C, D, E, K1, K2, K3, Z): - print(klass.mro()) + +for klass in [A, B, C, D, E, K1, K2, K3, Z]: + print(">>>", klass.__name__) + for item in klass.mro(): + print(item.__name__) diff --git a/tests/python/javascript-ready-mro.py b/tests/python/javascript-ready-mro.py new file mode 100644 index 0000000..93c0257 --- /dev/null +++ b/tests/python/javascript-ready-mro.py @@ -0,0 +1,125 @@ +import sys + + +def mro(*bases): + """Calculate the Method Resolution Order of bases using the C3 algorithm. + + Suppose you intended creating a class K with the given base classes. This + function returns the MRO which K would have, *excluding* K itself (since + it doesn't yet exist), as if you had actually created the class. + + Another way of looking at this, if you pass a single class K, this will + return the linearization of K (the MRO of K, *including* itself). + """ + seqs = [list(C.__mro__) for C in bases] + [list(bases)] + res = [] + def cdr(l): + return l[1:] + while True: + non_empty = [] + for seq in seqs: + out = [] + for item in seq: + if item: + out.append(item) + if len(out) != 0: + non_empty.append(out) + if len(non_empty) == 0: + # Nothing left to process, we're done. + return tuple(res) + for seq in non_empty: # Find merge candidates among seq heads. + candidate = seq[0] + not_head = [] + for s in non_empty: + if candidate in cdr(s): + not_head.append(s) + if len(not_head) != 0: + # Reject the candidate. + candidate = None + else: + break + if not candidate: + raise TypeError("inconsistent hierarchy, no C3 MRO is possible") + res.append(candidate) + for seq in non_empty: + # Remove candidate. + if seq[0] is candidate: + seq[0] = None + seqs = non_empty +### + +if __name__ == '__main__': + # Run self-tests. Prints nothing if they succeed. + O = object + class SeriousOrderDisagreement: + class X(O): pass + class Y(O): pass + class A(X, Y): pass + class B(Y, X): pass + bases = (A, B) + + try: + x = mro(*SeriousOrderDisagreement.bases) + except TypeError: + pass + else: + print("failed test, mro should have raised but got %s instead" % (x,)) + sys.exit(1) + + class Example0: # Trivial single inheritance case. + class A(O): pass + class B(A): pass + class C(B): pass + class D(C): pass + tester = D + expected = (D, C, B, A, O) + + class Example1: + class F(O): pass + class E(O): pass + class D(O): pass + class C(D, F): pass + class B(D, E): pass + class A(B, C): pass + tester = A + expected = (A, B, C, D, E, F, O) + + class Example2: + class F(O): pass + class E(O): pass + class D(O): pass + class C(D, F): pass + class B(E, D): pass + class A(B, C): pass + tester = A + expected = (A, B, E, C, D, F, O) + + class Example3: + class A(O): pass + class B(O): pass + class C(O): pass + class D(O): pass + class E(O): pass + class K1(A, B, C): pass + class K2(D, B, E): pass + class K3(D, A): pass + class Z(K1, K2, K3): pass + + assert mro(A) == (A, O) + assert mro(B) == (B, O) + assert mro(C) == (C, O) + assert mro(D) == (D, O) + assert mro(E) == (E, O) + assert mro(K1) == (K1, A, B, C, O) + assert mro(K2) == (K2, D, B, E, O) + assert mro(K3) == (K3, D, A, O) + + tester = Z + expected = (Z, K1, K2, K3, D, A, B, C, E, O) + + for example in [Example0, Example1, Example2, Example3]: + # First test that the expected result is the same as what Python + # actually generates. + assert example.expected == example.tester.__mro__ + # Now check the calculated MRO. + assert mro(example.tester) == example.expected diff --git a/tests/python/original-mro.py b/tests/python/original-mro.py new file mode 100644 index 0000000..fc0aad7 --- /dev/null +++ b/tests/python/original-mro.py @@ -0,0 +1,114 @@ +import sys + +def mro(*bases): + """Calculate the Method Resolution Order of bases using the C3 algorithm. + + Suppose you intended creating a class K with the given base classes. This + function returns the MRO which K would have, *excluding* K itself (since + it doesn't yet exist), as if you had actually created the class. + + Another way of looking at this, if you pass a single class K, this will + return the linearization of K (the MRO of K, *including* itself). + """ + seqs = [list(C.__mro__) for C in bases] + [list(bases)] + res = [] + while True: + non_empty = list(filter(None, seqs)) + if not non_empty: + # Nothing left to process, we're done. + return tuple(res) + for seq in non_empty: # Find merge candidates among seq heads. + candidate = seq[0] + not_head = [s for s in non_empty if candidate in s[1:]] + if not_head: + # Reject the candidate. + candidate = None + else: + break + if not candidate: + raise TypeError("inconsistent hierarchy, no C3 MRO is possible") + res.append(candidate) + for seq in non_empty: + # Remove candidate. + if seq[0] == candidate: + del seq[0] + + + +### + +if __name__ == '__main__': + # Run self-tests. Prints nothing if they succeed. + O = object + class SeriousOrderDisagreement: + class X(O): pass + class Y(O): pass + class A(X, Y): pass + class B(Y, X): pass + bases = (A, B) + + try: + x = mro(*SeriousOrderDisagreement.bases) + except TypeError: + pass + else: + print("failed test, mro should have raised but got %s instead" % (x,)) + sys.exit(1) + + class Example0: # Trivial single inheritance case. + class A(O): pass + class B(A): pass + class C(B): pass + class D(C): pass + tester = D + expected = (D, C, B, A, O) + + class Example1: + class F(O): pass + class E(O): pass + class D(O): pass + class C(D, F): pass + class B(D, E): pass + class A(B, C): pass + tester = A + expected = (A, B, C, D, E, F, O) + + class Example2: + class F(O): pass + class E(O): pass + class D(O): pass + class C(D, F): pass + class B(E, D): pass + class A(B, C): pass + tester = A + expected = (A, B, E, C, D, F, O) + + class Example3: + class A(O): pass + class B(O): pass + class C(O): pass + class D(O): pass + class E(O): pass + class K1(A, B, C): pass + class K2(D, B, E): pass + class K3(D, A): pass + class Z(K1, K2, K3): pass + + assert mro(A) == (A, O) + assert mro(B) == (B, O) + assert mro(C) == (C, O) + assert mro(D) == (D, O) + assert mro(E) == (E, O) + assert mro(K1) == (K1, A, B, C, O) + assert mro(K2) == (K2, D, B, E, O) + assert mro(K3) == (K3, D, A, O) + + tester = Z + expected = (Z, K1, K2, K3, D, A, B, C, E, O) + + for example in [Example0, Example1, Example2, Example3]: + # First test that the expected result is the same as what Python + # actually generates. + assert example.expected == example.tester.__mro__ + # Now check the calculated MRO. + assert mro(example.tester) == example.expected From 034b9b3f1b576ce779df9b63b300c968aecf9d1f Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 19:05:23 +0100 Subject: [PATCH 118/160] compliant: multiple fixes - bool inherits int - generator() is not callable - fix enumerate - list now accepts an iterable as argument - fix str.join in the case the iterable is empty - improve tuple repr - improve tuple support - fix empty return - fix issubclass - lookup can also happen on function, right now functions have not visible attributes - builtins modules are not sorted before generation --- pythonium/compliant/builtins/{int.py => 25-int.py} | 0 .../compliant/builtins/{bool.py => 50-bool.py} | 2 +- pythonium/compliant/builtins/func.py | 14 ++++++++------ pythonium/compliant/builtins/list.py | 7 +++++-- pythonium/compliant/builtins/str.py | 5 ++++- pythonium/compliant/builtins/tuple.py | 9 ++------- pythonium/compliant/compliant.py | 8 ++++++-- pythonium/compliant/runtime.py | 7 +++++-- pythonium/main.py | 2 +- pythonium/veloce/veloce.py | 1 + tests/compliant/callable.py | 7 ++++--- tests/compliant/enumerate.py | 4 +++- tests/del-items.py | 2 +- 13 files changed, 41 insertions(+), 27 deletions(-) rename pythonium/compliant/builtins/{int.py => 25-int.py} (100%) rename pythonium/compliant/builtins/{bool.py => 50-bool.py} (98%) diff --git a/pythonium/compliant/builtins/int.py b/pythonium/compliant/builtins/25-int.py similarity index 100% rename from pythonium/compliant/builtins/int.py rename to pythonium/compliant/builtins/25-int.py diff --git a/pythonium/compliant/builtins/bool.py b/pythonium/compliant/builtins/50-bool.py similarity index 98% rename from pythonium/compliant/builtins/bool.py rename to pythonium/compliant/builtins/50-bool.py index fabf8d3..0fe5c33 100644 --- a/pythonium/compliant/builtins/bool.py +++ b/pythonium/compliant/builtins/50-bool.py @@ -1,4 +1,4 @@ -class bool: +class bool(int): def __init__(self, obj): if jscode('obj !== undefined'): diff --git a/pythonium/compliant/builtins/func.py b/pythonium/compliant/builtins/func.py index f9d8199..ee459ce 100644 --- a/pythonium/compliant/builtins/func.py +++ b/pythonium/compliant/builtins/func.py @@ -47,7 +47,6 @@ def print(*args): jscode('console.log.apply(console, out)') - class map: def __init__(self, func, iterable): @@ -111,11 +110,9 @@ def any(iterable): def callable(obj): - if jscode("Object.toString.call(obj) ==='[object Function]'"): - return True - if jscode('obj.next'): + if jscode("{}.toString.call(obj) == '[object Function]'"): return True - if obj.__class__: + if jscode('obj.__metaclass__ !== undefined'): return True if jscode("lookup(obj, '__call__')"): return True @@ -135,13 +132,18 @@ def staticmethod(func): class enumerate: def __init__(self, iterator): - self.iterator = iterator + self.iterator = iter(iterator) self.index = 0 + def __repr__(self): + return '' + def __iter__(self): return self def __next__(self): + index = self.index + self.index = self.index + 1 return (index, next(self.iterator)) diff --git a/pythonium/compliant/builtins/list.py b/pythonium/compliant/builtins/list.py index 263f3ca..7a35996 100644 --- a/pythonium/compliant/builtins/list.py +++ b/pythonium/compliant/builtins/list.py @@ -18,14 +18,17 @@ def __next__(self): class list: - def __init__(self): + def __init__(self, iterable): self.jsobject = JSArray() + if jscode('iterable !== undefined'): + for item in iterable: + self.append(item) def __hash__(self): raise TypeError("unhashable type: 'list'") def __repr__(self): - iterable = map(repr, self) + iterable = map(nest_str_with_quotes, self) return "[" + ", ".join(iterable) + "]" def __jstype__(self): diff --git a/pythonium/compliant/builtins/str.py b/pythonium/compliant/builtins/str.py index cc2f7bb..3a526c0 100644 --- a/pythonium/compliant/builtins/str.py +++ b/pythonium/compliant/builtins/str.py @@ -25,7 +25,10 @@ def __iter__(self): def join(self, iterable): iterable = iter(iterable) - out = next(iterable) + try: + out = next(iterable) + except StopIteration: + return "" for item in iterable: out = out + self + item return out diff --git a/pythonium/compliant/builtins/tuple.py b/pythonium/compliant/builtins/tuple.py index 3394a51..26109cd 100644 --- a/pythonium/compliant/builtins/tuple.py +++ b/pythonium/compliant/builtins/tuple.py @@ -7,8 +7,8 @@ def __hash__(self): raise TypeError("unhashable type: 'list'") def __repr__(self): - iterable = map(repr, self) - return "[" + ", ".join(iterable) + "]" + iterable = map(nest_str_with_quotes, self) + return "(" + ", ".join(iterable) + ")" def __jstype__(self): out = JSArray() @@ -62,8 +62,3 @@ def remove(self, obj): def __delitem__(self, index): self.jsobject.splice(jstype(index), 1) - - def __repr__(self): - return "(" + ", ".join(map(repr, self)) + ")" - - diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 8f6ec9b..ab270c2 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -183,9 +183,12 @@ def visit_Module(self, node): def visit_Tuple(self, node): args = ', '.join(map(self.visit, node.elts)) if args: - return 'pythonium_call(list, [{}])'.format(args) + name = '__a_tuple{}'.format(self.uuid()) + self.writer.write('var {} = pythonium_call(tuple);'.format(name)) + self.writer.write('{}.jsobject = [{}];'.format(name, args)) + return name else: - return 'pythonium_call(list)' + return 'pythonium_call(tuple)' # List(expr* elts, expr_context ctx) def visit_List(self, node): @@ -713,6 +716,7 @@ def visit_Expr(self, node): def visit_Return(self, node): if node.value: self.writer.write('return {};'.format(self.visit(node.value))) + self.writer.write('return __NONE;') # Compare(expr left, cmpop* ops, expr* comparators) def visit_Compare(self, node): diff --git a/pythonium/compliant/runtime.py b/pythonium/compliant/runtime.py index 0333f73..c78693a 100644 --- a/pythonium/compliant/runtime.py +++ b/pythonium/compliant/runtime.py @@ -57,7 +57,7 @@ def issubclass(klass, other): if not klass.__bases__: return __FALSE for base in klass.__bases__: - if issubclass(base, other): + if issubclass(base, other) is __TRUE: return __TRUE return __FALSE @@ -197,8 +197,11 @@ def method_wrapper(): else: if obj.__class__: __mro__ = obj.__class__.__mro__ - else: + elif obj.__metaclass__: __mro__ = obj.__metaclass__.__mro__ + else: + # it's a function + return None for base in __mro__: class_attr = base[attr] if class_attr != None: diff --git a/pythonium/main.py b/pythonium/main.py index a1b2231..29f60da 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -44,7 +44,7 @@ def main(argv=None): # compile builtins for path in builtins.__path__: - for name in os.listdir(path): + for name in sorted(os.listdir(path)): if name.endswith('.py'): argv = [os.path.join(path, name)] main(argv) diff --git a/pythonium/veloce/veloce.py b/pythonium/veloce/veloce.py index 75c423b..fb43ca9 100644 --- a/pythonium/veloce/veloce.py +++ b/pythonium/veloce/veloce.py @@ -615,6 +615,7 @@ def visit_Expr(self, node): def visit_Return(self, node): if node.value: self.writer.write('return {};'.format(self.visit(node.value))) + self.writer.write('return undefined;') # Compare(expr left, cmpop* ops, expr* comparators) def visit_Compare(self, node): diff --git a/tests/compliant/callable.py b/tests/compliant/callable.py index c46416c..6e56248 100644 --- a/tests/compliant/callable.py +++ b/tests/compliant/callable.py @@ -3,23 +3,24 @@ print(callable(True)) print(callable(bool)) + class GenerateCallable: def __call__(self): return 42 - print(callable(GenerateCallable)) print(callable(GenerateCallable())) + class GenerateNonCallable: - pass + def method(self): + pass print(callable(GenerateNonCallable)) print(callable(GenerateNonCallable())) def generator(): yield 42 - print(callable(generator)) print(callable(generator())) diff --git a/tests/compliant/enumerate.py b/tests/compliant/enumerate.py index 4225dab..6805737 100644 --- a/tests/compliant/enumerate.py +++ b/tests/compliant/enumerate.py @@ -1 +1,3 @@ -print(list(enumerate(['A', 'B', 'C']))) +abc = ['A', 'B', 'C'] +enumeration = enumerate(abc) +novo = list(enumeration) diff --git a/tests/del-items.py b/tests/del-items.py index 9bbb332..27aec70 100644 --- a/tests/del-items.py +++ b/tests/del-items.py @@ -1,3 +1,3 @@ -d = {1:1} +d = {1: 1} del d[1] print(d) From 1fb08f810af69bce17a81630ab0b90c3365da808 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 19:29:22 +0100 Subject: [PATCH 119/160] remove wild debug statment --- pythonium/compliant/compliant.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index ab270c2..2fb7a3a 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -883,7 +883,6 @@ def _unpack_arguments(self, args, kwargs, varargs, varkwargs): # Lambda(arguments args, expr body) def visit_Lambda(self, node): args, kwargs, vararg, varkwargs = self.visit(node.args) - sys.stderr.write(", ".join(args)) name = '__lambda{}'.format(self.uuid()) self.writer.write('var {} = function({}) {{'.format(name, ', '.join(args))) self.writer.push() From e11ab925f51cefdce082b025c8a9f0e21df69bb4 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 19:30:48 +0100 Subject: [PATCH 120/160] runtests.py: use envoy for no good reason except the API is better, install with pip install git+https://github.com/kennethreitz/envoy.git --- runtests.py | 50 ++++++++++++------------ tests/compliant/nested-stop-iteration.py | 11 ++++++ 2 files changed, 36 insertions(+), 25 deletions(-) create mode 100644 tests/compliant/nested-stop-iteration.py diff --git a/runtests.py b/runtests.py index 534a001..eba916b 100755 --- a/runtests.py +++ b/runtests.py @@ -6,9 +6,7 @@ from traceback import print_exc from itertools import chain -from subprocess import STDOUT -from subprocess import check_output -from subprocess import CalledProcessError +from envoy import run # pip install git+https://github.com/kennethreitz/envoy.git from pythonium.main import main from pythonium.veloce.veloce import veloce_generate_js @@ -44,9 +42,9 @@ def compare_output(expected, result): return list(diffs) -def run(test, filepath, mode): +def run_test(test, filepath, mode): global ok_ctr, test_ctr - print('> Running {} in {} mode.'.format(test, mode)) + print('> Running {} in {} mode...'.format(test, mode)) test_ctr += 1 ext = 'exec-{}.js'.format(mode) exec_script = os.path.join(TMPDIR, test + ext) @@ -59,28 +57,30 @@ def run(test, filepath, mode): compliant_generate_js(filepath, output=f) except Exception as exc: print_exc() - print('< Translation failed with the above exception.') + print('< Translation failed with the above exception :(') return - try: - result = check_output(['node', '--harmony', exec_script], stderr=STDOUT) - except CalledProcessError as err: - print(err.output.decode(errors='replace')) + result = run('node --harmony {}'.format(exec_script)) + if result.status_code != 0: + print(result.std_out) + print(result.std_err) print('< ERROR :(') return - + else: + result = result.std_out expected_file = os.path.join(os.path.dirname(filepath), test+'.expected') if os.path.exists(expected_file): with open(expected_file, 'br') as f: expected = f.read() else: - try: - expected = check_output(['python3', filepath], stderr=STDOUT) - except CalledProcessError as err: - print(err.output.decode(errors='replace')) + expected = run('python3 {}'.format(filepath)) + if expected.status_code != 0: + print(expected.std_out) + print(expected.std_err) print('< PYTHON ERROR :(') return - + else: + expected = expected.std_out diffs = compare_output(expected, result) if diffs: for line in diffs: @@ -94,11 +94,11 @@ def run(test, filepath, mode): def run_python(test, filepath): global ok_ctr, test_ctr test_ctr +=1 - print('> Running python test {}.'.format(test)) - try: - expected = check_output(['python3', filepath], stderr=STDOUT) - except CalledProcessError as err: - print(err.output.decode(errors='replace')) + print('> Running python test {}...'.format(test)) + expected = run('python3 {}'.format(filepath)) + if expected.status_code != 0: + print(expected.std_out) + print(expected.std_err) print('< PYTHON ERROR :(') return else: @@ -125,22 +125,22 @@ def run_python(test, filepath): modes = ('veloce', 'compliant') name = os.path.basename(path) for mode in modes: - run(name, path, mode) + run_test(name, path, mode) else: for mode in ('veloce', 'compliant'): print('* Running tests for {} mode'.format(mode)) for test in os.listdir(TESTS_ROOT): if test.endswith('.py'): filepath = os.path.join(TESTS_ROOT, test) - run(test, filepath, mode) + run_test(test, filepath, mode) for test in os.listdir(COMPLIANT_TESTS_ROOT): if test.endswith('.py'): filepath = os.path.join(COMPLIANT_TESTS_ROOT, test) - run(test, filepath, mode) + run_test(test, filepath, mode) print('* Running python tests') for test in os.listdir(PYTHON_TESTS_ROOT): if test.endswith('.py'): run_python(test, os.path.join(PYTHON_TESTS_ROOT, test)) - print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) + print("*** Passed {}/{} tests".format(ok_ctr, test_ctr)) if (ok_ctr - test_ctr) != 0: sys.exit(1) diff --git a/tests/compliant/nested-stop-iteration.py b/tests/compliant/nested-stop-iteration.py new file mode 100644 index 0000000..b54ce57 --- /dev/null +++ b/tests/compliant/nested-stop-iteration.py @@ -0,0 +1,11 @@ +try: + for i in range(10): + next(iter(list())) +except: + print('catch!') + +try: + for i in range(10): + next(iter(list())) +except StopIteration: + print('catch!') From 6667212fda3d5303a2860dbf457bf397eea65828 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Tue, 10 Dec 2013 23:52:50 +0100 Subject: [PATCH 121/160] Revert "runtests.py: use envoy for no good reason except the API is better, install with pip install git+https://github.com/kennethreitz/envoy.git" This reverts commit e11ab925f51cefdce082b025c8a9f0e21df69bb4. --- runtests.py | 50 ++++++++++++------------ tests/compliant/nested-stop-iteration.py | 11 ------ 2 files changed, 25 insertions(+), 36 deletions(-) delete mode 100644 tests/compliant/nested-stop-iteration.py diff --git a/runtests.py b/runtests.py index eba916b..534a001 100755 --- a/runtests.py +++ b/runtests.py @@ -6,7 +6,9 @@ from traceback import print_exc from itertools import chain -from envoy import run # pip install git+https://github.com/kennethreitz/envoy.git +from subprocess import STDOUT +from subprocess import check_output +from subprocess import CalledProcessError from pythonium.main import main from pythonium.veloce.veloce import veloce_generate_js @@ -42,9 +44,9 @@ def compare_output(expected, result): return list(diffs) -def run_test(test, filepath, mode): +def run(test, filepath, mode): global ok_ctr, test_ctr - print('> Running {} in {} mode...'.format(test, mode)) + print('> Running {} in {} mode.'.format(test, mode)) test_ctr += 1 ext = 'exec-{}.js'.format(mode) exec_script = os.path.join(TMPDIR, test + ext) @@ -57,30 +59,28 @@ def run_test(test, filepath, mode): compliant_generate_js(filepath, output=f) except Exception as exc: print_exc() - print('< Translation failed with the above exception :(') + print('< Translation failed with the above exception.') return - result = run('node --harmony {}'.format(exec_script)) - if result.status_code != 0: - print(result.std_out) - print(result.std_err) + try: + result = check_output(['node', '--harmony', exec_script], stderr=STDOUT) + except CalledProcessError as err: + print(err.output.decode(errors='replace')) print('< ERROR :(') return - else: - result = result.std_out + expected_file = os.path.join(os.path.dirname(filepath), test+'.expected') if os.path.exists(expected_file): with open(expected_file, 'br') as f: expected = f.read() else: - expected = run('python3 {}'.format(filepath)) - if expected.status_code != 0: - print(expected.std_out) - print(expected.std_err) + try: + expected = check_output(['python3', filepath], stderr=STDOUT) + except CalledProcessError as err: + print(err.output.decode(errors='replace')) print('< PYTHON ERROR :(') return - else: - expected = expected.std_out + diffs = compare_output(expected, result) if diffs: for line in diffs: @@ -94,11 +94,11 @@ def run_test(test, filepath, mode): def run_python(test, filepath): global ok_ctr, test_ctr test_ctr +=1 - print('> Running python test {}...'.format(test)) - expected = run('python3 {}'.format(filepath)) - if expected.status_code != 0: - print(expected.std_out) - print(expected.std_err) + print('> Running python test {}.'.format(test)) + try: + expected = check_output(['python3', filepath], stderr=STDOUT) + except CalledProcessError as err: + print(err.output.decode(errors='replace')) print('< PYTHON ERROR :(') return else: @@ -125,22 +125,22 @@ def run_python(test, filepath): modes = ('veloce', 'compliant') name = os.path.basename(path) for mode in modes: - run_test(name, path, mode) + run(name, path, mode) else: for mode in ('veloce', 'compliant'): print('* Running tests for {} mode'.format(mode)) for test in os.listdir(TESTS_ROOT): if test.endswith('.py'): filepath = os.path.join(TESTS_ROOT, test) - run_test(test, filepath, mode) + run(test, filepath, mode) for test in os.listdir(COMPLIANT_TESTS_ROOT): if test.endswith('.py'): filepath = os.path.join(COMPLIANT_TESTS_ROOT, test) - run_test(test, filepath, mode) + run(test, filepath, mode) print('* Running python tests') for test in os.listdir(PYTHON_TESTS_ROOT): if test.endswith('.py'): run_python(test, os.path.join(PYTHON_TESTS_ROOT, test)) - print("*** Passed {}/{} tests".format(ok_ctr, test_ctr)) + print("= Passed {}/{} tests".format(ok_ctr, test_ctr)) if (ok_ctr - test_ctr) != 0: sys.exit(1) diff --git a/tests/compliant/nested-stop-iteration.py b/tests/compliant/nested-stop-iteration.py deleted file mode 100644 index b54ce57..0000000 --- a/tests/compliant/nested-stop-iteration.py +++ /dev/null @@ -1,11 +0,0 @@ -try: - for i in range(10): - next(iter(list())) -except: - print('catch!') - -try: - for i in range(10): - next(iter(list())) -except StopIteration: - print('catch!') From 74cd983d4e8c60c4ea59fb3b9f3bab9ae05a1532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Ljunglo=CC=88f?= Date: Wed, 11 Dec 2013 08:31:19 +0100 Subject: [PATCH 122/160] Move the Writer to utils.py --- pythonium/compliant/compliant.py | 22 +--------------------- pythonium/utils.py | 21 +++++++++++++++++++++ pythonium/veloce/veloce.py | 22 +--------------------- 3 files changed, 23 insertions(+), 42 deletions(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 2fb7a3a..cea1a1b 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -1,6 +1,5 @@ import os import sys -from io import StringIO from collections import namedtuple from ast import Str @@ -15,32 +14,13 @@ from ast import FunctionDef from ast import NodeVisitor -from ..utils import YieldSearch +from ..utils import YieldSearch, Writer from ..veloce.veloce import Veloce ClassDefNode = namedtuple('ClassDef', 'name') FunctionDefNode = namedtuple('FunctionDef', 'name') -class Writer: - - def __init__(self): - self.level = 0 - self.output = StringIO() - - def push(self): - self.level += 1 - - def pull(self): - self.level -= 1 - - def write(self, code): - self.output.write(' ' * 4 * self.level + code + '\n') - - def value(self): - return self.output.getvalue() - - class Compliant(NodeVisitor): @classmethod diff --git a/pythonium/utils.py b/pythonium/utils.py index 5f38e80..1f8eafd 100644 --- a/pythonium/utils.py +++ b/pythonium/utils.py @@ -1,4 +1,5 @@ from ast import NodeVisitor +from io import StringIO class YieldSearch(NodeVisitor): @@ -9,3 +10,23 @@ def visit_Yield(self, node): def visit_FunctionDef(self, node): pass # do not visit nest function definition to determine # if a function has a yield or not... + + + +class Writer: + + def __init__(self): + self.level = 0 + self.output = StringIO() + + def push(self): + self.level += 1 + + def pull(self): + self.level -= 1 + + def write(self, code): + self.output.write(' ' * 4 * self.level + code + '\n') + + def value(self): + return self.output.getvalue() diff --git a/pythonium/veloce/veloce.py b/pythonium/veloce/veloce.py index fb43ca9..03f1b57 100644 --- a/pythonium/veloce/veloce.py +++ b/pythonium/veloce/veloce.py @@ -1,6 +1,5 @@ import os import sys -from io import StringIO from ast import Str from ast import Name @@ -12,26 +11,7 @@ from ast import FunctionDef from ast import NodeVisitor -from ..utils import YieldSearch - - -class Writer: - - def __init__(self): - self.level = 0 - self.output = StringIO() - - def push(self): - self.level += 1 - - def pull(self): - self.level -= 1 - - def write(self, code): - self.output.write(' ' * 4 * self.level + code + '\n') - - def value(self): - return self.output.getvalue() +from ..utils import YieldSearch, Writer class Veloce(NodeVisitor): From 3b2d56f6d56b563421dee1601396cdb0a364eca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Ljunglo=CC=88f?= Date: Wed, 11 Dec 2013 09:10:14 +0100 Subject: [PATCH 123/160] Move veloce/compliant_generate_js to utils.py --- pythonium/compliant/compliant.py | 31 ------------------------- pythonium/main.py | 14 ++++++----- pythonium/utils.py | 40 +++++++++++++++++++++++++++++++- pythonium/veloce/veloce.py | 35 ---------------------------- runtests.py | 16 +++++++------ 5 files changed, 56 insertions(+), 80 deletions(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index cea1a1b..c50d630 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -903,34 +903,3 @@ def visit_ClassDef(self, node): self.writer.write('});') self._def_stack.pop() - -def compliant_generate_js(filepath, requirejs=False, root_path=None, output=None, deep=None): - dirname = os.path.abspath(os.path.dirname(filepath)) - if not root_path: - root_path = dirname - basename = os.path.basename(filepath) - output_name = os.path.join(dirname, basename + '.js') - if not output: - print('Generating {}'.format(output_name)) - # generate js - with open(os.path.join(dirname, basename)) as f: - input = parse(f.read()) - tree = parse(input) - compliant = Compliant() - compliant.visit(tree) - script = compliant.writer.value() - if requirejs: - out = 'define(function(require) {\n' - out += script - all = map(lambda x: "'{}': {}".format(x, x), compliant.__all__) - all = '{{{}}}'.format(', '.join(all)) - out += 'return {}'.format(all) - out += '\n})\n' - script = out - if deep: - for dependency in python_core.dependencies: - if dependency.startswith('.'): - generate_js(os.path.join(dirname, dependency + '.py'), requirejs, root_path, output, deep) - else: - generate_js(os.path.join(root_path, dependency[1:] + '.py'), requirejs, root_path, output, deep) - output.write(script) diff --git a/pythonium/main.py b/pythonium/main.py index 29f60da..bd6b6f7 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -22,8 +22,9 @@ import sys from docopt import docopt -from .veloce.veloce import veloce_generate_js -from .compliant.compliant import compliant_generate_js +from .veloce.veloce import Veloce +from .compliant.compliant import Compliant +from .utils import pythonium_generate_js __version__ = '0.5.0' @@ -55,8 +56,9 @@ def main(argv=None): main(['--help']) return - generator = veloce_generate_js if args['--veloce'] else compliant_generate_js - options = {'requirejs': args['--requirejs'], + translator = Veloce if args['--veloce'] else Compliant + options = {'translator': translator, + 'requirejs': args['--requirejs'], 'deep': args['--deep'], } @@ -64,10 +66,10 @@ def main(argv=None): if outfile: with open(outfile, 'w') as output: for filepath in filepaths: - generator(filepath, output=output, **options) + pythonium_generate_js(filepath, output=output, **options) else: for filepath in filepaths: - generator(filepath, output=sys.stdout, **options) + pythonium_generate_js(filepath, output=sys.stdout, **options) if __name__ == '__main__': diff --git a/pythonium/utils.py b/pythonium/utils.py index 1f8eafd..3fbe326 100644 --- a/pythonium/utils.py +++ b/pythonium/utils.py @@ -1,4 +1,5 @@ -from ast import NodeVisitor +import os +from ast import NodeVisitor, parse from io import StringIO @@ -30,3 +31,40 @@ def write(self, code): def value(self): return self.output.getvalue() + + +def pythonium_generate_js(filepath, translator, requirejs=False, root_path=None, output=None, deep=None): + dirname = os.path.abspath(os.path.dirname(filepath)) + if not root_path: + root_path = dirname + basename = os.path.basename(filepath) + output_name = os.path.join(dirname, basename + '.js') + if not output: + print('Generating {}'.format(output_name)) + # generate js + with open(os.path.join(dirname, basename)) as f: + input = parse(f.read()) + tree = parse(input) + pytrans = translator() + pytrans.visit(tree) + script = pytrans.writer.value() + if requirejs: + out = 'define(function(require) {\n' + out += script + if isinstance(pytrans.__all__, str): + out += '\nreturn {};\n'.format(pytrans.__all__) + elif isinstance(pytrans.__all__, list): + all = ["{!r}: {}".format(x, x) for x in pytrans.__all__] + public = '{{{}}}'.format(', '.join(all)) + out += '\nreturn {};\n'.format(public) + else: + raise Exception('__all__ is not defined!') + out += '\n})\n' + script = out + if deep: + for dependency in python_core.dependencies: + if dependency.startswith('.'): + generate_js(os.path.join(dirname, dependency + '.py'), requirejs, root_path, output, deep) + else: + generate_js(os.path.join(root_path, dependency[1:] + '.py'), requirejs, root_path, output, deep) + output.write(script) diff --git a/pythonium/veloce/veloce.py b/pythonium/veloce/veloce.py index 03f1b57..f06d4c9 100644 --- a/pythonium/veloce/veloce.py +++ b/pythonium/veloce/veloce.py @@ -710,38 +710,3 @@ def visit_ClassDef(self, node): self.writer.write('});') self.in_classdef = None - -def veloce_generate_js(filepath, requirejs=False, root_path=None, output=None, deep=None): - dirname = os.path.abspath(os.path.dirname(filepath)) - if not root_path: - root_path = dirname - basename = os.path.basename(filepath) - output_name = os.path.join(dirname, basename + '.js') - if not output: - print('Generating {}'.format(output_name)) - # generate js - with open(os.path.join(dirname, basename)) as f: - input = parse(f.read()) - tree = parse(input) - python_core = Veloce() - python_core.visit(tree) - script = python_core.writer.value() - if requirejs: - out = 'define(function(require) {\n' - out += script - if isinstance(python_core.__all__, str): - out += '\nreturn {};\n'.format(python_core.__all__) - elif python_core.__all__: - public = '{{{}}}'.format(', '.join(map(lambda x: '{}: {}'.format(x[0], x[1]), zip(python_core.__all__, python_core.__all__)))) - out += '\nreturn {};\n'.format(public) - else: - raise Exception('__all__ is not defined!') - out += '\n})\n' - script = out - if deep: - for dependency in python_core.dependencies: - if dependency.startswith('.'): - generate_js(os.path.join(dirname, dependency + '.py'), requirejs, root_path, output, deep) - else: - generate_js(os.path.join(root_path, dependency[1:] + '.py'), requirejs, root_path, output, deep) - output.write(script) diff --git a/runtests.py b/runtests.py index 534a001..1bce322 100755 --- a/runtests.py +++ b/runtests.py @@ -11,8 +11,9 @@ from subprocess import CalledProcessError from pythonium.main import main -from pythonium.veloce.veloce import veloce_generate_js -from pythonium.compliant.compliant import compliant_generate_js +from pythonium.veloce.veloce import Veloce +from pythonium.compliant.compliant import Compliant +from pythonium.utils import pythonium_generate_js ROOT = os.path.abspath(os.path.dirname(__file__)) @@ -51,12 +52,13 @@ def run(test, filepath, mode): ext = 'exec-{}.js'.format(mode) exec_script = os.path.join(TMPDIR, test + ext) with open(exec_script, 'w') as f: + if mode =='veloce': + translator=Veloce + else: + f.write(COMPLIANTJS) + translator=Compliant try: - if mode =='veloce': - veloce_generate_js(filepath, output=f) - else: - f.write(COMPLIANTJS) - compliant_generate_js(filepath, output=f) + pythonium_generate_js(filepath, translator, output=f) except Exception as exc: print_exc() print('< Translation failed with the above exception.') From ab14008c5eef16e0eb323c2f44b15e17331a5328 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 13 Dec 2013 21:21:55 +0100 Subject: [PATCH 124/160] setup.py: fix --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8e7ea46..ea80697 100755 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ author_email='amirouche.boubekki@gmail.com', url='https://github.com/pythonium/pythonium', zip_safe=False, - packages=['pythonium', 'pythonium.compliant', 'pythonium.compliant.lib', 'pythonium.veloce'], + packages=['pythonium', 'pythonium.compliant', 'pythonium.compliant.builtins', 'pythonium.veloce'], install_requires=['docopt'], entry_points=""" [console_scripts] From 56544ec4034ffd00629abe84ee73f6e7f13a1b2c Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 13 Dec 2013 21:26:09 +0100 Subject: [PATCH 125/160] update CHANGELOG --- CHANGELOG | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 75582c6..ad6d7a9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,3 +10,18 @@ - ``print`` was defined in ``lib/builtins.py`` and must be used to log Python objects. ``console.log(fuuuu)`` must be used to log JavaScript objects. - rework ``dict`` so that it works more like CPython one. - fixed a bug where if two functions were nested and the nested function was a generator both functions were dubbed generators + - replaced JS by jscode + - added a minimal Tree.js example (Dirk Krause) + - added assert + - fixed nested loops + - added del without slice support + - fixed mro (multiple inheritance) + - fixed repr + - fixed lambda will full signature support + - fixed thruth + - added “SPAM if EGG else FOOBAR” + - added a minimal HACKING file + - added travis + - added: bool as a func, callable, enumerate, getattr + - rework map and range + - added a lot of tests From db684aa4f1e3159e60fd09664ab30f4b880d8212 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Fri, 13 Dec 2013 21:26:58 +0100 Subject: [PATCH 126/160] bump to 0.6.0 --- CHANGELOG | 3 +++ pythonium/main.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index ad6d7a9..eff21d0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +0.6.0 + - TBD + 0.5.0 - Web Console available online @ http://hypermove.net/pythonium-web-console/ - Fix runtests.py: avoid envoy, made it work on Windows (Peter Ljunglöf) diff --git a/pythonium/main.py b/pythonium/main.py index bd6b6f7..4d35809 100755 --- a/pythonium/main.py +++ b/pythonium/main.py @@ -26,7 +26,7 @@ from .compliant.compliant import Compliant from .utils import pythonium_generate_js -__version__ = '0.5.0' +__version__ = '0.6.0' def main(argv=None): From b202a3b6e268814bcbc27bee668d290973512060 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Sun, 15 Dec 2013 13:11:20 +0100 Subject: [PATCH 127/160] renamed CHANGELOG to CHANGELOG.rst --- CHANGELOG => CHANGELOG.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CHANGELOG => CHANGELOG.rst (100%) diff --git a/CHANGELOG b/CHANGELOG.rst similarity index 100% rename from CHANGELOG rename to CHANGELOG.rst From 0562dbb604f73ebde9b0b6a58dae7f47eb18a22b Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 10:18:33 +0100 Subject: [PATCH 128/160] compliant: remove spurious return --- pythonium/compliant/compliant.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index c50d630..831d615 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -696,6 +696,7 @@ def visit_Expr(self, node): def visit_Return(self, node): if node.value: self.writer.write('return {};'.format(self.visit(node.value))) + return self.writer.write('return __NONE;') # Compare(expr left, cmpop* ops, expr* comparators) From cc342f750f74ab07cd7e8b22d57b280f493b8a2e Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 10:22:40 +0100 Subject: [PATCH 129/160] compliant: fix multiple targets unpack --- pythonium/compliant/compliant.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 831d615..36affcf 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -665,8 +665,9 @@ def visit_Assign(self, node): targets = map(self.visit, target.elts) if export: self.__all__.extends(targets) + self.writer.write('var getitem = pythonium_get_attribute(__assignement, "__getitem__");') for index, target in enumerate(targets): - self.writer.write('{} = __assignement[{}];\n'.format(target, index)) + self.writer.write('{} = getitem(pythonium_call(int, {}));'.format(target, index)) else: if isinstance(target, Attribute): name = self.visit(target.value) From af9d1747718126ed6edd2d9b19ef95480c4c9610 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 11:15:37 +0100 Subject: [PATCH 130/160] compliant: add list comprehension --- pythonium/compliant/builtins/25-int.py | 6 ++++++ pythonium/compliant/compliant.py | 17 ++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/pythonium/compliant/builtins/25-int.py b/pythonium/compliant/builtins/25-int.py index 08628f3..06d378c 100644 --- a/pythonium/compliant/builtins/25-int.py +++ b/pythonium/compliant/builtins/25-int.py @@ -92,3 +92,9 @@ def __div__(self, other): a = self.jsobject b = other.jsobject return int(jscode('a / b')) + + def __mod__(self, other): + a = self.jsobject + b = other.jsobject + return int(jscode('a % b')) + diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 36affcf..c1b6e57 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -475,13 +475,14 @@ def visit_Call(self, node): def visit_ListComp(self, node): # 'elt', 'generators' comprehension = '__comp{}__'.format(self.uuid()) - self.writer.write('var {} = [];'.format(comprehension)) + self.writer.write('var {} = pythonium_call(list);'.format(comprehension)) list(map(self.visit, node.generators)) value = self.visit(node.elt) - self.writer.write('{}.push({});'.format(comprehension, value)) + self.writer.write('pythonium_get_attribute({}, "append")({});'.format(comprehension, value)) for _ in node.generators: self.writer.pull() - self.writer.write('}') + self.writer.write('}} catch (__exception__) {if (!pythonium_is_exception(__exception__, StopIteration)) { throw x; }}') + self.writer.pull() return comprehension # SetComp(expr elt, comprehension* generators) @@ -498,12 +499,14 @@ def visit_comprehension(self, node): # 'target', 'iter', 'ifs' iterator = '__iterator{}__'.format(self.uuid()) index = '__index{}__'.format(self.uuid()) - self.writer.write('var {} = {};'.format(iterator, self.visit(node.iter))) - self.writer.write('for (var {} = 0; {}<{}.length; {}++) {{'.format(index, index, iterator, index)) + self.writer.write('var {} = iter({});'.format(iterator, self.visit(node.iter))) + self.writer.write('try {') + self.writer.push() + self.writer.write('while (true) {') self.writer.push() - self.writer.write('var {} = {}[{}];'.format(self.visit(node.target), iterator, index)) + self.writer.write('var {} = next({});'.format(self.visit(node.target), iterator)) if node.ifs: - self.writer.write('if(!{}) {{ continue; }}'.format(' && '.join(map(self.visit, node.ifs)))) + self.writer.write('if(!pythonium_is_true({})) {{ continue; }}'.format(' && '.join(map(self.visit, node.ifs)))) # While(expr test, stmt* body, stmt* orelse) def visit_While(self, node): From 765c42e07290445e8210fdb139acd9ec07276cb8 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 11:20:20 +0100 Subject: [PATCH 131/160] veloce: replace NotImplemented by raise NotImplemented --- pythonium/veloce/veloce.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/pythonium/veloce/veloce.py b/pythonium/veloce/veloce.py index f06d4c9..d610c41 100644 --- a/pythonium/veloce/veloce.py +++ b/pythonium/veloce/veloce.py @@ -77,21 +77,21 @@ def visit(self, node): ###################################################################### # Interactive(stmt* body) - visit_Interactive = NotImplemented + def visit_Interactive(self, node): raise NotImplemented # Expression(expr body) - visit_Expression = NotImplemented + def visit_Expression(self, node): raise NotImplemented # Suite(stmt* body) - visit_Suite = NotImplemented + def visit_Suite(self, node): raise NotImplemented # expr_context = Load | Store | Del | AugLoad | AugStore | Param - visit_Load = NotImplemented - visit_Store = NotImplemented - visit_Del = NotImplemented - visit_AugLoad = NotImplemented - visit_AugStore = NotImplemented - visit_Param = NotImplemented + def visit_Load(self, node): raise NotImplemented + def visit_Store(self, node): raise NotImplemented + def visit_Del(self, node): raise NotImplemented + def visit_AugLoad(self, node): raise NotImplemented + def visit_AugStore(self, node): raise NotImplemented + def visit_Param(self, node): raise NotImplemented # Pass def visit_Pass(self, node): @@ -123,14 +123,14 @@ def visit_Yield(self, node): return 'yield {}'.format(self.visit(node.value)) # YieldFrom(expr value) - visit_YieldFrom = NotImplemented + def visit_YieldFrom(self, node): raise NotImplemented # In def visit_In(self, node): return ' in ' # NotIn - visit_NotIn = NotImplemented + def visit_NotIn(self, node): raise NotImplemented # Module(stmt* body) def visit_Module(self, node): @@ -145,13 +145,13 @@ def visit_List(self, node): return '[{}]'.format(', '.join(map(self.visit, node.elts))) # Set(expr* elts) - visit_Set = NotImplemented + def visit_Set(self, node): raise NotImplemented # alias = (identifier name, identifier? asname) - visit_alias = NotImplemented + def visit_alias(self, node): raise NotImplemented # Import(alias* names) - visit_Import = NotImplemented + def visit_Import(self, node): raise NotImplemented # ImportFrom(identifier? module, alias* names, int? level) def visit_ImportFrom(self, node): @@ -184,7 +184,7 @@ def visit_Global(self, node): return '' # Nonlocal(identifier* names) - visit_Nonlocal = NotImplemented + def visit_Nonlocal(self, node): raise NotImplemented # FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns) def visit_FunctionDef(self, node): @@ -291,7 +291,7 @@ def visit_Index(self, node): return self.visit(node.value) # ExtSlice(slice* dims) - visit_ExtSlice = NotImplemented + def visit_ExtSlice(self, node): raise NotImplemented # Subscript(expr value, slice slice, expr_context ctx) def visit_Subscript(self, node): @@ -311,7 +311,7 @@ def visit_arguments(self, node): return args, kwargs, vararg, varkwargs # arg = (identifier arg, expr? annotation) - visit_arg = NotImplemented + def visit_arg(self, node): raise NotImplemented # Name(identifier id, expr_context ctx) def visit_Name(self, node): @@ -638,7 +638,7 @@ def visit_If(self, node): self.writer.write('}') # IfExp(expr test, expr body, expr orelse) - visit_IfExp = NotImplemented + def visit_IfExp(self, node): raise NotImplemented # Ellipsis visit_Ellipsis = NotImplemented From 7c19ac594b677734b4a3bc1cdec0491c40f86605 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 11:25:07 +0100 Subject: [PATCH 132/160] cleanup --- pythonium/compliant/compliant.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index c1b6e57..84022a4 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -22,7 +22,7 @@ class Compliant(NodeVisitor): - + @classmethod def translate(cls, code): translator = cls() @@ -54,7 +54,7 @@ def visit(self, node): # | For | While | If | With | Raise | Try | Assert | Import | ImportFrom # | Global | Nonlocal | Expr | Pass | Break | Continue # - # expr = BoolOp | BinOp | UnaryOp | Lambda | IfExp | Dict | Set + # expr = BoolOp | BinOp | UnaryOp | Lambda | IfExp | Dict | Set # | ListComp | SetComp | DictComp | GeneratorExp | Yield | YieldFrom # | Compare | Call | Num | Str | Bytes | Ellipsis | Attribute # | Subscript | Starred | Name | List | Tuple @@ -77,7 +77,7 @@ def visit(self, node): # excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body) # # arguments = (arg* args, identifier? vararg, expr? varargannotation, - # arg* kwonlyargs, identifier? kwarg, expr? kwargannotation, + # arg* kwonlyargs, identifier? kwarg, expr? kwargannotation, # expr* defaults, expr* kw_defaults) # # arg = (identifier arg, expr? annotation) @@ -147,7 +147,7 @@ def visit_Yield(self, node): # YieldFrom(expr value) visit_YieldFrom = NotImplemented - + # In def visit_In(self, node): return '__rcontains__' @@ -170,7 +170,7 @@ def visit_Tuple(self, node): else: return 'pythonium_call(tuple)' - # List(expr* elts, expr_context ctx) + # List(expr* elts, expr_context ctx) def visit_List(self, node): args = ', '.join(map(self.visit, node.elts)) if args: @@ -255,7 +255,7 @@ def visit_FunctionDef(self, node): self.__all__.append(node.name) self._def_stack.append(FunctionDefNode(node.name)) args, kwargs, varargs, varkwargs = self.visit(node.args) - + all_parameters = list(args) all_parameters.extend(kwargs.keys()) if varargs: @@ -329,9 +329,9 @@ def retrieve_vars(body, vars=None): self._def_stack.pop() self.writer.write('') - return node.name, name + return node.name, name - # Slice(expr? lower, expr? upper, expr? step) + # Slice(expr? lower, expr? upper, expr? step) def visit_Slice(self, node): start = self.visit(node.lower) if node.lower else 'undefined' end = self.visit(node.upper) if node.upper else 'undefined' @@ -342,7 +342,7 @@ def visit_Slice(self, node): def visit_Index(self, node): return self.visit(node.value) - # ExtSlice(slice* dims) + # ExtSlice(slice* dims) visit_ExtSlice = NotImplemented # Subscript(expr value, slice slice, expr_context ctx) @@ -350,7 +350,7 @@ def visit_Subscript(self, node): return "pythonium_call(pythonium_get_attribute({}, '__getitem__'), {})".format(self.visit(node.value), self.visit(node.slice)) # arguments = (arg* args, identifier? vararg, expr? varargannotation, - # arg* kwonlyargs, identifier? kwarg, expr? kwargannotation, + # arg* kwonlyargs, identifier? kwarg, expr? kwargannotation, # expr* defaults, expr* kw_defaults) def visit_arguments(self, node): args = list(map(lambda x: x.arg, node.args)) @@ -440,7 +440,7 @@ def visit_Call(self, node): except AttributeError: # it is not pass - + # positional args if node.args: args = [self.visit(e) for e in node.args] @@ -799,7 +799,7 @@ def visit_Dict(self, node): # For(expr target, expr iter, stmt* body, stmt* orelse) def visit_For(self, node): # support only arrays - target = node.target.id + target = node.target.id iterator = self.visit(node.iter) # iter is the python iterator self.writer.write('try {') self.writer.push() @@ -846,8 +846,8 @@ def _unpack_arguments(self, args, kwargs, varargs, varkwargs): position = num_args + index - 1 self.writer.write('if (varkwargs_start !== undefined && {} > varkwargs_start) {{'.format(position)) self.writer.push() - - self.writer.write('{} = {}.__class__.get({}, {}) || {};'.format(keyword, varkwargs, varkwargs, keyword, kwargs[keyword])) + + self.writer.write('{} = {}.__class__.get({}, {}) || {};'.format(keyword, varkwargs, varkwargs, keyword, kwargs[keyword])) self.writer.pull() self.writer.write('} else {') self.writer.push() @@ -879,7 +879,7 @@ def visit_Lambda(self, node): return name - # ClassDef(identifier name, expr* bases, keyword* keywords, + # ClassDef(identifier name, expr* bases, keyword* keywords, # expr? starargs, expr? kwargs, stmt* body, expr* decorator_list) def visit_ClassDef(self, node): # 'name', 'bases', 'keywords', 'starargs', 'kwargs', 'body', 'decorator_lis't @@ -907,4 +907,3 @@ def visit_ClassDef(self, node): self.writer.pull() self.writer.write('});') self._def_stack.pop() - From 70b4814e90db6a63c2e1bb2d15c3281c1470561d Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 11:40:26 +0100 Subject: [PATCH 133/160] veloce: fix lambda --- pythonium/veloce/veloce.py | 95 ++++++++++++++++++++++++++++++++------ tests/lambda.py | 8 +++- 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/pythonium/veloce/veloce.py b/pythonium/veloce/veloce.py index d610c41..5d1cef8 100644 --- a/pythonium/veloce/veloce.py +++ b/pythonium/veloce/veloce.py @@ -16,6 +16,13 @@ class Veloce(NodeVisitor): + @classmethod + def translate(cls, code): + translator = cls() + ast = parse(code) + translator.visit(ast) + return translator.writer.value() + def __init__(self): super().__init__() self.dependencies = [] @@ -386,23 +393,36 @@ def visit_Call(self, node): s = 'console.log({})'.format(', '.join(args)) return s else: + # positional args if node.args: args = [self.visit(e) for e in node.args] args = [e for e in args if e] else: args = [] - if node.keywords and not node.kwargs: - keywords = '__kwargs{}__'.format(self.uuid()) - _ = ', '.join(map(lambda x: '{}: {}'.format(x[0], x[1]), map(self.visit, node.keywords))) - self.writer.write('var {} = {{{}}}'.format(keywords, _)) - args.append(keywords) - elif node.kwargs and not node.keywords: - args.append(node.kwargs.id) - elif node.kwargs and node.keywords: + # variable arguments aka. starargs + call_arguments = 'call_arguments{}'.format(self.uuid()) + if node.starargs: + varargs = self.visit(node.starargs) + code = "for i in {}: jscode('{}.push(i)')".format(varargs, call_arguments) + self.writer.write(self.translate(code)) + # keywords and variable keywords arguments aka. starkwargs + if node.kwargs: + kwargs = self.visit(node.kwargs) + if node.keywords: + for key, value in map(self.visit, node.keywords): + self.writer.write('{}["{}"] = {};'.format(kwargs, key, value)) + elif node.keywords: + kwargs = '__pythonium_kwargs' + self.writer.write('var __pythonium_kwargs = {};') for key, value in map(self.visit, node.keywords): - self.writer.write('{}.{} = {}'.format(node.kwargs.id, key, value)) - args.append(node.kwargs.id) - return '{}({})'.format(name, ', '.join(args)) + self.writer.write('{}["{}"] = {};'.format(kwargs, key, value)) + if node.kwargs or node.keywords: + # XXX: define for every call since we can't define it globaly + self.writer.write('__ARGUMENTS_PADDING__ = {};') + args.append('__ARGUMENTS_PADDING__') + args.append(kwargs) + self.writer.write('var {} = [{}];'.format(call_arguments, ', '.join(args))) + return '{}.apply(undefined, {})'.format(name, call_arguments) # ListComp(expr elt, comprehension* generators) def visit_ListComp(self, node): @@ -686,10 +706,59 @@ def visit_Continue(self, node): def visit_Break(self, node): self.writer.write('break;') + def _unpack_arguments(self, args, kwargs, varargs, varkwargs): + self.writer.write('/* BEGIN arguments unpacking */') + if not varkwargs and kwargs: + varkwargs = '__kwargs' + + if varargs or (varkwargs and varkwargs != '__kwargs') or kwargs: + self.writer.write('var __args = Array.prototype.slice.call(arguments);') + if (varkwargs and varkwargs != '__kwargs') or kwargs: + self.writer.write('if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) {') + self.writer.push() + self.writer.write('var {} = __args[__args.length - 1];'.format(varkwargs)) + self.writer.write('var varkwargs_start = __args.length - 2;') + self.writer.pull() + self.writer.write('} else {') # no variable keywords was provided so it's empty + self.writer.push() + self.writer.write('var {} = {{}};'.format(varkwargs)) + self.writer.write('var varkwargs_start = undefined;') + self.writer.pull() + self.writer.write('}') + num_args = len(args) + for index, keyword in enumerate(kwargs.keys()): + position = num_args + index - 1 + self.writer.write('if (varkwargs_start !== undefined && {} > varkwargs_start) {{'.format(position)) + self.writer.push() + + self.writer.write('{} = {}[{}] || {};'.format(keyword, varkwargs, keyword, kwargs[keyword])) + self.writer.pull() + self.writer.write('} else {') + self.writer.push() + self.writer.write('{} = {} || {}[{}] || {};'.format(keyword, keyword, varkwargs, keyword, kwargs[keyword])) + self.writer.pull() + self.writer.write('}') + if varkwargs != '__kwargs': + self.writer.write('delete {}.{};'.format(varkwargs, keyword)) + if varargs: + self.writer.write('__args = __args.splice({});'.format(len(args))) + if varkwargs and (varkwargs != '__kwargs' or kwargs): + self.writer.write('if (varkwargs_start) {{ __args.splice(varkwargs_start - {}) }}'.format(len(args))) + self.writer.write('{} = __args;'.format(varargs)) + self.writer.write('/* END arguments unpacking */') + # Lambda(arguments args, expr body) def visit_Lambda(self, node): - args = ', '.join(map(self.visit, node.args.args)) - return '(function ({}) {{{}}})'.format(args, self.visit(node.body)) + args, kwargs, vararg, varkwargs = self.visit(node.args) + name = '__lambda{}'.format(self.uuid()) + self.writer.write('var {} = function({}) {{'.format(name, ', '.join(args))) + self.writer.push() + self._unpack_arguments(args, kwargs, vararg, varkwargs) + body = self.visit(node.body) + self.writer.write(body) + self.writer.pull() + self.writer.write('}') + return name # ClassDef(identifier name, expr* bases, keyword* keywords, # expr? starargs, expr? kwargs, stmt* body, expr* decorator_list) diff --git a/tests/lambda.py b/tests/lambda.py index 442408d..df31a87 100644 --- a/tests/lambda.py +++ b/tests/lambda.py @@ -1,2 +1,8 @@ -x = lambda x, y, *args, **kwargs: print(x, y, args, kwargs) +def func(x, y, arg, kwargs): + print(x) + print(y) + print(arg[0]) + print(arg[1]) + print(kwargs["key"]) +x = lambda x, y, *args, **kwargs: func(x, y, args, kwargs) x(42, 1337, 11, 100, key="value") From 63c41a134aafef7cd268f671d40790826ef0e3b8 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 11:55:05 +0100 Subject: [PATCH 134/160] veloce: fix calling and add support for IfExp => \o/ all tests are OK --- pythonium/veloce/veloce.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/pythonium/veloce/veloce.py b/pythonium/veloce/veloce.py index 5d1cef8..2a16fa0 100644 --- a/pythonium/veloce/veloce.py +++ b/pythonium/veloce/veloce.py @@ -421,8 +421,7 @@ def visit_Call(self, node): self.writer.write('__ARGUMENTS_PADDING__ = {};') args.append('__ARGUMENTS_PADDING__') args.append(kwargs) - self.writer.write('var {} = [{}];'.format(call_arguments, ', '.join(args))) - return '{}.apply(undefined, {})'.format(name, call_arguments) + return '{}({})'.format(name, ', '.join(args)) # ListComp(expr elt, comprehension* generators) def visit_ListComp(self, node): @@ -658,7 +657,20 @@ def visit_If(self, node): self.writer.write('}') # IfExp(expr test, expr body, expr orelse) - def visit_IfExp(self, node): raise NotImplemented + def visit_IfExp(self, node): + name = '__pythonium_ifexp_{}'.format(self.uuid()) + self.writer.write('if ({}) {{'.format(self.visit(node.test))) + self.writer.push() + body = self.visit(node.body) + self.writer.write('var {} = {};'.format(name, body)) + self.writer.pull() + self.writer.write('} else {') + self.writer.push() + orelse = self.visit(node.orelse) + self.writer.write('var {} = {};'.format(name, orelse)) + self.writer.pull() + self.writer.write('}') + return name # Ellipsis visit_Ellipsis = NotImplemented From 857d6bbc9aa00b18c6b969405a9dccc42cb6e0c4 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 12:00:10 +0100 Subject: [PATCH 135/160] replace travis image --- README.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index af04645..ca75c76 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,8 @@ Pythonium ######### -.. image:: https://travis-ci.org/pythonium/pythonium.png?branch=master :target: https://travis-ci.org/pythonium/pythonium +.. image:: https://travis-ci.org/pythonium/pythonium.png + :target: https://travis-ci.org/pythonium/pythonium **tldr**: Python 3 to Javascript translator written in Python that produces fast portable javascript code. From bf0eeb84860e29a507fa6ec0bb860a4c11ef4305 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 12:26:45 +0100 Subject: [PATCH 136/160] HACKING: git nodejs@v0.11.9 doesn't compile and remove --depth=1 which doesn't fetch the branches --- HACKING.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/HACKING.rst b/HACKING.rst index f581938..1c12f30 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -11,9 +11,11 @@ Requirements Installing nodejs ----------------- +**23/12/13 the following doesn't work, rely on your operating system documentation to install a recent version of nodejs** + cli dance in a **Python 2** environment, the build system does not support Python 3:: - git clone --depth 1 https://github.com/joyent/node.git + git clone https://github.com/joyent/node.git cd node git checkout v0.11.9 python2 configure From 8c9692ed74e082bc1394125372877e775376b879 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 12:28:04 +0100 Subject: [PATCH 137/160] compliant: replace x by __exception__ --- pythonium/compliant/compliant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 84022a4..4a01326 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -812,7 +812,7 @@ def visit_For(self, node): self.writer.pull() self.writer.write('}') self.writer.pull() - self.writer.write('} catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }}') + self.writer.write('} catch (__exception__) { if (!pythonium_is_exception(__exception__, StopIteration)) { throw x; }}') # Continue def visit_Continue(self, node): From e8f6ce3b8825448aad6e171f46a23746ea62b5a7 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 12:31:38 +0100 Subject: [PATCH 138/160] travis: fallback to 0.11.8 as there seems to be a regression preventing the test suite to pass --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3d848a8..ba1c4d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "0.11" + - "0.11.8" before_install: - sudo apt-get update - sudo apt-get install python3 python3-setuptools From 4b34aff23673c05f1a6549c7741cbf260b8c27be Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 12:33:40 +0100 Subject: [PATCH 139/160] Revert "travis: fallback to 0.11.8 as there seems to be a regression preventing the test suite to pass" This reverts commit e8f6ce3b8825448aad6e171f46a23746ea62b5a7. 0.11.8 is not installed on travis machines :( --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ba1c4d2..3d848a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "0.11.8" + - "0.11" before_install: - sudo apt-get update - sudo apt-get install python3 python3-setuptools From 44c825f05f60c87cb25f100e2ec9d77957bef3c1 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 12:38:14 +0100 Subject: [PATCH 140/160] CHANGELOG: update --- CHANGELOG.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index eff21d0..07cefe9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,5 +1,7 @@ 0.6.0 - - TBD + - compliant: added target unpack + - compliant: added list comprehension + - veloce: fixed lambda 0.5.0 - Web Console available online @ http://hypermove.net/pythonium-web-console/ From d55d962df2ddcbded5cb353b20bd46912fc7d912 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 13:47:01 +0100 Subject: [PATCH 141/160] examples, finished todo-list example - rework the example directory structure - finished the todo-list tutorial --- examples/{ => compliant}/todo-list/README.rst | 0 examples/{ => compliant}/todo-list/app.py | 0 examples/{ => compliant}/todo-list/app.py.js | 0 examples/{ => compliant}/todo-list/index.html | 0 examples/{ => compliant}/todo-list/jquery.js | 0 examples/{ => compliant}/todo-list/pythonium.js | 0 examples/{ => veloce}/threejs/README.md | 0 examples/{ => veloce}/threejs/app.js | 0 examples/{ => veloce}/threejs/app.py | 0 examples/{ => veloce}/threejs/index.html | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename examples/{ => compliant}/todo-list/README.rst (100%) rename examples/{ => compliant}/todo-list/app.py (100%) rename examples/{ => compliant}/todo-list/app.py.js (100%) rename examples/{ => compliant}/todo-list/index.html (100%) rename examples/{ => compliant}/todo-list/jquery.js (100%) rename examples/{ => compliant}/todo-list/pythonium.js (100%) rename examples/{ => veloce}/threejs/README.md (100%) rename examples/{ => veloce}/threejs/app.js (100%) rename examples/{ => veloce}/threejs/app.py (100%) rename examples/{ => veloce}/threejs/index.html (100%) diff --git a/examples/todo-list/README.rst b/examples/compliant/todo-list/README.rst similarity index 100% rename from examples/todo-list/README.rst rename to examples/compliant/todo-list/README.rst diff --git a/examples/todo-list/app.py b/examples/compliant/todo-list/app.py similarity index 100% rename from examples/todo-list/app.py rename to examples/compliant/todo-list/app.py diff --git a/examples/todo-list/app.py.js b/examples/compliant/todo-list/app.py.js similarity index 100% rename from examples/todo-list/app.py.js rename to examples/compliant/todo-list/app.py.js diff --git a/examples/todo-list/index.html b/examples/compliant/todo-list/index.html similarity index 100% rename from examples/todo-list/index.html rename to examples/compliant/todo-list/index.html diff --git a/examples/todo-list/jquery.js b/examples/compliant/todo-list/jquery.js similarity index 100% rename from examples/todo-list/jquery.js rename to examples/compliant/todo-list/jquery.js diff --git a/examples/todo-list/pythonium.js b/examples/compliant/todo-list/pythonium.js similarity index 100% rename from examples/todo-list/pythonium.js rename to examples/compliant/todo-list/pythonium.js diff --git a/examples/threejs/README.md b/examples/veloce/threejs/README.md similarity index 100% rename from examples/threejs/README.md rename to examples/veloce/threejs/README.md diff --git a/examples/threejs/app.js b/examples/veloce/threejs/app.js similarity index 100% rename from examples/threejs/app.js rename to examples/veloce/threejs/app.js diff --git a/examples/threejs/app.py b/examples/veloce/threejs/app.py similarity index 100% rename from examples/threejs/app.py rename to examples/veloce/threejs/app.py diff --git a/examples/threejs/index.html b/examples/veloce/threejs/index.html similarity index 100% rename from examples/threejs/index.html rename to examples/veloce/threejs/index.html From 16f58061f67f258bde7d0b8c5f5d4aba1740fef1 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 13:48:12 +0100 Subject: [PATCH 142/160] missing files from previous commit --- examples/compliant/todo-list/README.rst | 21 +- examples/compliant/todo-list/app.py | 14 +- examples/compliant/todo-list/app.py.js | 50 +- examples/compliant/todo-list/pythonium.js | 2689 +++++++++++++++------ pythonium/compliant/compliant.py | 3 +- 5 files changed, 2085 insertions(+), 692 deletions(-) diff --git a/examples/compliant/todo-list/README.rst b/examples/compliant/todo-list/README.rst index eb84b41..252256e 100644 --- a/examples/compliant/todo-list/README.rst +++ b/examples/compliant/todo-list/README.rst @@ -173,7 +173,26 @@ To attach this method to ``button``, use its ``click`` method:: button.click(on_click) -``add_todo`` is not yet defined and is left as an exercise. +add a todo +========== + +Add todo takes a str and need to add it to list of todos. First we need to fetch the list of todos:: + + todos = jQuery("#todos") + +Then a new ``li`` node must be added to the dom. For that matter we write a string of html with what we want to add to ``ul``:: + + li = '
  • ' + text + '
  • ' + +Now add it to the dom, for that let's use `jQuery.append `_, +append expects a JavaScript string so we need to convert li to javascript first:: + + li = jstype(li) + todos.append(li) + +Done! + +Checkout ``app.py`` file for the complete solution. Diving ====== diff --git a/examples/compliant/todo-list/app.py b/examples/compliant/todo-list/app.py index ec57d24..a26e316 100644 --- a/examples/compliant/todo-list/app.py +++ b/examples/compliant/todo-list/app.py @@ -3,8 +3,20 @@ def jQuery(selector): input = jQuery('[type="text"]') button = jQuery('[type="submit"]') +todos = jQuery('#todos') + + +def add_todo(text): + li = '
  • ' + text + '
  • ' + li = jstype(li) + todos.append(li) + def on_click(event): - print('Héy') + # event is JavaScript Event + text = str(input.val()) # convert the JavaScript string to a Python string + if len(text): + add_todo(text) + button.click(on_click) diff --git a/examples/compliant/todo-list/app.py.js b/examples/compliant/todo-list/app.py.js index 26f486a..ab0e371 100644 --- a/examples/compliant/todo-list/app.py.js +++ b/examples/compliant/todo-list/app.py.js @@ -1,17 +1,45 @@ var jQuery = function(selector) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - return pythonium_call($, pythonium_call(jstype, selector)); + var call_arguments0 = [jstype, selector]; + var call_arguments1 = [$, pythonium_call.apply(undefined, call_arguments0)]; + return pythonium_call.apply(undefined, call_arguments1); + return __NONE; }; -input = pythonium_call(jQuery, pythonium_call(str, '[type="text"]')); -button = pythonium_call(jQuery, pythonium_call(str, '[type="submit"]')); + +var call_arguments2 = [jQuery, pythonium_call(str, '[type="text"]')]; +input = pythonium_call.apply(undefined, call_arguments2); +var call_arguments3 = [jQuery, pythonium_call(str, '[type="submit"]')]; +button = pythonium_call.apply(undefined, call_arguments3); +var call_arguments4 = [jQuery, pythonium_call(str, "#todos")]; +todos = pythonium_call.apply(undefined, call_arguments4); +var add_todo = function(text) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var li; + /* BEGIN function */ + li = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "
  • "), "__add__"), text)), "__add__"), pythonium_call(str, "
  • "))); + var call_arguments5 = [jstype, li]; + li = pythonium_call.apply(undefined, call_arguments5); + var call_arguments6 = [pythonium_get_attribute(todos, "append"), li]; + pythonium_call.apply(undefined, call_arguments6); +}; + var on_click = function(event) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var text; /* BEGIN function */ - pythonium_call(print, pythonium_call(str, "Héy")); + var call_arguments7 = [pythonium_get_attribute(input, "val")]; + var call_arguments8 = [str, pythonium_call.apply(undefined, call_arguments7)]; + text = pythonium_call.apply(undefined, call_arguments8); + var call_arguments9 = [len, text]; + if (pythonium_is_true(pythonium_call.apply(undefined, call_arguments9))) { + var call_arguments10 = [add_todo, text]; + pythonium_call.apply(undefined, call_arguments10); + } }; -pythonium_call(pythonium_get_attribute(button, "click"), on_click); + +var call_arguments11 = [pythonium_get_attribute(button, "click"), on_click]; +pythonium_call.apply(undefined, call_arguments11); diff --git a/examples/compliant/todo-list/pythonium.js b/examples/compliant/todo-list/pythonium.js index c303293..24b0fb2 100644 --- a/examples/compliant/todo-list/pythonium.js +++ b/examples/compliant/todo-list/pythonium.js @@ -1,134 +1,229 @@ -__object = {__bases__:[],__name__:"object"}; -__object.__mro__ = [__object]; -__type = {__bases__:[__object],__mro__:[__object],__name__:"type"}; -__object.__metaclass__ = __type; +object = {__bases__:[],__name__:"object"}; +object.__mro__ = [object]; +type = {__bases__:[object],__mro__:[object],__name__:"type"}; +object.__metaclass__ = type; __ARGUMENTS_PADDING__ = {ARGUMENTS_PADDING:"YES IT IS!"}; -var __isnot__ = function(self, other) { - return !(this === other); -}; -__object.__isnot__ = __isnot__; +var __is__ = function(me, other) { + return (me === other); + return undefined; +}; +__is__.is_method = true; +object.__is__ = __is__; +var __isnot__ = function(me, other) { + return !(me === other); + return undefined; +}; +__isnot__.is_method = true; +object.__isnot__ = __isnot__; +var mro = function(me) { + var l,raw; + if((me === object)) { + raw = me.__mro__; + } + else { + if(me.__class__) { + raw = me.__class__.__mro__; + } + else { + raw = me.__mro__; + } + } + l = pythonium_call(tuple); + l.jsobject = raw.slice(); + return l; + return undefined; +}; +mro.is_method = true; +object.mro = mro; +var __hash__ = function(me) { + var uid; + uid = lookup(me, "uid"); + if(!uid) { + uid = object._uid; + object._uid = object._uid + 1; + me.__uid__ = uid; + } + return pythonium_call(str, ("{" + uid)); + return undefined; +}; +__hash__.is_method = true; +object._uid = 1; +object.__hash__ = __hash__; +var __rcontains__ = function(me, other) { + var contains; + contains = lookup(other, "__contains__"); + return contains(me); + return undefined; +}; +__rcontains__.is_method = true; +object.__rcontains__ = __rcontains__; var issubclass = function(klass, other) { if((klass === other)) { - return true; + return __TRUE; + return undefined; } if(!klass.__bases__) { - return false; + return __FALSE; + return undefined; } var iterator_base = klass.__bases__; for (var base_iterator_index=0; base_iterator_index < iterator_base.length; base_iterator_index++) { var base = iterator_base[base_iterator_index]; - if(issubclass(base, other)) { - return true; + if((issubclass(base, other) === __TRUE)) { + return __TRUE; + return undefined; } } - return false; -}; -var pythonium_create_dict = function(keys, values) { - var max,index,value,out,key; - out = {}; - max = keys.length; - index = 0; - while((index < max)) { - key = keys[index].jsobject; - value = values[index]; - out[key] = value; - index = index + 1; - } - return pythonium_call(dict, out, undefined); + return __FALSE; + return undefined; }; var pythonium_is_true = function(v) { - if(((v === __FALSE)||(v === false))) { + var length; + if((v === false)) { return false; + return undefined; } - if(((v === __TRUE)||(v !== undefined&&(v != __NONE)))) { + if((v === true)) { return true; + return undefined; + } + if((v === undefined)) { + return false; + return undefined; } - if(isinstance(v, int)) { - if((pythonium_get_attribute(v, "jsobject") == 0)) { + if((v === __NONE)) { + return false; + return undefined; + } + if((v === __FALSE)) { + return false; + return undefined; + } + if((isinstance(v, int)||isinstance(v, float))) { + if((v.jsobject == 0)) { return false; + return undefined; } - return true; } - return false; + length = lookup(v, "__len__"); + if((length&&(length().jsobject == 0))) { + return false; + return undefined; + } + return true; + return undefined; }; -var isinstance = function(object, klass) { - if(object.__class__) { - return issubclass(object.__class__, klass); +var isinstance = function(obj, klass) { + if(obj.__class__) { + return issubclass(obj.__class__, klass); + return undefined; } - return false; + return __FALSE; + return undefined; }; var pythonium_obj_to_js_exception = function(obj) { var exception = function() { this.exception = obj; }; return exception; + return undefined; }; var pythonium_is_exception = function(obj, exc) { if((obj === exc)) { return true; + return undefined; } return isinstance(obj, exc); + return undefined; }; -var pythonium_call = function(object) { - var instance,args,init; +var pythonium_call = function(obj) { + var args,instance,init; args = Array.prototype.slice.call(arguments, 1); - if(object.__metaclass__) { - instance = {__class__:object}; + if(obj.__metaclass__) { + instance = {__class__:obj}; init = lookup(instance, "__init__"); if(init) { init.apply(instance, args); } return instance; + return undefined; } else { - return object.apply(object, args); + return obj.apply(undefined, args); + return undefined; } }; +var pythonium_create_empty_dict = function() { + var instance; + instance = {__class__:dict}; + instance._keys = pythonium_call(list); + instance.jsobject = Object(); + return instance; + return undefined; +}; var pythonium_mro = function(bases) { - var res,seqs,non_empty,candidate,index,not_head,empty; + var candidate,not_head,out,non_empty,seqs,res; "Calculate the Method Resolution Order of bases using the C3 algorithm.\n\n Suppose you intended creating a class K with the given base classes. This\n function returns the MRO which K would have, *excluding* K itself (since\n it doesn't yet exist), as if you had actually created the class.\n\n Another way of looking at this, if you pass a single class K, this will\n return the linearization of K (the MRO of K, *including* itself).\n "; var __comp0__ = []; var __iterator1__ = bases; for (var __index2__ = 0; __index2__<__iterator1__.length; __index2__++) { var C = __iterator1__[__index2__]; - __comp0__.push(C.__mro__); + __comp0__.push(C.__mro__.slice()); } seqs = __comp0__; seqs.push(bases.slice()); + var cdr = function(l) { + l = l.slice(); + l = l.splice(1); + return l; + return undefined; + }; + var contains = function(l, c) { + var iterator_i = l; + for (var i_iterator_index=0; i_iterator_index < iterator_i.length; i_iterator_index++) { + var i = iterator_i[i_iterator_index]; + if((i === c)) { + return true; + return undefined; + } + } + return false; + return undefined; + }; res = []; while(true) { non_empty = []; var iterator_seq = seqs; for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { var seq = iterator_seq[seq_iterator_index]; - empty = true; + out = []; var iterator_item = seq; for (var item_iterator_index=0; item_iterator_index < iterator_item.length; item_iterator_index++) { var item = iterator_item[item_iterator_index]; if(item) { - empty = false; - break; + out.push(item); } } - if(!empty) { - non_empty.push(seq); + if((out.length != 0)) { + non_empty.push(out); } } if((non_empty.length == 0)) { return res; + return undefined; } var iterator_seq = non_empty; for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { var seq = iterator_seq[seq_iterator_index]; candidate = seq[0]; - var __comp3__ = []; - var __iterator4__ = non_empty; - for (var __index5__ = 0; __index5__<__iterator4__.length; __index5__++) { - var s = __iterator4__[__index5__]; - if(!(candidate in s.splice(1))) { continue; } - __comp3__.push(s); + not_head = []; + var iterator_s = non_empty; + for (var s_iterator_index=0; s_iterator_index < iterator_s.length; s_iterator_index++) { + var s = iterator_s[s_iterator_index]; + if(contains(cdr(s), candidate)) { + not_head.push(s); + } } - not_head = __comp3__; if((not_head.length != 0)) { candidate = undefined; } @@ -140,915 +235,2153 @@ var pythonium_mro = function(bases) { throw TypeError("Inconsistent hierarchy, no C3 MRO is possible"); } res.push(candidate); - var iterator_seq = seqs; + var iterator_seq = non_empty; for (var seq_iterator_index=0; seq_iterator_index < iterator_seq.length; seq_iterator_index++) { var seq = iterator_seq[seq_iterator_index]; - index = seq.indexOf(candidate); - if((index >= 0)) { - delete seq[index]; + if((seq[0] === candidate)) { + seq[0] = undefined; } } + seqs = non_empty; } }; var pythonium_create_class = function(name, bases, attrs) { var mro; attrs.__name__ = name; - attrs.__metaclass__ = __type; + attrs.__metaclass__ = type; attrs.__bases__ = bases; mro = pythonium_mro(bases); mro.splice(0, 0, attrs); attrs.__mro__ = mro; return attrs; + return undefined; }; -var lookup = function(object, attr) { - var class_attr,object_attr; - object_attr = object[attr]; - if((object_attr != undefined)) { - if((object_attr&&({}.toString.call(object_attr) == "[object Function]"))) { +var lookup = function(obj, attr) { + var class_attr,obj_attr,__mro__; + obj_attr = obj[attr]; + if((obj_attr != undefined)) { + if((obj_attr&&({}.toString.call(obj_attr) == "[object Function]")&&obj_attr.is_method&&!obj_attr.bound)) { var method_wrapper = function() { var args; args = Array.prototype.slice.call(arguments); - args.splice(0, 0, object); - return object_attr.apply(undefined, args); + args.splice(0, 0, obj); + return obj_attr.apply(undefined, args); + return undefined; }; + method_wrapper.bound = true; return method_wrapper; + return undefined; } - return object_attr; + return obj_attr; + return undefined; } else { - var iterator_base = object.__class__.__mro__; + if(obj.__class__) { + __mro__ = obj.__class__.__mro__; + } + else { + if(obj.__metaclass__) { + __mro__ = obj.__metaclass__.__mro__; + } + else { + return undefined; + return undefined; + } + } + var iterator_base = __mro__; for (var base_iterator_index=0; base_iterator_index < iterator_base.length; base_iterator_index++) { var base = iterator_base[base_iterator_index]; class_attr = base[attr]; if((class_attr != undefined)) { - if(({}.toString.call(class_attr) == "[object Function]")) { + if((({}.toString.call(class_attr) == "[object Function]")&&class_attr.is_method&&!class_attr.bound)) { var method_wrapper = function() { var args; args = Array.prototype.slice.call(arguments); - args.splice(0, 0, object); + args.splice(0, 0, obj); return class_attr.apply(undefined, args); + return undefined; }; + method_wrapper.bound = true; return method_wrapper; + return undefined; } return class_attr; + return undefined; } } } }; -var pythonium_object_get_attribute = function(object, attr) { +var pythonium_object_get_attribute = function(obj, attr) { var r,getattr; - r = lookup(object, attr); + r = lookup(obj, attr); if((r != undefined)) { return r; + return undefined; } else { - getattr = lookup(object, "__getattr__"); + getattr = lookup(obj, "__getattr__"); if(getattr) { return getattr(attr); + return undefined; } else { + console.trace("AttributeError", attr, obj); throw AttributeError; } } }; -__object.__getattribute__ = pythonium_object_get_attribute; -var pythonium_get_attribute = function(object, attr) { - var getattribute; - if(object.__class__) { - getattribute = lookup(object, "__getattribute__"); - return getattribute(attr); +pythonium_object_get_attribute.is_method = true; +object.__getattribute__ = pythonium_object_get_attribute; +var pythonium_get_attribute = function(obj, attr) { + var r,getattribute; + if((obj.__class__||obj.__metaclass__)) { + getattribute = lookup(obj, "__getattribute__"); + r = getattribute(attr); + return r; + return undefined; } - attr = object[attr]; + attr = obj[attr]; if(attr) { if(({}.toString.call(attr) == "[object Function]")) { var method_wrapper = function() { - return attr.apply(object, arguments); + return attr.apply(obj, arguments); + return undefined; }; return method_wrapper; + return undefined; } else { return attr; + return undefined; } } }; -var pythonium_set_attribute = function(object, attr, value) { - object[attr] = value; +var pythonium_set_attribute = function(obj, attr, value) { + obj[attr] = value; }; -var range = function(a, b) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { - var __kwargs = __args[__args.length - 1]; - var varkwargs_start = __args.length - 2; - } else { - var __kwargs = {}; - var varkwargs_start = undefined; - } - if (varkwargs_start !== undefined && 1 > varkwargs_start) { - b = __kwargs.b || __NONE; - } else { - b = b || __kwargs.b || __NONE; +var ASSERT = function(condition, message) { + if(!condition) { + throw (message||pythonium_call(str, "Assertion failed")); } - /* END unpacking arguments */ - var index,end,out; +}; +/* class definition int */ +var __int___init__ = function(self, jsobject) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - if (pythonium_is_true(b)) { - index = a; - end = b; - } - else { - index = pythonium_call(int, 0); - end = a; - } - out = pythonium_call(list); - while(pythonium_is_true((pythonium_get_attribute(index, "__lt__")(end)))) { - pythonium_call(pythonium_get_attribute(out, "append"), index); - index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); - } - return out; + pythonium_set_attribute(self, "jsobject", jsobject); }; -var repr = function(obj) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___init__.is_method = true; + +var __int___not__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject; /* BEGIN function */ - return pythonium_call(pythonium_get_attribute(obj, "__repr__")); + jsobject = pythonium_get_attribute(self, "jsobject"); + if (pythonium_is_true(jsobject == 0)) { + return __TRUE; + return __NONE; + } + return __FALSE; + return __NONE; }; -var print = function() { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - var args = __args.splice(0); - args = pythonium_call(list, args); - /* END unpacking arguments */ - var out,r; +__int___not__.is_method = true; + +var __int___abs__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - out = pythonium_call(list); - try { - var __next__ = pythonium_get_attribute(iter(args), "__next__"); - while(true) { - var arg = pythonium_call(__next__); - r = pythonium_call(repr, arg); - pythonium_call(pythonium_get_attribute(out, "append"), pythonium_get_attribute(r, "jsobject")); - } - } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} - pythonium_call(pythonium_get_attribute(pythonium_get_attribute(console, "log"), "apply"), console, pythonium_get_attribute(out, "jsobject")); + if (pythonium_is_true((pythonium_get_attribute(self, "__lt__")(pythonium_call(int, 0))))) { + return pythonium_call(pythonium_get_attribute(self, "__neg__")); + return __NONE; + } + return self; + return __NONE; }; -var map = function(func, objects) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var out; +__int___abs__.is_method = true; + +var __int___neg__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject; /* BEGIN function */ - out = pythonium_call(list); - try { - var __next__ = pythonium_get_attribute(iter(objects), "__next__"); - while(true) { - var obj = pythonium_call(__next__); - pythonium_call(pythonium_get_attribute(out, "append"), pythonium_call(func, obj)); - } - } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} - return out; + jsobject = pythonium_get_attribute(self, "jsobject"); + var call_arguments0 = [int, -self.jsobject]; + return pythonium_call.apply(undefined, call_arguments0); + return __NONE; +}; +__int___neg__.is_method = true; + +var __int___hash__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments1 = [str, pythonium_get_attribute(self, "jsobject")]; + return pythonium_call.apply(undefined, call_arguments1); + return __NONE; +}; +__int___hash__.is_method = true; + +var __int___jstype__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + return pythonium_get_attribute(self, "jsobject"); + return __NONE; +}; +__int___jstype__.is_method = true; + +var __int___repr__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + var call_arguments2 = [str, jsobject.toString()]; + return pythonium_call.apply(undefined, call_arguments2); + return __NONE; }; -var jstype = function(obj) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___repr__.is_method = true; + +var __int___add__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - return pythonium_get_attribute(obj, "jsobject"); + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + var call_arguments3 = [int, a + b]; + return pythonium_call.apply(undefined, call_arguments3); + return __NONE; }; -/* class definition _True */ -var __init__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___add__.is_method = true; + +var __int___sub__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - pythonium_set_attribute(self, "jsobject", true); + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + var call_arguments4 = [int, a - b]; + return pythonium_call.apply(undefined, call_arguments4); + return __NONE; }; -var __and__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___sub__.is_method = true; + +var __int___lt__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - if (pythonium_is_true(other === self)) { + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a < b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __or__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___lt__.is_method = true; + +var __int___gt__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - return __TRUE; + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a > b)) { + return __TRUE; + return __NONE; + } + return __FALSE; + return __NONE; }; -var __is__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___gt__.is_method = true; + +var __int___gte__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - if (pythonium_is_true(other === self)) { + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a >= b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __neg__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___gte__.is_method = true; + +var __int___lte__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a <= b)) { + return __TRUE; + return __NONE; + } return __FALSE; + return __NONE; }; -var _True = pythonium_create_class("_True", [__object], { - __init__: __init__, - __and__: __and__, - __or__: __or__, - __is__: __is__, - __neg__: __neg__, -}); -/* class definition _False */ -var __init__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___lte__.is_method = true; + +var __int___mul__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,c,a; /* BEGIN function */ - pythonium_set_attribute(self, "jsobject", false); + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a * b; + var call_arguments5 = [int, c]; + return pythonium_call.apply(undefined, call_arguments5); + return __NONE; }; -var __and__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___mul__.is_method = true; + +var __int___or__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,c,a; /* BEGIN function */ - return __FALSE; + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a || b; + var call_arguments6 = [int, c]; + return pythonium_call.apply(undefined, call_arguments6); + return __NONE; }; -var __or__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___or__.is_method = true; + +var __int___eq__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - if (pythonium_is_true(other === True)) { + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a == b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __is__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___eq__.is_method = true; + +var __int___neq__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - if (pythonium_is_true(other === self)) { - return __TRUE; - } - return __FALSE; + var call_arguments7 = [pythonium_get_attribute(self, "__eq__"), other]; + return pythonium_call(pythonium_get_attribute(pythonium_call.apply(undefined, call_arguments7), "__not__")); + return __NONE; }; -var __neg__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__int___neq__.is_method = true; + +var __int___div__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - return __TRUE; -}; -var _False = pythonium_create_class("_False", [__object], { - __init__: __init__, - __and__: __and__, - __or__: __or__, - __is__: __is__, - __neg__: __neg__, -}); -__TRUE = pythonium_call(_True); -__FALSE = pythonium_call(_False); -/* class definition StopIteration */ -/* pass */ -var StopIteration = pythonium_create_class("StopIteration", [__object], { + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + var call_arguments8 = [int, a / b]; + return pythonium_call.apply(undefined, call_arguments8); + return __NONE; +}; +__int___div__.is_method = true; + +var int = pythonium_create_class("int", [object], { + __init__: __int___init__, + __not__: __int___not__, + __abs__: __int___abs__, + __neg__: __int___neg__, + __hash__: __int___hash__, + __jstype__: __int___jstype__, + __repr__: __int___repr__, + __add__: __int___add__, + __sub__: __int___sub__, + __lt__: __int___lt__, + __gt__: __int___gt__, + __gte__: __int___gte__, + __lte__: __int___lte__, + __mul__: __int___mul__, + __or__: __int___or__, + __eq__: __int___eq__, + __neq__: __int___neq__, + __div__: __int___div__, }); -var iter = function(obj) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +/* class definition bool */ +var __bool___init__ = function(self, obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + if (pythonium_is_true(obj !== undefined)) { + var call_arguments0 = [pythonium_is_true, obj]; + pythonium_set_attribute(self, "jsobject", pythonium_call.apply(undefined, call_arguments0)); + } + else { + pythonium_set_attribute(self, "jsobject", false); + } +}; +__bool___init__.is_method = true; + +var __bool___jstype__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - return pythonium_call(pythonium_get_attribute(obj, "__iter__")); + return pythonium_get_attribute(self, "jsobject"); + return __NONE; }; -var next = function(obj) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__bool___jstype__.is_method = true; + +var __bool___repr__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - return pythonium_call(pythonium_get_attribute(obj, "__next__")); + if (pythonium_is_true(pythonium_get_attribute(self, "jsobject"))) { + return pythonium_call(str, "True"); + return __NONE; + } + return pythonium_call(str, "False"); + return __NONE; +}; +__bool___repr__.is_method = true; + +var __bool___and__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + if (pythonium_is_true(self)) { + if (pythonium_is_true(other)) { + return __TRUE; + return __NONE; + } + } + return __FALSE; + return __NONE; }; -var len = function(obj) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__bool___and__.is_method = true; + +var __bool___or__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - return pythonium_call(pythonium_get_attribute(obj, "__len__")); + if (pythonium_is_true(self)) { + return __TRUE; + return __NONE; + } + if (pythonium_is_true(other)) { + return __TRUE; + return __NONE; + } + return __FALSE; + return __NONE; }; -/* class definition ListIterator */ -var __init__ = function(self, obj) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__bool___or__.is_method = true; + +var __bool___is__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - pythonium_set_attribute(self, "list", obj); - pythonium_set_attribute(self, "index", pythonium_call(int, 0)); - pythonium_set_attribute(self, "length", pythonium_call(len, obj)); + if (pythonium_is_true(self === other)) { + return __TRUE; + return __NONE; + } + return __FALSE; + return __NONE; }; -var __next__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__bool___is__.is_method = true; + +var __bool___neg__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - if (pythonium_is_true((pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__eq__")(pythonium_get_attribute(self, "length"))))) { - throw StopIteration; + if (pythonium_is_true(self)) { + return __FALSE; + return __NONE; } - pythonium_set_attribute(self, "index", (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__add__"), pythonium_call(int, 1)))); - return pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "list"), '__getitem__'), (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__sub__"), pythonium_call(int, 1)))); + return __TRUE; + return __NONE; }; -var ListIterator = pythonium_create_class("ListIterator", [__object], { - __init__: __init__, - __next__: __next__, +__bool___neg__.is_method = true; + +var __bool___not__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + if (pythonium_is_true(self)) { + return __FALSE; + return __NONE; + } + return __TRUE; + return __NONE; +}; +__bool___not__.is_method = true; + +var bool = pythonium_create_class("bool", [int], { + __init__: __bool___init__, + __jstype__: __bool___jstype__, + __repr__: __bool___repr__, + __and__: __bool___and__, + __or__: __bool___or__, + __is__: __bool___is__, + __neg__: __bool___neg__, + __not__: __bool___not__, }); -/* class definition list */ -var __init__ = function(self, jsobject) { - /* BEGIN unpacking arguments */ +var call_arguments1 = [bool, true]; +__TRUE = pythonium_call.apply(undefined, call_arguments1); +var call_arguments2 = [bool]; +__FALSE = pythonium_call.apply(undefined, call_arguments2); +var nest_str_with_quotes = function(s) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var r; + /* BEGIN function */ + var call_arguments0 = [repr, s]; + r = pythonium_call.apply(undefined, call_arguments0); + var call_arguments1 = [isinstance, s, str]; + if (pythonium_is_true(pythonium_call.apply(undefined, call_arguments1))) { + if (pythonium_is_true((pythonium_get_attribute(pythonium_call(str, "'"), "__rcontains__")(r)))) { + r = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, '"'), "__add__"), r)), "__add__"), pythonium_call(str, '"'))); + } + else { + r = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "'"), "__add__"), r)), "__add__"), pythonium_call(str, "'"))); + } + } + return r; + return __NONE; +}; + +/* class definition dict */ +var __dict___init__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments2 = [list]; + pythonium_set_attribute(self, "_keys", pythonium_call.apply(undefined, call_arguments2)); + pythonium_set_attribute(self, "jsobject", Object()); +}; +__dict___init__.is_method = true; + +var __dict___hash__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments3 = [TypeError, pythonium_call(str, "unhashable type: 'dict'")]; + throw pythonium_call.apply(undefined, call_arguments3); +}; +__dict___hash__.is_method = true; + +var __dict___jstype__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + throw NotImplementedError; +}; +__dict___jstype__.is_method = true; + +var __dict___repr__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var out,value_repr,key_repr; + /* BEGIN function */ + out = pythonium_call(list); + try { + var __next4__ = pythonium_get_attribute(iter(pythonium_get_attribute(self, "_keys")), "__next__"); + while(true) { + var key = __next4__(); + var call_arguments5 = [nest_str_with_quotes, key]; + key_repr = pythonium_call.apply(undefined, call_arguments5); + var call_arguments6 = [nest_str_with_quotes, pythonium_call(pythonium_get_attribute(self, '__getitem__'), key)]; + value_repr = pythonium_call.apply(undefined, call_arguments6); + var call_arguments7 = [pythonium_get_attribute(out, "append"), (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(key_repr, "__add__"), pythonium_call(str, ": "))), "__add__"), value_repr))]; + pythonium_call.apply(undefined, call_arguments7); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + var call_arguments8 = [pythonium_get_attribute(pythonium_call(str, ", "), "join"), out]; + return (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "{"), "__add__"), pythonium_call.apply(undefined, call_arguments8))), "__add__"), pythonium_call(str, "}"))); + return __NONE; +}; +__dict___repr__.is_method = true; + +var __dict_get = function(self, key, d) { + /* BEGIN arguments unpacking */ var __args = Array.prototype.slice.call(arguments); if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { var __kwargs = __args[__args.length - 1]; var varkwargs_start = __args.length - 2; } else { - var __kwargs = {}; + var __kwargs = pythonium_create_empty_dict(); var varkwargs_start = undefined; } - if (varkwargs_start !== undefined && 1 > varkwargs_start) { - jsobject = __kwargs.jsobject || __NONE; + if (varkwargs_start !== undefined && 2 > varkwargs_start) { + d = __kwargs.__class__.get(__kwargs, d) || __NONE; } else { - jsobject = jsobject || __kwargs.jsobject || __NONE; + d = d || __kwargs.__class__.get(__kwargs, d) || __NONE; + } + /* END arguments unpacking */ + var jsobject,h; + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(key, "__rcontains__")(pythonium_get_attribute(self, "_keys"))))) { + var call_arguments9 = [hash, key]; + var call_arguments10 = [jstype, pythonium_call.apply(undefined, call_arguments9)]; + h = pythonium_call.apply(undefined, call_arguments10); + jsobject = pythonium_get_attribute(self, "jsobject"); + return jsobject[h]; + return __NONE; } - /* END unpacking arguments */ + return d; + return __NONE; +}; +__dict_get.is_method = true; + +var __dict___len__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments11 = [len, pythonium_get_attribute(self, "_keys")]; + return pythonium_call.apply(undefined, call_arguments11); + return __NONE; +}; +__dict___len__.is_method = true; + +var __dict___iter__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments12 = [ListIterator, pythonium_get_attribute(self, "_keys")]; + return pythonium_call.apply(undefined, call_arguments12); + return __NONE; +}; +__dict___iter__.is_method = true; + +var __dict___getitem__ = function(self, key) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,h; + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(key, "__rcontains__")(pythonium_get_attribute(self, "_keys"))))) { + var call_arguments13 = [hash, key]; + var call_arguments14 = [jstype, pythonium_call.apply(undefined, call_arguments13)]; + h = pythonium_call.apply(undefined, call_arguments14); + jsobject = pythonium_get_attribute(self, "jsobject"); + return jsobject[h]; + return __NONE; + } + var call_arguments15 = [KeyError, key]; + throw pythonium_call.apply(undefined, call_arguments15); +}; +__dict___getitem__.is_method = true; + +var __dict___setitem__ = function(self, key, value) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,h; + /* BEGIN function */ + var call_arguments16 = [hash, key]; + var call_arguments17 = [jstype, pythonium_call.apply(undefined, call_arguments16)]; + h = pythonium_call.apply(undefined, call_arguments17); + jsobject = pythonium_get_attribute(self, "jsobject"); + jsobject[h] = value; + var call_arguments18 = [pythonium_get_attribute(pythonium_get_attribute(self, "_keys"), "append"), key]; + pythonium_call.apply(undefined, call_arguments18); +}; +__dict___setitem__.is_method = true; + +var __dict_keys = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + return pythonium_get_attribute(self, "_keys"); + return __NONE; +}; +__dict_keys.is_method = true; + +var __dict_items = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var out; /* BEGIN function */ - if (pythonium_is_true(jsobject)) { - pythonium_set_attribute(self, "jsobject", jsobject); + var call_arguments19 = [list]; + out = pythonium_call.apply(undefined, call_arguments19); + try { + var __next20__ = pythonium_get_attribute(iter(pythonium_get_attribute(self, "_keys")), "__next__"); + while(true) { + var key = __next20__(); + var __a_list21 = pythonium_call(list); + __a_list21.jsobject = [key, pythonium_call(pythonium_get_attribute(self, '__getitem__'), key)]; + var call_arguments22 = [pythonium_get_attribute(out, "append"), __a_list21]; + pythonium_call.apply(undefined, call_arguments22); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return out; + return __NONE; +}; +__dict_items.is_method = true; + +var __dict___delitem__ = function(self, key) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,h; + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(key, "__rcontains__")(pythonium_get_attribute(self, "_keys"))))) { + var call_arguments23 = [pythonium_get_attribute(pythonium_get_attribute(self, "_keys"), "remove"), key]; + pythonium_call.apply(undefined, call_arguments23); + var call_arguments24 = [hash, key]; + var call_arguments25 = [jstype, pythonium_call.apply(undefined, call_arguments24)]; + h = pythonium_call.apply(undefined, call_arguments25); + jsobject = pythonium_get_attribute(self, "jsobject"); + delete jsobject[h]; } else { - pythonium_set_attribute(self, "jsobject", []); + throw KeyError; } }; -var __repr__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var s; - /* BEGIN function */ - s = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "["), "__add__"), pythonium_call(pythonium_get_attribute(pythonium_call(str, ", "), "join"), self))), "__add__"), pythonium_call(str, "]"))); - return s; -}; -var append = function(self, item) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var jsobject; +__dict___delitem__.is_method = true; + +var dict = pythonium_create_class("dict", [object], { + __init__: __dict___init__, + __hash__: __dict___hash__, + __jstype__: __dict___jstype__, + __repr__: __dict___repr__, + get: __dict_get, + __len__: __dict___len__, + __iter__: __dict___iter__, + __getitem__: __dict___getitem__, + __setitem__: __dict___setitem__, + keys: __dict_keys, + items: __dict_items, + __delitem__: __dict___delitem__, +}); +/* class definition Exception */ +var __Exception___init__ = function(self, message) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - jsobject = pythonium_get_attribute(self, "jsobject"); - jsobject.push(item); + pythonium_set_attribute(self, "message", message); }; -var insert = function(self, index, item) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__Exception___init__.is_method = true; + +var Exception = pythonium_create_class("Exception", [object], { + __init__: __Exception___init__, +}); +/* class definition TypeError */ +/* pass */ +var TypeError = pythonium_create_class("TypeError", [Exception], { +}); +/* class definition AttributeError */ +/* pass */ +var AttributeError = pythonium_create_class("AttributeError", [Exception], { +}); +/* class definition KeyError */ +/* pass */ +var KeyError = pythonium_create_class("KeyError", [Exception], { +}); +/* class definition StopIteration */ +/* pass */ +var StopIteration = pythonium_create_class("StopIteration", [Exception], { +}); +/* class definition NotImplementedError */ +/* pass */ +var NotImplementedError = pythonium_create_class("NotImplementedError", [Exception], { +}); +/* class definition NotImplemented */ +/* pass */ +var NotImplemented = pythonium_create_class("NotImplemented", [Exception], { +}); +/* class definition ValueError */ +/* pass */ +var ValueError = pythonium_create_class("ValueError", [Exception], { +}); +/* class definition float */ +var __float___init__ = function(self, jsobject) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "splice"), index, pythonium_call(int, 0), item); + pythonium_set_attribute(self, "jsobject", jsobject); }; -var __setitem__ = function(self, index, value) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__float___init__.is_method = true; + +var __float___hash__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments0 = [str, pythonium_get_attribute(self, "jsobject")]; + return pythonium_call.apply(undefined, call_arguments0); + return __NONE; +}; +__float___hash__.is_method = true; + +var __float___repr__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ var jsobject; /* BEGIN function */ jsobject = pythonium_get_attribute(self, "jsobject"); - index = pythonium_get_attribute(index, "jsobject"); - jsobject[index] = value; -}; -var __getitem__ = function(self, s) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var index,jsobject; + var call_arguments1 = [str, jsobject.toString()]; + return pythonium_call.apply(undefined, call_arguments1); + return __NONE; +}; +__float___repr__.is_method = true; + +var __float___neg__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject; /* BEGIN function */ jsobject = pythonium_get_attribute(self, "jsobject"); - index = pythonium_get_attribute(s, "jsobject"); - return jsobject[index]; + var call_arguments2 = [int, -self.jsobject]; + return pythonium_call.apply(undefined, call_arguments2); + return __NONE; +}; +__float___neg__.is_method = true; + +var __float___abs__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(self, "__lt__")(pythonium_call(int, 0))))) { + return pythonium_call(pythonium_get_attribute(self, "__neg__")); + return __NONE; + } + return self; + return __NONE; }; -var __len__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var length,jsobject; +__float___abs__.is_method = true; + +var __float___sub__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - jsobject = pythonium_get_attribute(self, "jsobject"); - length = jsobject.length; - return pythonium_call(int, length); + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + var call_arguments3 = [float, a - b]; + return pythonium_call.apply(undefined, call_arguments3); + return __NONE; }; -var __iter__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - /* BEGIN function */ - return pythonium_call(ListIterator, self); -}; -var list = pythonium_create_class("list", [__object], { - __init__: __init__, - __repr__: __repr__, - append: append, - insert: insert, - __setitem__: __setitem__, - __getitem__: __getitem__, - __len__: __len__, - __iter__: __iter__, -}); -/* class definition float */ -var __init__ = function(self, jsobject) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - /* BEGIN function */ - pythonium_set_attribute(self, "jsobject", jsobject); -}; -var __repr__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - /* BEGIN function */ - return self; -}; -var __div__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__float___sub__.is_method = true; + +var __float___eq__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ a = pythonium_get_attribute(self, "jsobject"); b = pythonium_get_attribute(other, "jsobject"); - return pythonium_call(float, a / b); + if (pythonium_is_true(a == b)) { + return __TRUE; + return __NONE; + } + return __FALSE; + return __NONE; }; -var __sub__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__float___eq__.is_method = true; + +var __float___add__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ a = pythonium_get_attribute(self, "jsobject"); b = pythonium_get_attribute(other, "jsobject"); - return pythonium_call(float, a - b); + var call_arguments4 = [int, a + b]; + return pythonium_call.apply(undefined, call_arguments4); + return __NONE; }; -var __eq__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__float___add__.is_method = true; + +var __float___lt__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ a = pythonium_get_attribute(self, "jsobject"); b = pythonium_get_attribute(other, "jsobject"); - if (pythonium_is_true(a == b)) { + if (pythonium_is_true(a < b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var float = pythonium_create_class("float", [__object], { - __init__: __init__, - __repr__: __repr__, - __div__: __div__, - __sub__: __sub__, - __eq__: __eq__, -}); -/* class definition _None */ -var __and__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__float___lt__.is_method = true; + +var __float___gt__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a > b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __or__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__float___gt__.is_method = true; + +var __float___gte__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a >= b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __is__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__float___gte__.is_method = true; + +var __float___lte__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ - if (pythonium_is_true(other === self)) { + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + if (pythonium_is_true(a <= b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __neg__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__float___lte__.is_method = true; + +var __float___mul__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,c,a; /* BEGIN function */ - return __TRUE; + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a * b; + var call_arguments5 = [int, c]; + return pythonium_call.apply(undefined, call_arguments5); + return __NONE; }; -var _None = pythonium_create_class("_None", [__object], { - __and__: __and__, - __or__: __or__, - __is__: __is__, - __neg__: __neg__, +__float___mul__.is_method = true; + +var __float___or__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,c,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + c = a || b; + var call_arguments6 = [int, c]; + return pythonium_call.apply(undefined, call_arguments6); + return __NONE; +}; +__float___or__.is_method = true; + +var __float___neq__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments7 = [pythonium_get_attribute(self, "__eq__"), other]; + return pythonium_call(pythonium_get_attribute(pythonium_call.apply(undefined, call_arguments7), "__not__")); + return __NONE; +}; +__float___neq__.is_method = true; + +var __float___div__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; + /* BEGIN function */ + a = pythonium_get_attribute(self, "jsobject"); + b = pythonium_get_attribute(other, "jsobject"); + var call_arguments8 = [int, a / b]; + return pythonium_call.apply(undefined, call_arguments8); + return __NONE; +}; +__float___div__.is_method = true; + +var float = pythonium_create_class("float", [object], { + __init__: __float___init__, + __hash__: __float___hash__, + __repr__: __float___repr__, + __neg__: __float___neg__, + __abs__: __float___abs__, + __sub__: __float___sub__, + __eq__: __float___eq__, + __add__: __float___add__, + __lt__: __float___lt__, + __gt__: __float___gt__, + __gte__: __float___gte__, + __lte__: __float___lte__, + __mul__: __float___mul__, + __or__: __float___or__, + __neq__: __float___neq__, + __div__: __float___div__, }); -__NONE = pythonium_call(_None); -/* class definition iterator */ -var __init__ = function(self, list) { - /* BEGIN unpacking arguments */ +/* class definition range */ +var __range___init__ = function(self, a, b) { + /* BEGIN arguments unpacking */ var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = pythonium_create_empty_dict(); + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 2 > varkwargs_start) { + b = __kwargs.__class__.get(__kwargs, b) || __NONE; + } else { + b = b || __kwargs.__class__.get(__kwargs, b) || __NONE; + } + /* END arguments unpacking */ /* BEGIN function */ - /* pass */ + if (pythonium_is_true(b)) { + pythonium_set_attribute(self, "index", a); + pythonium_set_attribute(self, "end", b); + } + else { + pythonium_set_attribute(self, "index", pythonium_call(int, 0)); + pythonium_set_attribute(self, "end", a); + } }; -var iterator = pythonium_create_class("iterator", [__object], { - __init__: __init__, +__range___init__.is_method = true; + +var __range___iter__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + return self; + return __NONE; +}; +__range___iter__.is_method = true; + +var __range___next__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var index; + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__lt__")(pythonium_get_attribute(self, "end"))))) { + index = pythonium_get_attribute(self, "index"); + pythonium_get_attribute(self, "index") = pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__add__"), pythonium_call(int, 1)); + return index; + return __NONE; + } + throw StopIteration; +}; +__range___next__.is_method = true; + +var range = pythonium_create_class("range", [object], { + __init__: __range___init__, + __iter__: __range___iter__, + __next__: __range___next__, }); -/* class definition slice */ -var __init__ = function(self, start, step, end) { - /* BEGIN unpacking arguments */ +var range = function(a, b) { + /* BEGIN arguments unpacking */ var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ + if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { + var __kwargs = __args[__args.length - 1]; + var varkwargs_start = __args.length - 2; + } else { + var __kwargs = pythonium_create_empty_dict(); + var varkwargs_start = undefined; + } + if (varkwargs_start !== undefined && 1 > varkwargs_start) { + b = __kwargs.__class__.get(__kwargs, b) || __NONE; + } else { + b = b || __kwargs.__class__.get(__kwargs, b) || __NONE; + } + /* END arguments unpacking */ + var out; /* BEGIN function */ - pythonium_set_attribute(self, "start", start); - pythonium_set_attribute(self, "step", step); - pythonium_set_attribute(self, "end", end); + var call_arguments0 = [list]; + out = pythonium_call.apply(undefined, call_arguments0); + while(pythonium_is_true((pythonium_get_attribute(index, "__lt__")(end)))) { + var call_arguments1 = [pythonium_get_attribute(out, "append"), index]; + pythonium_call.apply(undefined, call_arguments1); + index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); + } + return out; + return __NONE; }; -var slice = pythonium_create_class("slice", [__object], { - __init__: __init__, -}); -/* class definition Exception */ -var __init__ = function(self, message) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ + +var repr = function(obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - pythonium_set_attribute(self, "message", message); + if (pythonium_is_true((pythonium_get_attribute(obj, "__is__")(object)))) { + return pythonium_call(str, ""); + return __NONE; + } + var call_arguments2 = [pythonium_get_attribute(obj, "__repr__")]; + return pythonium_call.apply(undefined, call_arguments2); + return __NONE; }; -var Exception = pythonium_create_class("Exception", [__object], { - __init__: __init__, -}); -/* class definition TypeError */ -/* pass */ -var TypeError = pythonium_create_class("TypeError", [Exception], { -}); -/* class definition AttributeError */ -/* pass */ -var AttributeError = pythonium_create_class("AttributeError", [Exception], { -}); -/* class definition int */ -var __init__ = function(self, jsobject) { - /* BEGIN unpacking arguments */ + +var print = function() { + /* BEGIN arguments unpacking */ var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ + __args = __args.splice(0); + var args = pythonium_call(tuple); + args.jsobject = __args; + /* END arguments unpacking */ + var out,name,r; /* BEGIN function */ - pythonium_set_attribute(self, "jsobject", jsobject); + out = []; + try { + var __next3__ = pythonium_get_attribute(iter(args), "__next__"); + while(true) { + var arg = __next3__(); + if (pythonium_is_true(arg.__class__ !== undefined)) { + var call_arguments4 = [repr, arg]; + var call_arguments5 = [jstype, pythonium_call.apply(undefined, call_arguments4)]; + r = pythonium_call.apply(undefined, call_arguments5); + out.push(r); + } + else { + if (pythonium_is_true(arg.__metaclass__ !== undefined)) { + name = arg.__name__; + out.push(""); + } + else { + out.push(arg); + } + } + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + console.log.apply(console, out); }; -var __repr__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ + +/* class definition map */ +var __map___init__ = function(self, func, iterable) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - return self; + pythonium_set_attribute(self, "func", func); + var call_arguments6 = [iter, iterable]; + pythonium_set_attribute(self, "iterable", pythonium_call.apply(undefined, call_arguments6)); }; -var __add__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__map___init__.is_method = true; + +var __map___iter__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - a = pythonium_get_attribute(self, "jsobject"); - b = pythonium_get_attribute(other, "jsobject"); - return pythonium_call(int, a + b); + return self; + return __NONE; +}; +__map___iter__.is_method = true; + +var __map___next__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var n,r; + /* BEGIN function */ + var call_arguments7 = [next, pythonium_get_attribute(self, "iterable")]; + n = pythonium_call.apply(undefined, call_arguments7); + var call_arguments8 = [pythonium_get_attribute(self, "func"), n]; + r = pythonium_call.apply(undefined, call_arguments8); + return r; + return __NONE; +}; +__map___next__.is_method = true; + +var __map___repr__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + return pythonium_call(str, ""); + return __NONE; +}; +__map___repr__.is_method = true; + +var map = pythonium_create_class("map", [object], { + __init__: __map___init__, + __iter__: __map___iter__, + __next__: __map___next__, + __repr__: __map___repr__, +}); +var jstype = function(obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments9 = [pythonium_get_attribute(obj, "__jstype__")]; + return pythonium_call.apply(undefined, call_arguments9); + return __NONE; }; -var __sub__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; + +var hash = function(obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - a = pythonium_get_attribute(self, "jsobject"); - b = pythonium_get_attribute(other, "jsobject"); - return pythonium_call(int, a - b); + var call_arguments10 = [pythonium_get_attribute(obj, "__hash__")]; + return pythonium_call.apply(undefined, call_arguments10); + return __NONE; }; -var __lt__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; + +var iter = function(obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - a = pythonium_get_attribute(self, "jsobject"); - b = pythonium_get_attribute(other, "jsobject"); - if (pythonium_is_true(a < b)) { - return __TRUE; + var call_arguments11 = [pythonium_get_attribute(obj, "__iter__")]; + return pythonium_call.apply(undefined, call_arguments11); + return __NONE; +}; + +var next = function(obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var r; + /* BEGIN function */ + if (pythonium_is_true(obj.next !== undefined)) { + r = obj.next(); + if (pythonium_is_true(r.done)) { + throw StopIteration; + } + else { + return r.value; + return __NONE; + } } + var call_arguments12 = [pythonium_get_attribute(obj, "__next__")]; + return pythonium_call.apply(undefined, call_arguments12); + return __NONE; +}; + +var len = function(obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments13 = [pythonium_get_attribute(obj, "__len__")]; + return pythonium_call.apply(undefined, call_arguments13); + return __NONE; +}; + +var abs = function(obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments14 = [pythonium_get_attribute(obj, "__abs__")]; + return pythonium_call.apply(undefined, call_arguments14); + return __NONE; +}; + +var all = function(iterable) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + try { + var __next15__ = pythonium_get_attribute(iter(iterable), "__next__"); + while(true) { + var element = __next15__(); + if (pythonium_is_true(pythonium_call(pythonium_get_attribute(element, "__not__")))) { + return __FALSE; + return __NONE; + } + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return __TRUE; + return __NONE; +}; + +var any = function(iterable) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + try { + var __next16__ = pythonium_get_attribute(iter(iterable), "__next__"); + while(true) { + var element = __next16__(); + if (pythonium_is_true(element)) { + return __TRUE; + return __NONE; + } + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} return __FALSE; + return __NONE; }; -var __lte__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; + +var callable = function(obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - a = pythonium_get_attribute(self, "jsobject"); - b = pythonium_get_attribute(other, "jsobject"); - if (pythonium_is_true(a <= b)) { + if (pythonium_is_true({}.toString.call(obj) == '[object Function]')) { + return __TRUE; + return __NONE; + } + if (pythonium_is_true(obj.__metaclass__ !== undefined)) { return __TRUE; + return __NONE; + } + if (pythonium_is_true(lookup(obj, '__call__'))) { + return __TRUE; + return __NONE; } return __FALSE; + return __NONE; +}; + +var classmethod = function(func) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + pythonium_set_attribute(func, "classmethod", __TRUE); + return func; + return __NONE; +}; + +var staticmethod = function(func) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + pythonium_set_attribute(func, "staticmethod", __TRUE); + return func; + return __NONE; +}; + +/* class definition enumerate */ +var __enumerate___init__ = function(self, iterator) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments17 = [iter, iterator]; + pythonium_set_attribute(self, "iterator", pythonium_call.apply(undefined, call_arguments17)); + pythonium_set_attribute(self, "index", pythonium_call(int, 0)); }; -var __mul__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b,c; +__enumerate___init__.is_method = true; + +var __enumerate___repr__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - a = pythonium_get_attribute(self, "jsobject"); - b = pythonium_get_attribute(other, "jsobject"); - c = a * b; - return pythonium_call(int, c); + return pythonium_call(str, ""); + return __NONE; }; -var __or__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b,c; +__enumerate___repr__.is_method = true; + +var __enumerate___iter__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - a = pythonium_get_attribute(self, "jsobject"); - b = pythonium_get_attribute(other, "jsobject"); - c = a || b; - return pythonium_call(int, c); + return self; + return __NONE; }; -var __eq__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__enumerate___iter__.is_method = true; + +var __enumerate___next__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var index; /* BEGIN function */ - a = pythonium_get_attribute(self, "jsobject"); - b = pythonium_get_attribute(other, "jsobject"); - if (pythonium_is_true(a == b)) { - return __TRUE; + index = pythonium_get_attribute(self, "index"); + pythonium_set_attribute(self, "index", (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__add__"), pythonium_call(int, 1)))); + var call_arguments18 = [next, pythonium_get_attribute(self, "iterator")]; + var __a_tuple19 = pythonium_call(tuple); + __a_tuple19.jsobject = [index, pythonium_call.apply(undefined, call_arguments18)]; + return __a_tuple19; + return __NONE; +}; +__enumerate___next__.is_method = true; + +var enumerate = pythonium_create_class("enumerate", [object], { + __init__: __enumerate___init__, + __repr__: __enumerate___repr__, + __iter__: __enumerate___iter__, + __next__: __enumerate___next__, +}); +var getattr = function(obj, attr, d) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var r; + /* BEGIN function */ + var call_arguments20 = [lookup, obj, attr]; + r = pythonium_call.apply(undefined, call_arguments20); + if (pythonium_is_true(r === undefined)) { + if (pythonium_is_true(d === undefined)) { + throw AttributeError; + } + else { + return d; + return __NONE; + } + } + else { + return r; + return __NONE; } - return __FALSE; }; -var __neg__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ + +/* class definition ListIterator */ +var __ListIterator___init__ = function(self, obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + pythonium_set_attribute(self, "list", obj); + pythonium_set_attribute(self, "index", pythonium_call(int, 0)); + var call_arguments0 = [len, obj]; + pythonium_set_attribute(self, "length", pythonium_call.apply(undefined, call_arguments0)); +}; +__ListIterator___init__.is_method = true; + +var __ListIterator___iter__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + return self; + return __NONE; +}; +__ListIterator___iter__.is_method = true; + +var __ListIterator___next__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var index; + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__eq__")(pythonium_get_attribute(self, "length"))))) { + throw StopIteration; + } + index = pythonium_get_attribute(self, "index"); + pythonium_set_attribute(self, "index", (pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "index"), "__add__"), pythonium_call(int, 1)))); + return pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "list"), '__getitem__'), index); + return __NONE; +}; +__ListIterator___next__.is_method = true; + +var ListIterator = pythonium_create_class("ListIterator", [object], { + __init__: __ListIterator___init__, + __iter__: __ListIterator___iter__, + __next__: __ListIterator___next__, +}); +/* class definition list */ +var __list___init__ = function(self, iterable) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", []); + if (pythonium_is_true(iterable !== undefined)) { + try { + var __next1__ = pythonium_get_attribute(iter(iterable), "__next__"); + while(true) { + var item = __next1__(); + var call_arguments2 = [pythonium_get_attribute(self, "append"), item]; + pythonium_call.apply(undefined, call_arguments2); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + } +}; +__list___init__.is_method = true; + +var __list___hash__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments3 = [TypeError, pythonium_call(str, "unhashable type: 'list'")]; + throw pythonium_call.apply(undefined, call_arguments3); +}; +__list___hash__.is_method = true; + +var __list___repr__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var iterable; + /* BEGIN function */ + var call_arguments4 = [map, nest_str_with_quotes, self]; + iterable = pythonium_call.apply(undefined, call_arguments4); + var call_arguments5 = [pythonium_get_attribute(pythonium_call(str, ", "), "join"), iterable]; + return (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "["), "__add__"), pythonium_call.apply(undefined, call_arguments5))), "__add__"), pythonium_call(str, "]"))); + return __NONE; +}; +__list___repr__.is_method = true; + +var __list___jstype__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var out,item; + /* BEGIN function */ + out = []; + try { + var __next6__ = pythonium_get_attribute(iter(self), "__next__"); + while(true) { + var item = __next6__(); + var call_arguments7 = [jstype, item]; + item = pythonium_call.apply(undefined, call_arguments7); + out.push(item); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return out; + return __NONE; +}; +__list___jstype__.is_method = true; + +var __list_append = function(self, item) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ var jsobject; /* BEGIN function */ jsobject = pythonium_get_attribute(self, "jsobject"); - return pythonium_call(int, -jsobject); + jsobject.push(item); }; -var __div__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__list_append.is_method = true; + +var __list_insert = function(self, index, item) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - a = pythonium_get_attribute(self, "jsobject"); - b = pythonium_get_attribute(other, "jsobject"); - return pythonium_call(int, a / b); -}; -var int = pythonium_create_class("int", [__object], { - __init__: __init__, - __repr__: __repr__, - __add__: __add__, - __sub__: __sub__, - __lt__: __lt__, - __lte__: __lte__, - __mul__: __mul__, - __or__: __or__, - __eq__: __eq__, - __neg__: __neg__, - __div__: __div__, -}); -/* class definition dict */ -var __init__ = function(self, jsobject) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ + var call_arguments8 = [pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "splice"), index, pythonium_call(int, 0), item]; + pythonium_call.apply(undefined, call_arguments8); +}; +__list_insert.is_method = true; + +var __list___setitem__ = function(self, index, value) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject; /* BEGIN function */ - pythonium_set_attribute(self, "jsobject", jsobject); + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(index, "jsobject"); + jsobject[index] = value; }; -var __repr__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var key_repr,value_repr,out; +__list___setitem__.is_method = true; + +var __list___getitem__ = function(self, s) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,index; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + var call_arguments9 = [jstype, s]; + index = pythonium_call.apply(undefined, call_arguments9); + return jsobject[index]; + return __NONE; +}; +__list___getitem__.is_method = true; + +var __list___len__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,length; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + length = jsobject.length; + var call_arguments10 = [int, length]; + return pythonium_call.apply(undefined, call_arguments10); + return __NONE; +}; +__list___len__.is_method = true; + +var __list___iter__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments11 = [ListIterator, self]; + return pythonium_call.apply(undefined, call_arguments11); + return __NONE; +}; +__list___iter__.is_method = true; + +var __list___contains__ = function(self, obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - out = pythonium_call(list); try { - var __next__ = pythonium_get_attribute(iter(pythonium_call(pythonium_get_attribute(self, "keys"))), "__next__"); + var __next12__ = pythonium_get_attribute(iter(self), "__next__"); while(true) { - var key = pythonium_call(__next__); - key_repr = pythonium_call(repr, key); - value_repr = pythonium_call(repr, pythonium_call(pythonium_get_attribute(self, "get"), key)); - pythonium_call(pythonium_get_attribute(out, "append"), (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(key_repr, "__add__"), pythonium_call(str, ": "))), "__add__"), value_repr))); + var item = __next12__(); + if (pythonium_is_true((pythonium_get_attribute(obj, "__eq__")(item)))) { + return __TRUE; + return __NONE; + } + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return __FALSE; + return __NONE; +}; +__list___contains__.is_method = true; + +var __list_pop = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments13 = [pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "pop")]; + return pythonium_call.apply(undefined, call_arguments13); + return __NONE; +}; +__list_pop.is_method = true; + +var __list_index = function(self, obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var index; + /* BEGIN function */ + index = pythonium_call(int, 0); + try { + var __next14__ = pythonium_get_attribute(iter(self), "__next__"); + while(true) { + var item = __next14__(); + if (pythonium_is_true((pythonium_get_attribute(item, "__eq__")(obj)))) { + return index; + return __NONE; + } + index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); } } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} - return (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "{"), "__add__"), pythonium_call(pythonium_get_attribute(pythonium_call(str, ", "), "join"), out))), "__add__"), pythonium_call(str, "}"))); + throw ValueError; }; -var get = function(self, key, d) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - if (__args[__args.length - 2] === __ARGUMENTS_PADDING__) { - var __kwargs = __args[__args.length - 1]; - var varkwargs_start = __args.length - 2; - } else { - var __kwargs = {}; - var varkwargs_start = undefined; - } - if (varkwargs_start !== undefined && 2 > varkwargs_start) { - d = __kwargs.d || __NONE; - } else { - d = d || __kwargs.d || __NONE; - } - /* END unpacking arguments */ - var attr,jsobject; +__list_index.is_method = true; + +var __list_remove = function(self, obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,index; /* BEGIN function */ + var call_arguments15 = [pythonium_get_attribute(self, "index"), obj]; + index = pythonium_call.apply(undefined, call_arguments15); jsobject = pythonium_get_attribute(self, "jsobject"); - key = pythonium_get_attribute(key, "jsobject"); - attr = jsobject[key]; - if (pythonium_is_true((pythonium_get_attribute(__NONE, "__isnot__")(attr)))) { - return attr; + jsobject.splice(jstype(index), 1); +}; +__list_remove.is_method = true; + +var __list___delitem__ = function(self, index) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments16 = [jstype, index]; + var call_arguments17 = [pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "splice"), pythonium_call.apply(undefined, call_arguments16), pythonium_call(int, 1)]; + pythonium_call.apply(undefined, call_arguments17); +}; +__list___delitem__.is_method = true; + +var list = pythonium_create_class("list", [object], { + __init__: __list___init__, + __hash__: __list___hash__, + __repr__: __list___repr__, + __jstype__: __list___jstype__, + append: __list_append, + insert: __list_insert, + __setitem__: __list___setitem__, + __getitem__: __list___getitem__, + __len__: __list___len__, + __iter__: __list___iter__, + __contains__: __list___contains__, + pop: __list_pop, + index: __list_index, + remove: __list_remove, + __delitem__: __list___delitem__, +}); +/* class definition _None */ +var ___None___and__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + return __TRUE; + return __NONE; } - else { - return d; + return __FALSE; + return __NONE; +}; +___None___and__.is_method = true; + +var ___None___or__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + if (pythonium_is_true((pythonium_get_attribute(other, "__is__")(__TRUE)))) { + return __TRUE; + return __NONE; } + return __FALSE; + return __NONE; }; -var __setitem__ = function(self, key, value) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +___None___or__.is_method = true; + +var ___None___is__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - pythonium_call(pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "__setitem__"), key, value); + if (pythonium_is_true(other === self)) { + return __TRUE; + return __NONE; + } + return __FALSE; + return __NONE; }; -var keys = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +___None___is__.is_method = true; + +var ___None___neg__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - return pythonium_call(map, str, pythonium_call(list, pythonium_call(pythonium_get_attribute(Object, "keys"), pythonium_get_attribute(self, "jsobject")))); + return __TRUE; + return __NONE; }; -var items = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var out; +___None___neg__.is_method = true; + +var ___None___not__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ - out = pythonium_call(list); - try { - var __next__ = pythonium_get_attribute(iter(pythonium_call(pythonium_get_attribute(self, "keys"))), "__next__"); - while(true) { - var key = pythonium_call(__next__); - pythonium_call(pythonium_get_attribute(out, "append"), pythonium_call(list, [key, pythonium_call(pythonium_get_attribute(self, "get"), key)])); - } - } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} - return out; + return __TRUE; + return __NONE; +}; +___None___not__.is_method = true; + +var _None = pythonium_create_class("_None", [object], { + __and__: ___None___and__, + __or__: ___None___or__, + __is__: ___None___is__, + __neg__: ___None___neg__, + __not__: ___None___not__, +}); +var call_arguments0 = [_None]; +__NONE = pythonium_call.apply(undefined, call_arguments0); +/* class definition slice */ +var __slice___init__ = function(self, start, step, end) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + pythonium_set_attribute(self, "start", start); + pythonium_set_attribute(self, "step", step); + pythonium_set_attribute(self, "end", end); }; -var dict = pythonium_create_class("dict", [__object], { - __init__: __init__, - __repr__: __repr__, - get: get, - __setitem__: __setitem__, - keys: keys, - items: items, +__slice___init__.is_method = true; + +var slice = pythonium_create_class("slice", [object], { + __init__: __slice___init__, }); /* class definition str */ -var __init__ = function(self, jsobject) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +var __str___init__ = function(self, jsobject) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ pythonium_set_attribute(self, "jsobject", jsobject); }; -var __repr__ = function(self) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__str___init__.is_method = true; + +var __str___repr__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ /* BEGIN function */ return self; + return __NONE; }; -var join = function(self, objects) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var L,index,out,obj; - /* BEGIN function */ - L = pythonium_call(len, objects); - if (pythonium_is_true(pythonium_call(pythonium_get_attribute(L, "__neg__")))) { - return pythonium_call(str, ""); - } - out = pythonium_call(pythonium_get_attribute(objects, '__getitem__'), pythonium_call(int, 0)); - index = pythonium_call(int, 1); - while(pythonium_is_true((pythonium_get_attribute(index, "__lt__")(L)))) { - obj = pythonium_call(pythonium_get_attribute(objects, '__getitem__'), index); - out = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(out, "__add__"), self)), "__add__"), obj)); - index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); +__str___repr__.is_method = true; + +var __str___jstype__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + return pythonium_get_attribute(self, "jsobject"); + return __NONE; +}; +__str___jstype__.is_method = true; + +var __str___hash__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + return (pythonium_call(pythonium_get_attribute(pythonium_call(str, '"'), "__add__"), self)); + return __NONE; +}; +__str___hash__.is_method = true; + +var __str___contains__ = function(self, s) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,i; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + var call_arguments0 = [jstype, s]; + s = pythonium_call.apply(undefined, call_arguments0); + i = jsobject.indexOf(s); + var call_arguments1 = [int, i]; + if (pythonium_is_true((pythonium_get_attribute(pythonium_call.apply(undefined, call_arguments1), "__neq__")(pythonium_call(pythonium_get_attribute(pythonium_call(int, 1), "__neg__")))))) { + return __TRUE; + return __NONE; + } + return __FALSE; + return __NONE; +}; +__str___contains__.is_method = true; + +var __str___iter__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments2 = [ListIterator, self]; + return pythonium_call.apply(undefined, call_arguments2); + return __NONE; +}; +__str___iter__.is_method = true; + +var __str_join = function(self, iterable) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var out; + /* BEGIN function */ + var call_arguments3 = [iter, iterable]; + iterable = pythonium_call.apply(undefined, call_arguments3); + try { + var call_arguments4 = [next, iterable]; + out = pythonium_call.apply(undefined, call_arguments4); + } catch (__exception__) { + if (pythonium_is_exception(__exception__, StopIteration)) { + return pythonium_call(str, ""); + return __NONE; + } } + try { + var __next5__ = pythonium_get_attribute(iter(iterable), "__next__"); + while(true) { + var item = __next5__(); + out = (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(out, "__add__"), self)), "__add__"), item)); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} return out; + return __NONE; }; -var __add__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__str_join.is_method = true; + +var __str___add__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ a = pythonium_get_attribute(self, "jsobject"); b = pythonium_get_attribute(other, "jsobject"); - return pythonium_call(str, a + b); + var call_arguments6 = [str, a + b]; + return pythonium_call.apply(undefined, call_arguments6); + return __NONE; +}; +__str___add__.is_method = true; + +var __str___len__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject; + /* BEGIN function */ + jsobject = self.jsobject; + var call_arguments7 = [int, jsobject.length]; + return pythonium_call.apply(undefined, call_arguments7); + return __NONE; }; -var __lte__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__str___len__.is_method = true; + +var __str___lte__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ a = pythonium_get_attribute(self, "jsobject"); b = pythonium_get_attribute(other, "jsobject"); if (pythonium_is_true(a <= b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __gte__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__str___lte__.is_method = true; + +var __str___gte__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ a = pythonium_get_attribute(self, "jsobject"); b = pythonium_get_attribute(other, "jsobject"); if (pythonium_is_true(a >= b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __gt__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__str___gte__.is_method = true; + +var __str___gt__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ a = pythonium_get_attribute(self, "jsobject"); b = pythonium_get_attribute(other, "jsobject"); if (pythonium_is_true(a > b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __eq__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - var a,b; +__str___gt__.is_method = true; + +var __str___eq__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var b,a; /* BEGIN function */ a = pythonium_get_attribute(self, "jsobject"); b = pythonium_get_attribute(other, "jsobject"); if (pythonium_is_true(a == b)) { return __TRUE; + return __NONE; } return __FALSE; + return __NONE; }; -var __getitem__ = function(self, index) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ +__str___eq__.is_method = true; + +var __str___getitem__ = function(self, index) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ var jsobject,c; /* BEGIN function */ jsobject = pythonium_get_attribute(self, "jsobject"); index = pythonium_get_attribute(index, "jsobject"); c = jsobject[index]; - return pythonium_call(str, c); + var call_arguments8 = [str, c]; + return pythonium_call.apply(undefined, call_arguments8); + return __NONE; +}; +__str___getitem__.is_method = true; + +var __str___neq__ = function(self, other) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments9 = [pythonium_get_attribute(self, "__eq__"), other]; + return pythonium_call(pythonium_get_attribute(pythonium_call.apply(undefined, call_arguments9), "__not__")); + return __NONE; +}; +__str___neq__.is_method = true; + +var str = pythonium_create_class("str", [object], { + __init__: __str___init__, + __repr__: __str___repr__, + __jstype__: __str___jstype__, + __hash__: __str___hash__, + __contains__: __str___contains__, + __iter__: __str___iter__, + join: __str_join, + __add__: __str___add__, + __len__: __str___len__, + __lte__: __str___lte__, + __gte__: __str___gte__, + __gt__: __str___gt__, + __eq__: __str___eq__, + __getitem__: __str___getitem__, + __neq__: __str___neq__, +}); +/* class definition tuple */ +var __tuple___init__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + pythonium_set_attribute(self, "jsobject", []); +}; +__tuple___init__.is_method = true; + +var __tuple___hash__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments0 = [TypeError, pythonium_call(str, "unhashable type: 'list'")]; + throw pythonium_call.apply(undefined, call_arguments0); +}; +__tuple___hash__.is_method = true; + +var __tuple___repr__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var iterable; + /* BEGIN function */ + var call_arguments1 = [map, nest_str_with_quotes, self]; + iterable = pythonium_call.apply(undefined, call_arguments1); + var call_arguments2 = [pythonium_get_attribute(pythonium_call(str, ", "), "join"), iterable]; + return (pythonium_call(pythonium_get_attribute((pythonium_call(pythonium_get_attribute(pythonium_call(str, "("), "__add__"), pythonium_call.apply(undefined, call_arguments2))), "__add__"), pythonium_call(str, ")"))); + return __NONE; +}; +__tuple___repr__.is_method = true; + +var __tuple___jstype__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var out,item; + /* BEGIN function */ + out = []; + try { + var __next3__ = pythonium_get_attribute(iter(self), "__next__"); + while(true) { + var item = __next3__(); + var call_arguments4 = [jstype, item]; + item = pythonium_call.apply(undefined, call_arguments4); + out.push(item); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return out; + return __NONE; +}; +__tuple___jstype__.is_method = true; + +var __tuple_insert = function(self, index, item) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments5 = [pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "splice"), index, pythonium_call(int, 0), item]; + pythonium_call.apply(undefined, call_arguments5); +}; +__tuple_insert.is_method = true; + +var __tuple___setitem__ = function(self, index, value) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + index = pythonium_get_attribute(index, "jsobject"); + jsobject[index] = value; }; -var __neq__ = function(self, other) { - /* BEGIN unpacking arguments */ - var __args = Array.prototype.slice.call(arguments); - /* END unpacking arguments */ - /* BEGIN function */ - return pythonium_call(pythonium_get_attribute(pythonium_call(pythonium_get_attribute(self, "__eq__"), other), "__neg__")); -}; -var str = pythonium_create_class("str", [__object], { - __init__: __init__, - __repr__: __repr__, - join: join, - __add__: __add__, - __lte__: __lte__, - __gte__: __gte__, - __gt__: __gt__, - __eq__: __eq__, - __getitem__: __getitem__, - __neq__: __neq__, +__tuple___setitem__.is_method = true; + +var __tuple___getitem__ = function(self, s) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,index; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + var call_arguments6 = [jstype, s]; + index = pythonium_call.apply(undefined, call_arguments6); + return jsobject[index]; + return __NONE; +}; +__tuple___getitem__.is_method = true; + +var __tuple___len__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,length; + /* BEGIN function */ + jsobject = pythonium_get_attribute(self, "jsobject"); + length = jsobject.length; + var call_arguments7 = [int, length]; + return pythonium_call.apply(undefined, call_arguments7); + return __NONE; +}; +__tuple___len__.is_method = true; + +var __tuple___iter__ = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments8 = [ListIterator, self]; + return pythonium_call.apply(undefined, call_arguments8); + return __NONE; +}; +__tuple___iter__.is_method = true; + +var __tuple___contains__ = function(self, obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + try { + var __next9__ = pythonium_get_attribute(iter(self), "__next__"); + while(true) { + var item = __next9__(); + if (pythonium_is_true((pythonium_get_attribute(obj, "__eq__")(item)))) { + return __TRUE; + return __NONE; + } + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + return __FALSE; + return __NONE; +}; +__tuple___contains__.is_method = true; + +var __tuple_pop = function(self) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments10 = [pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "pop")]; + return pythonium_call.apply(undefined, call_arguments10); + return __NONE; +}; +__tuple_pop.is_method = true; + +var __tuple_index = function(self, obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var index; + /* BEGIN function */ + index = pythonium_call(int, 0); + try { + var __next11__ = pythonium_get_attribute(iter(self), "__next__"); + while(true) { + var item = __next11__(); + if (pythonium_is_true((pythonium_get_attribute(item, "__eq__")(obj)))) { + return index; + return __NONE; + } + index = pythonium_call(pythonium_get_attribute(index, "__add__"), pythonium_call(int, 1)); + } + } catch (x) { if (!pythonium_is_exception(x, StopIteration)) { throw x; }} + throw ValueError; +}; +__tuple_index.is_method = true; + +var __tuple_remove = function(self, obj) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + var jsobject,index; + /* BEGIN function */ + var call_arguments12 = [pythonium_get_attribute(self, "index"), obj]; + index = pythonium_call.apply(undefined, call_arguments12); + jsobject = pythonium_get_attribute(self, "jsobject"); + jsobject.splice(jstype(index), 1); +}; +__tuple_remove.is_method = true; + +var __tuple___delitem__ = function(self, index) { + /* BEGIN arguments unpacking */ + /* END arguments unpacking */ + /* BEGIN function */ + var call_arguments13 = [jstype, index]; + var call_arguments14 = [pythonium_get_attribute(pythonium_get_attribute(self, "jsobject"), "splice"), pythonium_call.apply(undefined, call_arguments13), pythonium_call(int, 1)]; + pythonium_call.apply(undefined, call_arguments14); +}; +__tuple___delitem__.is_method = true; + +var tuple = pythonium_create_class("tuple", [object], { + __init__: __tuple___init__, + __hash__: __tuple___hash__, + __repr__: __tuple___repr__, + __jstype__: __tuple___jstype__, + insert: __tuple_insert, + __setitem__: __tuple___setitem__, + __getitem__: __tuple___getitem__, + __len__: __tuple___len__, + __iter__: __tuple___iter__, + __contains__: __tuple___contains__, + pop: __tuple_pop, + index: __tuple_index, + remove: __tuple_remove, + __delitem__: __tuple___delitem__, }); diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 4a01326..888cfaf 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -146,7 +146,8 @@ def visit_Yield(self, node): return 'yield {}'.format(self.visit(node.value)) # YieldFrom(expr value) - visit_YieldFrom = NotImplemented + def visit_YieldFrom(self, node): + pass # In def visit_In(self, node): From 9fc79b7f06c36bb1339322809f3adcaf9a6edf50 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 15:14:10 +0100 Subject: [PATCH 143/160] typofix --- pythonium/compliant/compliant.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pythonium/compliant/compliant.py b/pythonium/compliant/compliant.py index 888cfaf..267f43f 100644 --- a/pythonium/compliant/compliant.py +++ b/pythonium/compliant/compliant.py @@ -668,7 +668,7 @@ def visit_Assign(self, node): if isinstance(target, Tuple): targets = map(self.visit, target.elts) if export: - self.__all__.extends(targets) + self.__all__.extend(targets) self.writer.write('var getitem = pythonium_get_attribute(__assignement, "__getitem__");') for index, target in enumerate(targets): self.writer.write('{} = getitem(pythonium_call(int, {}));'.format(target, index)) @@ -688,7 +688,7 @@ def visit_Assign(self, node): else: name = target if export: - self.__all__.extends(name) + self.__all__.extend(name) self.writer.write('{} = __assignement;'.format(name)) if self._def_stack and isinstance(self._def_stack[-1], ClassDefNode): return target, name From 6e3180d54c1394e27e6f64ad5d58f8c42e9337c0 Mon Sep 17 00:00:00 2001 From: Amirouche Boubekki Date: Mon, 23 Dec 2013 15:44:07 +0100 Subject: [PATCH 144/160] compliant: wip trampoline for the browser --- app.py.js | 0 examples/compliant/yield/Makefile | 2 + examples/compliant/yield/README.rst | 5 + examples/compliant/yield/app.py | 44 + examples/compliant/yield/app.py.js | 11 + examples/compliant/yield/index.html | 17 + examples/compliant/yield/jquery.js | 9789 +++++++++++++++++++++++++ examples/compliant/yield/pythonium.js | 2269 ++++++ pythonium/compliant/builtins/list.py | 7 + tests/python/trampoline.py | 44 + 10 files changed, 12188 insertions(+) create mode 100644 app.py.js create mode 100644 examples/compliant/yield/Makefile create mode 100644 examples/compliant/yield/README.rst create mode 100644 examples/compliant/yield/app.py create mode 100644 examples/compliant/yield/app.py.js create mode 100644 examples/compliant/yield/index.html create mode 100644 examples/compliant/yield/jquery.js create mode 100644 examples/compliant/yield/pythonium.js create mode 100644 tests/python/trampoline.py diff --git a/app.py.js b/app.py.js new file mode 100644 index 0000000..e69de29 diff --git a/examples/compliant/yield/Makefile b/examples/compliant/yield/Makefile new file mode 100644 index 0000000..befc1ce --- /dev/null +++ b/examples/compliant/yield/Makefile @@ -0,0 +1,2 @@ +all: + python -m http.server diff --git a/examples/compliant/yield/README.rst b/examples/compliant/yield/README.rst new file mode 100644 index 0000000..4f85dc3 --- /dev/null +++ b/examples/compliant/yield/README.rst @@ -0,0 +1,5 @@ +======= + yield +======= + +Example use of yield to avoid callbacks. diff --git a/examples/compliant/yield/app.py b/examples/compliant/yield/app.py new file mode 100644 index 0000000..284b8d0 --- /dev/null +++ b/examples/compliant/yield/app.py @@ -0,0 +1,44 @@ +tosend = list() +todos = list() + + +def asyncronous_fetch_one(): + yield 10 + + +def asyncronous_fetch_two(): + yield 32 + + +def main(): + a = yield asyncronous_fetch_one() + b = yield asyncronous_fetch_two() + print(a+b) + + +# bootstrap +tosend.append((main(), None)) + +print('starting ;)') +while tosend or todos: + print(tosend, todos) + while tosend: + print('in tosend') + to, value = tosend.pop() + try: + n = to.send(value) + except StopIteration: + print('fuuuu') + pass + else: + todos.append((to, n)) + while todos: + print('in todos') + to, generator = todos.pop() + try: + tosend.append((to, next(generator))) + except StopIteration: + pass + else: + todos.append((to, generator)) + diff --git a/examples/compliant/yield/app.py.js b/examples/compliant/yield/app.py.js new file mode 100644 index 0000000..745195b --- /dev/null +++ b/examples/compliant/yield/app.py.js @@ -0,0 +1,11 @@ +frak = function *() { + yield 42; +} + +var fuuu = function *() { + console.log('fuuuu'); + a = yield frak(); +} +var f = fuuu() +f.next() +f.send(undefined) diff --git a/examples/compliant/yield/index.html b/examples/compliant/yield/index.html new file mode 100644 index 0000000..a35a7e6 --- /dev/null +++ b/examples/compliant/yield/index.html @@ -0,0 +1,17 @@ + + + + todo list by Pythonium + + + + +

    A todo list

    + +
      +
    + + + + + diff --git a/examples/compliant/yield/jquery.js b/examples/compliant/yield/jquery.js new file mode 100644 index 0000000..c5c6482 --- /dev/null +++ b/examples/compliant/yield/jquery.js @@ -0,0 +1,9789 @@ +/*! + * jQuery JavaScript Library v1.10.2 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03T13:48Z + */ +(function( window, undefined ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; +var + // The deferred used on DOM ready + readyList, + + // A central reference to the root jQuery(document) + rootjQuery, + + // Support: IE<10 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "1.10.2", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( jQuery.support.ownLast ) { + for ( key in obj ) { + return core_hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +/*! + * Sizzle CSS Selector Engine v1.10.2 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-07-03 + */ +(function( window, undefined ) { + +var i, + support, + cachedruns, + Expr, + getText, + isXML, + compile, + outermostContext, + sortInput, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + hasDuplicate = false, + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rsibling = new RegExp( whitespace + "*[+~]" ), + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Detect xml + * @param {Element|Object} elem An element or a document + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent.attachEvent && parent !== parent.top ) { + parent.attachEvent( "onbeforeunload", function() { + setDocument(); + }); + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = assert(function( div ) { + div.innerHTML = "
    "; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Support: Opera 10-12/IE8 + // ^= $= *= and empty values + // Should not select anything + // Support: Windows 8 Native Apps + // The type attribute is restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "t", "" ); + + if ( div.querySelectorAll("[t^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val === undefined ? + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null : + val; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] && match[4] !== undefined ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + } + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) + ); + return results; +} + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + elem[ name ] === true ? name.toLowerCase() : null; + } + }); +} + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function( support ) { + + var all, a, input, select, fragment, opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
    a"; + + // Finish early in limited (non-browser) environments + all = div.getElementsByTagName("*") || []; + a = div.getElementsByTagName("a")[ 0 ]; + if ( !a || !a.style || !all.length ) { + return support; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + support.getSetAttribute = div.className !== "t"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName("tbody").length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName("link").length; + + // Get the style information from getAttribute + // (IE uses .cssText instead) + support.style = /top/.test( a.getAttribute("style") ); + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + support.hrefNormalized = a.getAttribute("href") === "/a"; + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + support.opacity = /^0.5/.test( a.style.opacity ); + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + support.cssFloat = !!a.style.cssFloat; + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + support.checkOn = !!input.value; + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + support.optSelected = opt.selected; + + // Tests for enctype support on a form (#6743) + support.enctype = !!document.createElement("form").enctype; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>"; + + // Will be defined later + support.inlineBlockNeedsLayout = false; + support.shrinkWrapBlocks = false; + support.pixelPosition = false; + support.deleteExpando = true; + support.noCloneEvent = true; + support.reliableMarginRight = true; + support.boxSizingReliable = true; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + for ( i in { submit: true, change: true, focusin: true }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Support: IE<9 + // Iteration over object's inherited properties before its own. + for ( i in jQuery( support ) ) { + break; + } + support.ownLast = i !== "0"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
    t
    "; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior. + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
    "; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; +})({}); + +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function internalData( elem, name, data, pvt /* Internal Use Only */ ){ + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "applet": true, + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + data = null, + i = 0, + elem = this[0]; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( name.indexOf("data-") === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // Use proper attribute retrieval(#6932, #12072) + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + elem[ propName ] = false; + // Support: IE<9 + // Also clear defaultChecked/defaultSelected (if appropriate) + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + return tabindex ? + parseInt( tabindex, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ? + function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + jQuery.expr.attrHandle[ name ] = fn; + return ret; + } : + function( elem, name, isXML ) { + return isXML ? + undefined : + elem[ jQuery.camelCase( "default-" + name ) ] ? + name.toLowerCase() : + null; + }; +}); + +// fix oldIE attroperties +if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; +} + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = { + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords = + // Some attributes are constructed with empty-string values when not defined + function( elem, name, isXML ) { + var ret; + return isXML ? + undefined : + (ret = elem.getAttributeNode( name )) && ret.value !== "" ? + ret.value : + null; + }; + jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ret.specified ? + ret.value : + undefined; + }, + set: nodeHook.set + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }; + }); +} + + +// Some attributes require a special call on IE +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !jQuery.support.hrefNormalized ) { + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = ret.push( cur ); + break; + } + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
    ", "
    " ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + col: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
    ", "
    " ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
    " && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); +jQuery.fn.extend({ + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); +var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each(function() { + if ( isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("