author | Edouard Tisserant |
Mon, 28 Oct 2019 19:52:43 +0100 | |
branch | svghmi |
changeset 2808 | dc78ffa5253d |
parent 2455 | 80b225e9a6b6 |
permissions | -rw-r--r-- |
# Copyright 2006 James Tauber and contributors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # pylint: disable=too-many-function-args,undefined-variable,no-absolute-import,assign-to-new-keyword,nonzero-method,next-method-called,next-method-defined # iteration from Bob Ippolito's Iteration in JavaScript from __pyjamas__ import JS # must declare import _before_ importing sys def import_module(path, parent_module, module_name, dynamic=1, async=False): JS(""" var cache_file; if (module_name == "sys" || module_name == 'pyjslib') { /*module_load_request[module_name] = 1;*/ return; } if (path == null) { path = './'; } var override_name = sys.platform + "." + module_name; if (((sys.overrides != null) && (sys.overrides.has_key(override_name)))) { cache_file = sys.overrides.__getitem__(override_name) ; } else { cache_file = module_name ; } cache_file = (path + cache_file + '.cache.js' ) ; //alert("cache " + cache_file + " " + module_name + " " + parent_module); /* already loaded? */ if (module_load_request[module_name]) { if (module_load_request[module_name] >= 3 && parent_module != null) { //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';'; //pyjs_eval(onload_fn); /* set up the parent-module namespace */ } return; } if (typeof (module_load_request[module_name]) == 'undefined') { module_load_request[module_name] = 1; } /* following a load, this first executes the script * "preparation" function MODULENAME_loaded_fn() * and then sets up the loaded module in the namespace * of the parent. */ onload_fn = ''; // module_name + "_loaded_fn();" if (parent_module != null) { //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';'; /*pmod = parent_module + '.' + module_name; onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/ } if (dynamic) { /* this one tacks the script onto the end of the DOM */ pyjs_load_script(cache_file, onload_fn, async); /* this one actually RUNS the script (eval) into the page. my feeling is that this would be better for non-async but i can't get it to work entirely yet. */ /*pyjs_ajax_eval(cache_file, onload_fn, async);*/ } else { if (module_name != "pyjslib" && module_name != "sys") pyjs_eval(onload_fn); } """) JS(""" function import_wait(proceed_fn, parent_mod, dynamic) { var data = ''; var element = $doc.createElement("div"); $doc.body.appendChild(element); function write_dom(txt) { element.innerHTML = txt + '<br />'; } var timeoutperiod = 1; if (dynamic) var timeoutperiod = 1; var wait = function() { var status = ''; for (l in module_load_request) { var m = module_load_request[l]; if (l == "sys" || l == 'pyjslib') continue; status += l + m + " "; } //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod); wait_count += 1; if (status == '') { setTimeout(wait, timeoutperiod); return; } for (l in module_load_request) { var m = module_load_request[l]; if (l == "sys" || l == 'pyjslib') { module_load_request[l] = 4; continue; } if ((parent_mod != null) && (l == parent_mod)) { if (m == 1) { setTimeout(wait, timeoutperiod); return; } if (m == 2) { /* cheat and move app on to next stage */ module_load_request[l] = 3; } } if (m == 1 || m == 2) { setTimeout(wait, timeoutperiod); return; } if (m == 3) { //alert("waited for module " + l + ": loaded"); module_load_request[l] = 4; mod_fn = modules[l]; } } //alert("module wait done"); if (proceed_fn.importDone) proceed_fn.importDone(proceed_fn); else proceed_fn(); } wait(); } """) # pylint: disable=old-style-class class Object: def __init__(self): pass object = Object class Modload: def __init__(self, path, app_modlist, app_imported_fn, dynamic, parent_mod): self.app_modlist = app_modlist self.app_imported_fn = app_imported_fn self.path = path self.idx = 0 self.dynamic = dynamic self.parent_mod = parent_mod def next(self): for i in range(len(self.app_modlist[self.idx])): app = self.app_modlist[self.idx][i] import_module(self.path, self.parent_mod, app, self.dynamic, True) self.idx += 1 if self.idx >= len(self.app_modlist): import_wait(self.app_imported_fn, self.parent_mod, self.dynamic) else: import_wait(getattr(self, "next"), self.parent_mod, self.dynamic) def get_module(module_name): _ev = "__mod = %s;" % module_name JS("pyjs_eval(_ev);") return __mod def preload_app_modules(path, app_modnames, app_imported_fn, dynamic, parent_mod=None): loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod) loader.next() # as comment on line 20 says # import sys should be below import sys # noqa # pylint: disable=wrong-import-order,unused-import,wrong-import-position class BaseException: name = "BaseException" def __init__(self, *args): self.args = args def __str__(self): if len(self.args) is 0: return '' elif len(self.args) is 1: return repr(self.args[0]) return repr(self.args) def toString(self): return str(self) class Exception(BaseException): name = "Exception" class TypeError(BaseException): name = "TypeError" class StandardError(Exception): name = "StandardError" class LookupError(StandardError): name = "LookupError" def toString(self): return self.name + ": " + self.args[0] class KeyError(LookupError): name = "KeyError" class AttributeError(StandardError): name = "AttributeError" def toString(self): return "AttributeError: %s of %s" % (self.args[1], self.args[0]) JS(r""" pyjslib.StopIteration = function () { }; pyjslib.StopIteration.prototype = new Error(); pyjslib.StopIteration.name = 'StopIteration'; pyjslib.StopIteration.message = 'StopIteration'; pyjslib.String_find = function(sub, start, end) { var pos=this.indexOf(sub, start); if (pyjslib.isUndefined(end)) return pos; if (pos + sub.length>end) return -1; return pos; } pyjslib.String_join = function(data) { var text=""; if (pyjslib.isArray(data)) { return data.join(this); } else if (pyjslib.isIteratable(data)) { var iter=data.__iter__(); try { text+=iter.next(); while (true) { var item=iter.next(); text+=this + item; } } catch (e) { if (e != pyjslib.StopIteration) throw e; } } return text; } pyjslib.String_isdigit = function() { return (this.match(/^\d+$/g) != null); } pyjslib.String_replace = function(old, replace, count) { var do_max=false; var start=0; var new_str=""; var pos=0; if (!pyjslib.isString(old)) return this.__replace(old, replace); if (!pyjslib.isUndefined(count)) do_max=true; while (start<this.length) { if (do_max && !count--) break; pos=this.indexOf(old, start); if (pos<0) break; new_str+=this.substring(start, pos) + replace; start=pos+old.length; } if (start<this.length) new_str+=this.substring(start); return new_str; } pyjslib.String_split = function(sep, maxsplit) { var items=new pyjslib.List(); var do_max=false; var subject=this; var start=0; var pos=0; if (pyjslib.isUndefined(sep) || pyjslib.isNull(sep)) { sep=" "; subject=subject.strip(); subject=subject.replace(/\s+/g, sep); } else if (!pyjslib.isUndefined(maxsplit)) do_max=true; if (subject.length == 0) { return items; } while (start<subject.length) { if (do_max && !maxsplit--) break; pos=subject.indexOf(sep, start); if (pos<0) break; items.append(subject.substring(start, pos)); start=pos+sep.length; } if (start<=subject.length) items.append(subject.substring(start)); return items; } pyjslib.String___iter__ = function() { var i = 0; var s = this; return { 'next': function() { if (i >= s.length) { throw pyjslib.StopIteration; } return s.substring(i++, i, 1); }, '__iter__': function() { return this; } }; } pyjslib.String_strip = function(chars) { return this.lstrip(chars).rstrip(chars); } pyjslib.String_lstrip = function(chars) { if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, ""); return this.replace(new RegExp("^[" + chars + "]+"), ""); } pyjslib.String_rstrip = function(chars) { if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, ""); return this.replace(new RegExp("[" + chars + "]+$"), ""); } pyjslib.String_startswith = function(prefix, start) { if (pyjslib.isUndefined(start)) start = 0; if (this.substring(start, prefix.length) == prefix) return true; return false; } pyjslib.abs = Math.abs; """) class Class: def __init__(self, name): self.name = name def __str___(self): return self.name def eq(a, b): JS(""" if (pyjslib.hasattr(a, "__cmp__")) { return a.__cmp__(b) == 0; } else if (pyjslib.hasattr(b, "__cmp__")) { return b.__cmp__(a) == 0; } return a == b; """) def cmp(a, b): if hasattr(a, "__cmp__"): return a.__cmp__(b) elif hasattr(b, "__cmp__"): return -b.__cmp__(a) if a > b: return 1 elif b > a: return -1 else: return 0 def bool(v): # this needs to stay in native code without any dependencies here, # because this is used by if and while, we need to prevent # recursion JS(""" if (!v) return false; switch(typeof v){ case 'boolean': return v; case 'object': if (v.__nonzero__){ return v.__nonzero__(); }else if (v.__len__){ return v.__len__()>0; } return true; } return Boolean(v); """) class List: def __init__(self, data=None): JS(""" this.l = []; this.extend(data); """) def append(self, item): JS(""" this.l[this.l.length] = item;""") def extend(self, data): JS(""" if (pyjslib.isArray(data)) { n = this.l.length; for (var i=0; i < data.length; i++) { this.l[n+i]=data[i]; } } else if (pyjslib.isIteratable(data)) { var iter=data.__iter__(); var i=this.l.length; try { while (true) { var item=iter.next(); this.l[i++]=item; } } catch (e) { if (e != pyjslib.StopIteration) throw e; } } """) def remove(self, value): JS(""" var index=this.index(value); if (index<0) return false; this.l.splice(index, 1); return true; """) def index(self, value, start=0): JS(""" var length=this.l.length; for (var i=start; i<length; i++) { if (this.l[i]==value) { return i; } } return -1; """) def insert(self, index, value): JS(""" var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""") def pop(self, index=-1): JS(""" if (index<0) index = this.l.length + index; var a = this.l[index]; this.l.splice(index, 1); return a; """) def __cmp__(self, l): if not isinstance(l, List): return -1 ll = len(self) - len(l) if ll != 0: return ll for x in range(len(l)): ll = cmp(self.__getitem__(x), l[x]) if ll != 0: return ll return 0 def slice(self, lower, upper): JS(""" if (upper==null) return pyjslib.List(this.l.slice(lower)); return pyjslib.List(this.l.slice(lower, upper)); """) def __getitem__(self, index): JS(""" if (index<0) index = this.l.length + index; return this.l[index]; """) def __setitem__(self, index, value): JS(""" this.l[index]=value;""") def __delitem__(self, index): JS(""" this.l.splice(index, 1);""") def __len__(self): JS(""" return this.l.length;""") def __contains__(self, value): return self.index(value) >= 0 def __iter__(self): JS(""" var i = 0; var l = this.l; return { 'next': function() { if (i >= l.length) { throw pyjslib.StopIteration; } return l[i++]; }, '__iter__': function() { return this; } }; """) def reverse(self): JS(""" this.l.reverse();""") def sort(self, compareFunc=None, keyFunc=None, reverse=False): if not compareFunc: compareFunc = cmp if keyFunc and reverse: def thisSort1(a, b): return -compareFunc(keyFunc(a), keyFunc(b)) self.l.sort(thisSort1) elif keyFunc: def thisSort2(a, b): return compareFunc(keyFunc(a), keyFunc(b)) self.l.sort(thisSort2) elif reverse: def thisSort3(a, b): return -compareFunc(a, b) self.l.sort(thisSort3) else: self.l.sort(compareFunc) def getArray(self): """ Access the javascript Array that is used internally by this list """ return self.l def __str__(self): return repr(self) list = List class Tuple: def __init__(self, data=None): JS(""" this.l = []; this.extend(data); """) def append(self, item): JS(""" this.l[this.l.length] = item;""") def extend(self, data): JS(""" if (pyjslib.isArray(data)) { n = this.l.length; for (var i=0; i < data.length; i++) { this.l[n+i]=data[i]; } } else if (pyjslib.isIteratable(data)) { var iter=data.__iter__(); var i=this.l.length; try { while (true) { var item=iter.next(); this.l[i++]=item; } } catch (e) { if (e != pyjslib.StopIteration) throw e; } } """) def remove(self, value): JS(""" var index=this.index(value); if (index<0) return false; this.l.splice(index, 1); return true; """) def index(self, value, start=0): JS(""" var length=this.l.length; for (var i=start; i<length; i++) { if (this.l[i]==value) { return i; } } return -1; """) def insert(self, index, value): JS(""" var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""") def pop(self, index=-1): JS(""" if (index<0) index = this.l.length + index; var a = this.l[index]; this.l.splice(index, 1); return a; """) def __cmp__(self, l): if not isinstance(l, Tuple): return -1 ll = len(self) - len(l) if ll != 0: return ll for x in range(len(l)): ll = cmp(self.__getitem__(x), l[x]) if ll != 0: return ll return 0 def slice(self, lower, upper): JS(""" if (upper==null) return pyjslib.Tuple(this.l.slice(lower)); return pyjslib.Tuple(this.l.slice(lower, upper)); """) def __getitem__(self, index): JS(""" if (index<0) index = this.l.length + index; return this.l[index]; """) def __setitem__(self, index, value): JS(""" this.l[index]=value;""") def __delitem__(self, index): JS(""" this.l.splice(index, 1);""") def __len__(self): JS(""" return this.l.length;""") def __contains__(self, value): return self.index(value) >= 0 def __iter__(self): JS(""" var i = 0; var l = this.l; return { 'next': function() { if (i >= l.length) { throw pyjslib.StopIteration; } return l[i++]; }, '__iter__': function() { return this; } }; """) def reverse(self): JS(""" this.l.reverse();""") def sort(self, compareFunc=None, keyFunc=None, reverse=False): if not compareFunc: compareFunc = cmp if keyFunc and reverse: def thisSort1(a, b): return -compareFunc(keyFunc(a), keyFunc(b)) self.l.sort(thisSort1) elif keyFunc: def thisSort2(a, b): return compareFunc(keyFunc(a), keyFunc(b)) self.l.sort(thisSort2) elif reverse: def thisSort3(a, b): return -compareFunc(a, b) self.l.sort(thisSort3) else: self.l.sort(compareFunc) def getArray(self): """ Access the javascript Array that is used internally by this list """ return self.l def __str__(self): return repr(self) tuple = Tuple class Dict: def __init__(self, data=None): JS(""" this.d = {}; if (pyjslib.isArray(data)) { for (var i in data) { var item=data[i]; this.__setitem__(item[0], item[1]); //var sKey=pyjslib.hash(item[0]); //this.d[sKey]=item[1]; } } else if (pyjslib.isIteratable(data)) { var iter=data.__iter__(); try { while (true) { var item=iter.next(); this.__setitem__(item.__getitem__(0), item.__getitem__(1)); } } catch (e) { if (e != pyjslib.StopIteration) throw e; } } else if (pyjslib.isObject(data)) { for (var key in data) { this.__setitem__(key, data[key]); } } """) def __setitem__(self, key, value): JS(""" var sKey = pyjslib.hash(key); this.d[sKey]=[key, value]; """) def __getitem__(self, key): JS(""" var sKey = pyjslib.hash(key); var value=this.d[sKey]; if (pyjslib.isUndefined(value)){ throw pyjslib.KeyError(key); } return value[1]; """) def __nonzero__(self): JS(""" for (var i in this.d){ return true; } return false; """) def __len__(self): JS(""" var size=0; for (var i in this.d) size++; return size; """) def has_key(self, key): return self.__contains__(key) def __delitem__(self, key): JS(""" var sKey = pyjslib.hash(key); delete this.d[sKey]; """) def __contains__(self, key): JS(""" var sKey = pyjslib.hash(key); return (pyjslib.isUndefined(this.d[sKey])) ? false : true; """) def keys(self): JS(""" var keys=new pyjslib.List(); for (var key in this.d) { keys.append(this.d[key][0]); } return keys; """) def values(self): JS(""" var values=new pyjslib.List(); for (var key in this.d) values.append(this.d[key][1]); return values; """) def items(self): JS(""" var items = new pyjslib.List(); for (var key in this.d) { var kv = this.d[key]; items.append(new pyjslib.List(kv)) } return items; """) def __iter__(self): return self.keys().__iter__() def iterkeys(self): return self.__iter__() def itervalues(self): return self.values().__iter__() def iteritems(self): return self.items().__iter__() def setdefault(self, key, default_value): if key not in self: self[key] = default_value def get(self, key, default_=None): if key not in self: return default_ return self[key] def update(self, d): for k, v in d.iteritems(): self[k] = v def getObject(self): """ Return the javascript Object which this class uses to store dictionary keys and values """ return self.d def copy(self): return Dict(self.items()) def __str__(self): return repr(self) dict = Dict # taken from mochikit: range( [start,] stop[, step] ) def range(): JS(""" var start = 0; var stop = 0; var step = 1; if (arguments.length == 2) { start = arguments[0]; stop = arguments[1]; } else if (arguments.length == 3) { start = arguments[0]; stop = arguments[1]; step = arguments[2]; } else if (arguments.length>0) stop = arguments[0]; return { 'next': function() { if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration; var rval = start; start += step; return rval; }, '__iter__': function() { return this; } } """) def slice(object, lower, upper): JS(""" if (pyjslib.isString(object)) { if (lower < 0) { lower = object.length + lower; } if (upper < 0) { upper = object.length + upper; } if (pyjslib.isNull(upper)) upper=object.length; return object.substring(lower, upper); } if (pyjslib.isObject(object) && object.slice) return object.slice(lower, upper); return null; """) def str(text): JS(""" if (pyjslib.hasattr(text,"__str__")) { return text.__str__(); } return String(text); """) def ord(x): if isString(x) and len(x) is 1: JS(""" return x.charCodeAt(0); """) else: JS(""" throw pyjslib.TypeError(); """) return None def chr(x): JS(""" return String.fromCharCode(x) """) def is_basetype(x): JS(""" var t = typeof(x); return t == 'boolean' || t == 'function' || t == 'number' || t == 'string' || t == 'undefined' ; """) def get_pyjs_classtype(x): JS(""" if (pyjslib.hasattr(x, "__class__")) if (pyjslib.hasattr(x.__class__, "__new__")) var src = x.__class__.__name__; return src; return null; """) def repr(x): """ Return the string representation of 'x'. """ JS(""" if (x === null) return "null"; if (x === undefined) return "undefined"; var t = typeof(x); //alert("repr typeof " + t + " : " + x); if (t == "boolean") return x.toString(); if (t == "function") return "<function " + x.toString() + ">"; if (t == "number") return x.toString(); if (t == "string") { if (x.indexOf("'") == -1) return "'" + x + "'"; if (x.indexOf('"') == -1) return '"' + x + '"'; var s = x.replace(new RegExp('"', "g"), '\\\\"'); return '"' + s + '"'; }; if (t == "undefined") return "undefined"; // If we get here, x is an object. See if it's a Pyjamas class. if (!pyjslib.hasattr(x, "__init__")) return "<" + x.toString() + ">"; // Handle the common Pyjamas data types. var constructor = "UNKNOWN"; constructor = pyjslib.get_pyjs_classtype(x); //alert("repr constructor: " + constructor); if (constructor == "Tuple") { var contents = x.getArray(); var s = "("; for (var i=0; i < contents.length; i++) { s += pyjslib.repr(contents[i]); if (i < contents.length - 1) s += ", "; }; s += ")" return s; }; if (constructor == "List") { var contents = x.getArray(); var s = "["; for (var i=0; i < contents.length; i++) { s += pyjslib.repr(contents[i]); if (i < contents.length - 1) s += ", "; }; s += "]" return s; }; if (constructor == "Dict") { var keys = new Array(); for (var key in x.d) keys.push(key); var s = "{"; for (var i=0; i<keys.length; i++) { var key = keys[i] s += pyjslib.repr(key) + ": " + pyjslib.repr(x.d[key]); if (i < keys.length-1) s += ", " }; s += "}"; return s; }; // If we get here, the class isn't one we know -> return the class name. // Note that we replace underscores with dots so that the name will // (hopefully!) look like the original Python name. //var s = constructor.replace(new RegExp('_', "g"), '.'); return "<" + constructor + " object>"; """) def float(text): JS(""" return parseFloat(text); """) def int(text, radix=0): JS(""" return parseInt(text, radix); """) def len(object): JS(""" if (object==null) return 0; if (pyjslib.isObject(object) && object.__len__) return object.__len__(); return object.length; """) def isinstance(object_, classinfo): if pyjslib.isUndefined(object_): return False if not pyjslib.isObject(object_): return False if _isinstance(classinfo, Tuple): for ci in classinfo: if isinstance(object_, ci): return True return False else: return _isinstance(object_, classinfo) def _isinstance(object_, classinfo): if not pyjslib.isObject(object_): return False JS(""" if (object_.__class__){ var res = object_ instanceof classinfo.constructor; return res; } return false; """) def getattr(obj, name, default_=None): JS(""" if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){ if (pyjslib.isUndefined(default_)){ throw pyjslib.AttributeError(obj, name); }else{ return default_; } } if (!pyjslib.isFunction(obj[name])) return obj[name]; var fnwrap = function() { var args = []; for (var i = 0; i < arguments.length; i++) { args.push(arguments[i]); } return obj[name].apply(obj,args); } fnwrap.__name__ = name; return fnwrap; """) def setattr(obj, name, value): JS(""" if (!pyjslib.isObject(obj)) return null; obj[name] = value; """) def hasattr(obj, name): JS(""" if (!pyjslib.isObject(obj)) return false; if (pyjslib.isUndefined(obj[name])) return false; return true; """) def dir(obj): JS(""" var properties=new pyjslib.List(); for (property in obj) properties.append(property); return properties; """) def filter(obj, method, sequence=None): # object context is LOST when a method is passed, hence object must be passed separately # to emulate python behaviour, should generate this code inline rather than as a function call items = [] if sequence is None: sequence = method method = obj for item in sequence: if method(item): items.append(item) else: for item in sequence: if method.call(obj, item): items.append(item) return items def map(obj, method, sequence=None): items = [] if sequence is None: sequence = method method = obj for item in sequence: items.append(method(item)) else: for item in sequence: items.append(method.call(obj, item)) return items def enumerate(sequence): enumeration = [] nextIndex = 0 for item in sequence: enumeration.append([nextIndex, item]) nextIndex = nextIndex + 1 return enumeration def min(*sequence): minValue = None for item in sequence: if minValue is None: minValue = item elif item < minValue: minValue = item return minValue def max(*sequence): maxValue = None for item in sequence: if maxValue is None: maxValue = item elif item > maxValue: maxValue = item return maxValue next_hash_id = 0 def hash(obj): JS(""" if (obj == null) return null; if (obj.$H) return obj.$H; if (obj.__hash__) return obj.__hash__(); if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj; obj.$H = ++pyjslib.next_hash_id; return obj.$H; """) # type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html def isObject(a): JS(""" return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a); """) def isFunction(a): JS(""" return typeof a == 'function'; """) def isString(a): JS(""" return typeof a == 'string'; """) def isNull(a): JS(""" return typeof a == 'object' && !a; """) def isArray(a): JS(""" return pyjslib.isObject(a) && a.constructor == Array; """) def isUndefined(a): JS(""" return typeof a == 'undefined'; """) def isIteratable(a): JS(""" return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__); """) def isNumber(a): JS(""" return typeof a == 'number' && isFinite(a); """) def toJSObjects(x): """ Convert the pyjs pythonic List and Dict objects into javascript Object and Array objects, recursively. """ if isArray(x): JS(""" var result = []; for(var k=0; k < x.length; k++) { var v = x[k]; var tv = pyjslib.toJSObjects(v); result.push(tv); } return result; """) if isObject(x): if isinstance(x, Dict): JS(""" var o = x.getObject(); var result = {}; for (var i in o) { result[o[i][0].toString()] = o[i][1]; } return pyjslib.toJSObjects(result) """) elif isinstance(x, List): return toJSObjects(x.l) elif hasattr(x, '__class__'): # we do not have a special implementation for custom # classes, just pass it on return x if isObject(x): JS(""" var result = {}; for(var k in x) { var v = x[k]; var tv = pyjslib.toJSObjects(v) result[k] = tv; } return result; """) return x def printFunc(objs): JS(""" if ($wnd.console==undefined) return; var s = ""; for(var i=0; i < objs.length; i++) { if(s != "") s += " "; s += objs[i]; } console.debug(s) """) def type(clsname, bases=None, methods=None): """ creates a class, derived from bases, with methods and variables """ JS(" var mths = {}; ") if methods: for k in methods.keys(): _mth = methods[k] JS(" mths[k] = _mth; ") JS(" var bss = null; ") if bases: JS("bss = bases.l;") JS(" return pyjs_type(clsname, bss, mths); ")