py_ext/modules/svgui/pyjs/lib/pyjslib.py
changeset 728 e0424e96e3fd
parent 727 3edd2f19bce2
child 729 25054c592dc4
equal deleted inserted replaced
727:3edd2f19bce2 728:e0424e96e3fd
     1 # Copyright 2006 James Tauber and contributors
       
     2 #
       
     3 # Licensed under the Apache License, Version 2.0 (the "License");
       
     4 # you may not use this file except in compliance with the License.
       
     5 # You may obtain a copy of the License at
       
     6 #
       
     7 #     http://www.apache.org/licenses/LICENSE-2.0
       
     8 #
       
     9 # Unless required by applicable law or agreed to in writing, software
       
    10 # distributed under the License is distributed on an "AS IS" BASIS,
       
    11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    12 # See the License for the specific language governing permissions and
       
    13 # limitations under the License.
       
    14 
       
    15 
       
    16 # iteration from Bob Ippolito's Iteration in JavaScript
       
    17 
       
    18 from __pyjamas__ import JS
       
    19 
       
    20 # must declare import _before_ importing sys
       
    21 
       
    22 def import_module(path, parent_module, module_name, dynamic=1, async=False):
       
    23     """ 
       
    24     """
       
    25 
       
    26     JS("""
       
    27         var cache_file;
       
    28 
       
    29         if (module_name == "sys" || module_name == 'pyjslib')
       
    30         {
       
    31             /*module_load_request[module_name] = 1;*/
       
    32             return;
       
    33         }
       
    34 
       
    35         if (path == null)
       
    36         {
       
    37             path = './';
       
    38         }
       
    39 
       
    40         var override_name = sys.platform + "." + module_name;
       
    41         if (((sys.overrides != null) && 
       
    42              (sys.overrides.has_key(override_name))))
       
    43         {
       
    44             cache_file =  sys.overrides.__getitem__(override_name) ;
       
    45         }
       
    46         else
       
    47         {
       
    48             cache_file =  module_name ;
       
    49         }
       
    50 
       
    51         cache_file = (path + cache_file + '.cache.js' ) ;
       
    52 
       
    53         //alert("cache " + cache_file + " " + module_name + " " + parent_module);
       
    54 
       
    55         /* already loaded? */
       
    56         if (module_load_request[module_name])
       
    57         {
       
    58             if (module_load_request[module_name] >= 3 && parent_module != null)
       
    59             {
       
    60                 //onload_fn = parent_module + '.' + module_name + ' = ' + module_name + ';';
       
    61                 //pyjs_eval(onload_fn); /* set up the parent-module namespace */
       
    62             }
       
    63             return;
       
    64         }
       
    65         if (typeof (module_load_request[module_name]) == 'undefined')
       
    66         {
       
    67             module_load_request[module_name] = 1;
       
    68         }
       
    69 
       
    70         /* following a load, this first executes the script 
       
    71          * "preparation" function MODULENAME_loaded_fn()
       
    72          * and then sets up the loaded module in the namespace
       
    73          * of the parent.
       
    74          */
       
    75 
       
    76         onload_fn = ''; // module_name + "_loaded_fn();"
       
    77 
       
    78         if (parent_module != null)
       
    79         {
       
    80             //onload_fn += parent_module + '.' + module_name + ' = ' + module_name + ';';
       
    81             /*pmod = parent_module + '.' + module_name;
       
    82             onload_fn += 'alert("' + pmod + '"+' + pmod+');';*/
       
    83         }
       
    84 
       
    85 
       
    86         if (dynamic)
       
    87         {
       
    88             /* this one tacks the script onto the end of the DOM
       
    89              */
       
    90 
       
    91             pyjs_load_script(cache_file, onload_fn, async);
       
    92 
       
    93             /* this one actually RUNS the script (eval) into the page.
       
    94                my feeling is that this would be better for non-async
       
    95                but i can't get it to work entirely yet.
       
    96              */
       
    97             /*pyjs_ajax_eval(cache_file, onload_fn, async);*/
       
    98         }
       
    99         else
       
   100         {
       
   101             if (module_name != "pyjslib" &&
       
   102                 module_name != "sys")
       
   103                 pyjs_eval(onload_fn);
       
   104         }
       
   105 
       
   106     """)
       
   107 
       
   108 JS("""
       
   109 function import_wait(proceed_fn, parent_mod, dynamic) {
       
   110 
       
   111     var data = '';
       
   112     var element = $doc.createElement("div");
       
   113     $doc.body.appendChild(element);
       
   114     function write_dom(txt) {
       
   115         element.innerHTML = txt + '<br />';
       
   116     }
       
   117 
       
   118     var timeoutperiod = 1;
       
   119     if (dynamic)
       
   120         var timeoutperiod = 1;
       
   121 
       
   122     var wait = function() {
       
   123 
       
   124         var status = '';
       
   125         for (l in module_load_request)
       
   126         {
       
   127             var m = module_load_request[l];
       
   128             if (l == "sys" || l == 'pyjslib')
       
   129                 continue;
       
   130             status += l + m + " ";
       
   131         }
       
   132 
       
   133         //write_dom( " import wait " + wait_count + " " + status + " parent_mod " + parent_mod);
       
   134         wait_count += 1;
       
   135 
       
   136         if (status == '')
       
   137         {
       
   138             setTimeout(wait, timeoutperiod);
       
   139             return;
       
   140         }
       
   141 
       
   142         for (l in module_load_request)
       
   143         {
       
   144             var m = module_load_request[l];
       
   145             if (l == "sys" || l == 'pyjslib')
       
   146             {
       
   147                 module_load_request[l] = 4;
       
   148                 continue;
       
   149             }
       
   150             if ((parent_mod != null) && (l == parent_mod))
       
   151             {
       
   152                 if (m == 1)
       
   153                 {
       
   154                     setTimeout(wait, timeoutperiod);
       
   155                     return;
       
   156                 }
       
   157                 if (m == 2)
       
   158                 {
       
   159                     /* cheat and move app on to next stage */
       
   160                     module_load_request[l] = 3;
       
   161                 }
       
   162             }
       
   163             if (m == 1 || m == 2)
       
   164             {
       
   165                 setTimeout(wait, timeoutperiod);
       
   166                 return;
       
   167             }
       
   168             if (m == 3)
       
   169             {
       
   170                 //alert("waited for module " + l + ": loaded");
       
   171                 module_load_request[l] = 4;
       
   172                 mod_fn = modules[l];
       
   173             }
       
   174         }
       
   175         //alert("module wait done");
       
   176 
       
   177         if (proceed_fn.importDone)
       
   178             proceed_fn.importDone(proceed_fn);
       
   179         else
       
   180             proceed_fn();
       
   181     }
       
   182 
       
   183     wait();
       
   184 }
       
   185 """)
       
   186 
       
   187 class Object:
       
   188     pass
       
   189 
       
   190 object = Object
       
   191 
       
   192 class Modload:
       
   193 
       
   194     def __init__(self, path, app_modlist, app_imported_fn, dynamic,
       
   195                  parent_mod):
       
   196         self.app_modlist = app_modlist
       
   197         self.app_imported_fn = app_imported_fn
       
   198         self.path = path
       
   199         self.idx = 0;
       
   200         self.dynamic = dynamic
       
   201         self.parent_mod = parent_mod
       
   202 
       
   203     def next(self):
       
   204         
       
   205         for i in range(len(self.app_modlist[self.idx])):
       
   206             app = self.app_modlist[self.idx][i]
       
   207             import_module(self.path, self.parent_mod, app, self.dynamic, True);
       
   208         self.idx += 1
       
   209 
       
   210         if self.idx >= len(self.app_modlist):
       
   211             import_wait(self.app_imported_fn, self.parent_mod, self.dynamic)
       
   212         else:
       
   213             import_wait(getattr(self, "next"), self.parent_mod, self.dynamic)
       
   214 
       
   215 def get_module(module_name):
       
   216     ev = "__mod = %s;" % module_name
       
   217     JS("pyjs_eval(ev);")
       
   218     return __mod
       
   219 
       
   220 def preload_app_modules(path, app_modnames, app_imported_fn, dynamic,
       
   221                         parent_mod=None):
       
   222 
       
   223     loader = Modload(path, app_modnames, app_imported_fn, dynamic, parent_mod)
       
   224     loader.next()
       
   225 
       
   226 import sys
       
   227 
       
   228 class BaseException:
       
   229 
       
   230     name = "BaseException"
       
   231 
       
   232     def __init__(self, *args):
       
   233         self.args = args
       
   234 
       
   235     def __str__(self):
       
   236         if len(self.args) is 0:
       
   237             return ''
       
   238         elif len(self.args) is 1:
       
   239             return repr(self.args[0])
       
   240         return repr(self.args)
       
   241 
       
   242     def toString(self):
       
   243         return str(self)
       
   244 
       
   245 class Exception(BaseException):
       
   246 
       
   247     name = "Exception"
       
   248 
       
   249 class TypeError(BaseException):
       
   250     name = "TypeError"
       
   251 
       
   252 class StandardError(Exception):
       
   253     name = "StandardError"
       
   254 
       
   255 class LookupError(StandardError):
       
   256     name = "LookupError"
       
   257 
       
   258     def toString(self):
       
   259         return self.name + ": " + self.args[0]
       
   260 
       
   261 class KeyError(LookupError):
       
   262     name = "KeyError"
       
   263 
       
   264 class AttributeError(StandardError):
       
   265 
       
   266     name = "AttributeError"
       
   267 
       
   268     def toString(self):
       
   269         return "AttributeError: %s of %s" % (self.args[1], self.args[0])
       
   270 
       
   271 JS("""
       
   272 pyjslib.StopIteration = function () { };
       
   273 pyjslib.StopIteration.prototype = new Error();
       
   274 pyjslib.StopIteration.name = 'StopIteration';
       
   275 pyjslib.StopIteration.message = 'StopIteration';
       
   276 
       
   277 pyjslib.String_find = function(sub, start, end) {
       
   278     var pos=this.indexOf(sub, start);
       
   279     if (pyjslib.isUndefined(end)) return pos;
       
   280 
       
   281     if (pos + sub.length>end) return -1;
       
   282     return pos;
       
   283 }
       
   284 
       
   285 pyjslib.String_join = function(data) {
       
   286     var text="";
       
   287 
       
   288     if (pyjslib.isArray(data)) {
       
   289         return data.join(this);
       
   290     }
       
   291     else if (pyjslib.isIteratable(data)) {
       
   292         var iter=data.__iter__();
       
   293         try {
       
   294             text+=iter.next();
       
   295             while (true) {
       
   296                 var item=iter.next();
       
   297                 text+=this + item;
       
   298             }
       
   299         }
       
   300         catch (e) {
       
   301             if (e != pyjslib.StopIteration) throw e;
       
   302         }
       
   303     }
       
   304 
       
   305     return text;
       
   306 }
       
   307 
       
   308 pyjslib.String_isdigit = function() {
       
   309     return (this.match(/^\d+$/g) != null);
       
   310 }
       
   311 
       
   312 pyjslib.String_replace = function(old, replace, count) {
       
   313     var do_max=false;
       
   314     var start=0;
       
   315     var new_str="";
       
   316     var pos=0;
       
   317 
       
   318     if (!pyjslib.isString(old)) return this.__replace(old, replace);
       
   319     if (!pyjslib.isUndefined(count)) do_max=true;
       
   320 
       
   321     while (start<this.length) {
       
   322         if (do_max && !count--) break;
       
   323 
       
   324         pos=this.indexOf(old, start);
       
   325         if (pos<0) break;
       
   326 
       
   327         new_str+=this.substring(start, pos) + replace;
       
   328         start=pos+old.length;
       
   329     }
       
   330     if (start<this.length) new_str+=this.substring(start);
       
   331 
       
   332     return new_str;
       
   333 }
       
   334 
       
   335 pyjslib.String_split = function(sep, maxsplit) {
       
   336     var items=new pyjslib.List();
       
   337     var do_max=false;
       
   338     var subject=this;
       
   339     var start=0;
       
   340     var pos=0;
       
   341 
       
   342     if (pyjslib.isUndefined(sep) || pyjslib.isNull(sep)) {
       
   343         sep=" ";
       
   344         subject=subject.strip();
       
   345         subject=subject.replace(/\s+/g, sep);
       
   346     }
       
   347     else if (!pyjslib.isUndefined(maxsplit)) do_max=true;
       
   348 
       
   349     if (subject.length == 0) {
       
   350         return items;
       
   351     }
       
   352 
       
   353     while (start<subject.length) {
       
   354         if (do_max && !maxsplit--) break;
       
   355 
       
   356         pos=subject.indexOf(sep, start);
       
   357         if (pos<0) break;
       
   358 
       
   359         items.append(subject.substring(start, pos));
       
   360         start=pos+sep.length;
       
   361     }
       
   362     if (start<=subject.length) items.append(subject.substring(start));
       
   363 
       
   364     return items;
       
   365 }
       
   366 
       
   367 pyjslib.String___iter__ = function() {
       
   368     var i = 0;
       
   369     var s = this;
       
   370     return {
       
   371         'next': function() {
       
   372             if (i >= s.length) {
       
   373                 throw pyjslib.StopIteration;
       
   374             }
       
   375             return s.substring(i++, i, 1);
       
   376         },
       
   377         '__iter__': function() {
       
   378             return this;
       
   379         }
       
   380     };
       
   381 }
       
   382 
       
   383 pyjslib.String_strip = function(chars) {
       
   384     return this.lstrip(chars).rstrip(chars);
       
   385 }
       
   386 
       
   387 pyjslib.String_lstrip = function(chars) {
       
   388     if (pyjslib.isUndefined(chars)) return this.replace(/^\s+/, "");
       
   389 
       
   390     return this.replace(new RegExp("^[" + chars + "]+"), "");
       
   391 }
       
   392 
       
   393 pyjslib.String_rstrip = function(chars) {
       
   394     if (pyjslib.isUndefined(chars)) return this.replace(/\s+$/, "");
       
   395 
       
   396     return this.replace(new RegExp("[" + chars + "]+$"), "");
       
   397 }
       
   398 
       
   399 pyjslib.String_startswith = function(prefix, start) {
       
   400     if (pyjslib.isUndefined(start)) start = 0;
       
   401 
       
   402     if (this.substring(start, prefix.length) == prefix) return true;
       
   403     return false;
       
   404 }
       
   405 
       
   406 pyjslib.abs = Math.abs;
       
   407 
       
   408 """)
       
   409 
       
   410 class Class:
       
   411     def __init__(self, name):
       
   412         self.name = name
       
   413 
       
   414     def __str___(self):
       
   415         return self.name
       
   416 
       
   417 def eq(a,b):
       
   418     JS("""
       
   419     if (pyjslib.hasattr(a, "__cmp__")) {
       
   420         return a.__cmp__(b) == 0;
       
   421     } else if (pyjslib.hasattr(b, "__cmp__")) {
       
   422         return b.__cmp__(a) == 0;
       
   423     }
       
   424     return a == b;
       
   425     """)
       
   426 
       
   427 def cmp(a,b):
       
   428     if hasattr(a, "__cmp__"):
       
   429         return a.__cmp__(b)
       
   430     elif hasattr(b, "__cmp__"):
       
   431         return -b.__cmp__(a)
       
   432     if a > b:
       
   433         return 1
       
   434     elif b > a:
       
   435         return -1
       
   436     else:
       
   437         return 0
       
   438 
       
   439 def bool(v):
       
   440     # this needs to stay in native code without any dependencies here,
       
   441     # because this is used by if and while, we need to prevent
       
   442     # recursion
       
   443     JS("""
       
   444     if (!v) return false;
       
   445     switch(typeof v){
       
   446     case 'boolean':
       
   447         return v;
       
   448     case 'object':
       
   449         if (v.__nonzero__){
       
   450             return v.__nonzero__();
       
   451         }else if (v.__len__){
       
   452             return v.__len__()>0;
       
   453         }
       
   454         return true;
       
   455     }
       
   456     return Boolean(v);
       
   457     """)
       
   458 
       
   459 class List:
       
   460     def __init__(self, data=None):
       
   461         JS("""
       
   462         this.l = [];
       
   463         this.extend(data);
       
   464         """)
       
   465 
       
   466     def append(self, item):
       
   467         JS("""    this.l[this.l.length] = item;""")
       
   468 
       
   469     def extend(self, data):
       
   470         JS("""
       
   471         if (pyjslib.isArray(data)) {
       
   472             n = this.l.length;
       
   473             for (var i=0; i < data.length; i++) {
       
   474                 this.l[n+i]=data[i];
       
   475                 }
       
   476             }
       
   477         else if (pyjslib.isIteratable(data)) {
       
   478             var iter=data.__iter__();
       
   479             var i=this.l.length;
       
   480             try {
       
   481                 while (true) {
       
   482                     var item=iter.next();
       
   483                     this.l[i++]=item;
       
   484                     }
       
   485                 }
       
   486             catch (e) {
       
   487                 if (e != pyjslib.StopIteration) throw e;
       
   488                 }
       
   489             }
       
   490         """)
       
   491 
       
   492     def remove(self, value):
       
   493         JS("""
       
   494         var index=this.index(value);
       
   495         if (index<0) return false;
       
   496         this.l.splice(index, 1);
       
   497         return true;
       
   498         """)
       
   499 
       
   500     def index(self, value, start=0):
       
   501         JS("""
       
   502         var length=this.l.length;
       
   503         for (var i=start; i<length; i++) {
       
   504             if (this.l[i]==value) {
       
   505                 return i;
       
   506                 }
       
   507             }
       
   508         return -1;
       
   509         """)
       
   510 
       
   511     def insert(self, index, value):
       
   512         JS("""    var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""")
       
   513 
       
   514     def pop(self, index = -1):
       
   515         JS("""
       
   516         if (index<0) index = this.l.length + index;
       
   517         var a = this.l[index];
       
   518         this.l.splice(index, 1);
       
   519         return a;
       
   520         """)
       
   521 
       
   522     def __cmp__(self, l):
       
   523         if not isinstance(l, List):
       
   524             return -1
       
   525         ll = len(self) - len(l)
       
   526         if ll != 0:
       
   527             return ll
       
   528         for x in range(len(l)):
       
   529             ll = cmp(self.__getitem__(x), l[x])
       
   530             if ll != 0:
       
   531                 return ll
       
   532         return 0
       
   533 
       
   534     def slice(self, lower, upper):
       
   535         JS("""
       
   536         if (upper==null) return pyjslib.List(this.l.slice(lower));
       
   537         return pyjslib.List(this.l.slice(lower, upper));
       
   538         """)
       
   539 
       
   540     def __getitem__(self, index):
       
   541         JS("""
       
   542         if (index<0) index = this.l.length + index;
       
   543         return this.l[index];
       
   544         """)
       
   545 
       
   546     def __setitem__(self, index, value):
       
   547         JS("""    this.l[index]=value;""")
       
   548 
       
   549     def __delitem__(self, index):
       
   550         JS("""    this.l.splice(index, 1);""")
       
   551 
       
   552     def __len__(self):
       
   553         JS("""    return this.l.length;""")
       
   554 
       
   555     def __contains__(self, value):
       
   556         return self.index(value) >= 0
       
   557 
       
   558     def __iter__(self):
       
   559         JS("""
       
   560         var i = 0;
       
   561         var l = this.l;
       
   562         return {
       
   563             'next': function() {
       
   564                 if (i >= l.length) {
       
   565                     throw pyjslib.StopIteration;
       
   566                 }
       
   567                 return l[i++];
       
   568             },
       
   569             '__iter__': function() {
       
   570                 return this;
       
   571             }
       
   572         };
       
   573         """)
       
   574 
       
   575     def reverse(self):
       
   576         JS("""    this.l.reverse();""")
       
   577 
       
   578     def sort(self, compareFunc=None, keyFunc=None, reverse=False):
       
   579         if not compareFunc:
       
   580             global cmp
       
   581             compareFunc = cmp
       
   582         if keyFunc and reverse:
       
   583             def thisSort1(a,b):
       
   584                 return -compareFunc(keyFunc(a), keyFunc(b))
       
   585             self.l.sort(thisSort1)
       
   586         elif keyFunc:
       
   587             def thisSort2(a,b):
       
   588                 return compareFunc(keyFunc(a), keyFunc(b))
       
   589             self.l.sort(thisSort2)
       
   590         elif reverse:
       
   591             def thisSort3(a,b):
       
   592                 return -compareFunc(a, b)
       
   593             self.l.sort(thisSort3)
       
   594         else:
       
   595             self.l.sort(compareFunc)
       
   596 
       
   597     def getArray(self):
       
   598         """
       
   599         Access the javascript Array that is used internally by this list
       
   600         """
       
   601         return self.l
       
   602 
       
   603     def __str__(self):
       
   604         return repr(self)
       
   605 
       
   606 list = List
       
   607 
       
   608 class Tuple:
       
   609     def __init__(self, data=None):
       
   610         JS("""
       
   611         this.l = [];
       
   612         this.extend(data);
       
   613         """)
       
   614 
       
   615     def append(self, item):
       
   616         JS("""    this.l[this.l.length] = item;""")
       
   617 
       
   618     def extend(self, data):
       
   619         JS("""
       
   620         if (pyjslib.isArray(data)) {
       
   621             n = this.l.length;
       
   622             for (var i=0; i < data.length; i++) {
       
   623                 this.l[n+i]=data[i];
       
   624                 }
       
   625             }
       
   626         else if (pyjslib.isIteratable(data)) {
       
   627             var iter=data.__iter__();
       
   628             var i=this.l.length;
       
   629             try {
       
   630                 while (true) {
       
   631                     var item=iter.next();
       
   632                     this.l[i++]=item;
       
   633                     }
       
   634                 }
       
   635             catch (e) {
       
   636                 if (e != pyjslib.StopIteration) throw e;
       
   637                 }
       
   638             }
       
   639         """)
       
   640 
       
   641     def remove(self, value):
       
   642         JS("""
       
   643         var index=this.index(value);
       
   644         if (index<0) return false;
       
   645         this.l.splice(index, 1);
       
   646         return true;
       
   647         """)
       
   648 
       
   649     def index(self, value, start=0):
       
   650         JS("""
       
   651         var length=this.l.length;
       
   652         for (var i=start; i<length; i++) {
       
   653             if (this.l[i]==value) {
       
   654                 return i;
       
   655                 }
       
   656             }
       
   657         return -1;
       
   658         """)
       
   659 
       
   660     def insert(self, index, value):
       
   661         JS("""    var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""")
       
   662 
       
   663     def pop(self, index = -1):
       
   664         JS("""
       
   665         if (index<0) index = this.l.length + index;
       
   666         var a = this.l[index];
       
   667         this.l.splice(index, 1);
       
   668         return a;
       
   669         """)
       
   670 
       
   671     def __cmp__(self, l):
       
   672         if not isinstance(l, Tuple):
       
   673             return -1
       
   674         ll = len(self) - len(l)
       
   675         if ll != 0:
       
   676             return ll
       
   677         for x in range(len(l)):
       
   678             ll = cmp(self.__getitem__(x), l[x])
       
   679             if ll != 0:
       
   680                 return ll
       
   681         return 0
       
   682 
       
   683     def slice(self, lower, upper):
       
   684         JS("""
       
   685         if (upper==null) return pyjslib.Tuple(this.l.slice(lower));
       
   686         return pyjslib.Tuple(this.l.slice(lower, upper));
       
   687         """)
       
   688 
       
   689     def __getitem__(self, index):
       
   690         JS("""
       
   691         if (index<0) index = this.l.length + index;
       
   692         return this.l[index];
       
   693         """)
       
   694 
       
   695     def __setitem__(self, index, value):
       
   696         JS("""    this.l[index]=value;""")
       
   697 
       
   698     def __delitem__(self, index):
       
   699         JS("""    this.l.splice(index, 1);""")
       
   700 
       
   701     def __len__(self):
       
   702         JS("""    return this.l.length;""")
       
   703 
       
   704     def __contains__(self, value):
       
   705         return self.index(value) >= 0
       
   706 
       
   707     def __iter__(self):
       
   708         JS("""
       
   709         var i = 0;
       
   710         var l = this.l;
       
   711         return {
       
   712             'next': function() {
       
   713                 if (i >= l.length) {
       
   714                     throw pyjslib.StopIteration;
       
   715                 }
       
   716                 return l[i++];
       
   717             },
       
   718             '__iter__': function() {
       
   719                 return this;
       
   720             }
       
   721         };
       
   722         """)
       
   723 
       
   724     def reverse(self):
       
   725         JS("""    this.l.reverse();""")
       
   726 
       
   727     def sort(self, compareFunc=None, keyFunc=None, reverse=False):
       
   728         if not compareFunc:
       
   729             global cmp
       
   730             compareFunc = cmp
       
   731         if keyFunc and reverse:
       
   732             def thisSort1(a,b):
       
   733                 return -compareFunc(keyFunc(a), keyFunc(b))
       
   734             self.l.sort(thisSort1)
       
   735         elif keyFunc:
       
   736             def thisSort2(a,b):
       
   737                 return compareFunc(keyFunc(a), keyFunc(b))
       
   738             self.l.sort(thisSort2)
       
   739         elif reverse:
       
   740             def thisSort3(a,b):
       
   741                 return -compareFunc(a, b)
       
   742             self.l.sort(thisSort3)
       
   743         else:
       
   744             self.l.sort(compareFunc)
       
   745 
       
   746     def getArray(self):
       
   747         """
       
   748         Access the javascript Array that is used internally by this list
       
   749         """
       
   750         return self.l
       
   751 
       
   752     def __str__(self):
       
   753         return repr(self)
       
   754 
       
   755 tuple = Tuple
       
   756 
       
   757 
       
   758 class Dict:
       
   759     def __init__(self, data=None):
       
   760         JS("""
       
   761         this.d = {};
       
   762 
       
   763         if (pyjslib.isArray(data)) {
       
   764             for (var i in data) {
       
   765                 var item=data[i];
       
   766                 this.__setitem__(item[0], item[1]);
       
   767                 //var sKey=pyjslib.hash(item[0]);
       
   768                 //this.d[sKey]=item[1];
       
   769                 }
       
   770             }
       
   771         else if (pyjslib.isIteratable(data)) {
       
   772             var iter=data.__iter__();
       
   773             try {
       
   774                 while (true) {
       
   775                     var item=iter.next();
       
   776                     this.__setitem__(item.__getitem__(0), item.__getitem__(1));
       
   777                     }
       
   778                 }
       
   779             catch (e) {
       
   780                 if (e != pyjslib.StopIteration) throw e;
       
   781                 }
       
   782             }
       
   783         else if (pyjslib.isObject(data)) {
       
   784             for (var key in data) {
       
   785                 this.__setitem__(key, data[key]);
       
   786                 }
       
   787             }
       
   788         """)
       
   789 
       
   790     def __setitem__(self, key, value):
       
   791         JS("""
       
   792         var sKey = pyjslib.hash(key);
       
   793         this.d[sKey]=[key, value];
       
   794         """)
       
   795 
       
   796     def __getitem__(self, key):
       
   797         JS("""
       
   798         var sKey = pyjslib.hash(key);
       
   799         var value=this.d[sKey];
       
   800         if (pyjslib.isUndefined(value)){
       
   801             throw pyjslib.KeyError(key);
       
   802         }
       
   803         return value[1];
       
   804         """)
       
   805 
       
   806     def __nonzero__(self):
       
   807         JS("""
       
   808         for (var i in this.d){
       
   809             return true;
       
   810         }
       
   811         return false;
       
   812         """)
       
   813 
       
   814     def __len__(self):
       
   815         JS("""
       
   816         var size=0;
       
   817         for (var i in this.d) size++;
       
   818         return size;
       
   819         """)
       
   820 
       
   821     def has_key(self, key):
       
   822         return self.__contains__(key)
       
   823 
       
   824     def __delitem__(self, key):
       
   825         JS("""
       
   826         var sKey = pyjslib.hash(key);
       
   827         delete this.d[sKey];
       
   828         """)
       
   829 
       
   830     def __contains__(self, key):
       
   831         JS("""
       
   832         var sKey = pyjslib.hash(key);
       
   833         return (pyjslib.isUndefined(this.d[sKey])) ? false : true;
       
   834         """)
       
   835 
       
   836     def keys(self):
       
   837         JS("""
       
   838         var keys=new pyjslib.List();
       
   839         for (var key in this.d) {
       
   840             keys.append(this.d[key][0]);
       
   841         }
       
   842         return keys;
       
   843         """)
       
   844 
       
   845     def values(self):
       
   846         JS("""
       
   847         var values=new pyjslib.List();
       
   848         for (var key in this.d) values.append(this.d[key][1]);
       
   849         return values;
       
   850         """)
       
   851 
       
   852     def items(self):
       
   853         JS("""
       
   854         var items = new pyjslib.List();
       
   855         for (var key in this.d) {
       
   856           var kv = this.d[key];
       
   857           items.append(new pyjslib.List(kv))
       
   858           }
       
   859           return items;
       
   860         """)
       
   861 
       
   862     def __iter__(self):
       
   863         return self.keys().__iter__()
       
   864 
       
   865     def iterkeys(self):
       
   866         return self.__iter__()
       
   867 
       
   868     def itervalues(self):
       
   869         return self.values().__iter__();
       
   870 
       
   871     def iteritems(self):
       
   872         return self.items().__iter__();
       
   873 
       
   874     def setdefault(self, key, default_value):
       
   875         if not self.has_key(key):
       
   876             self[key] = default_value
       
   877 
       
   878     def get(self, key, default_=None):
       
   879         if not self.has_key(key):
       
   880             return default_
       
   881         return self[key]
       
   882 
       
   883     def update(self, d):
       
   884         for k,v in d.iteritems():
       
   885             self[k] = v
       
   886 
       
   887     def getObject(self):
       
   888         """
       
   889         Return the javascript Object which this class uses to store
       
   890         dictionary keys and values
       
   891         """
       
   892         return self.d
       
   893 
       
   894     def copy(self):
       
   895         return Dict(self.items())
       
   896 
       
   897     def __str__(self):
       
   898         return repr(self)
       
   899 
       
   900 dict = Dict
       
   901 
       
   902 # taken from mochikit: range( [start,] stop[, step] )
       
   903 def range():
       
   904     JS("""
       
   905     var start = 0;
       
   906     var stop = 0;
       
   907     var step = 1;
       
   908 
       
   909     if (arguments.length == 2) {
       
   910         start = arguments[0];
       
   911         stop = arguments[1];
       
   912         }
       
   913     else if (arguments.length == 3) {
       
   914         start = arguments[0];
       
   915         stop = arguments[1];
       
   916         step = arguments[2];
       
   917         }
       
   918     else if (arguments.length>0) stop = arguments[0];
       
   919 
       
   920     return {
       
   921         'next': function() {
       
   922             if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw pyjslib.StopIteration;
       
   923             var rval = start;
       
   924             start += step;
       
   925             return rval;
       
   926             },
       
   927         '__iter__': function() {
       
   928             return this;
       
   929             }
       
   930         }
       
   931     """)
       
   932 
       
   933 def slice(object, lower, upper):
       
   934     JS("""
       
   935     if (pyjslib.isString(object)) {
       
   936         if (lower < 0) {
       
   937            lower = object.length + lower;
       
   938         }
       
   939         if (upper < 0) {
       
   940            upper = object.length + upper;
       
   941         }
       
   942         if (pyjslib.isNull(upper)) upper=object.length;
       
   943         return object.substring(lower, upper);
       
   944     }
       
   945     if (pyjslib.isObject(object) && object.slice)
       
   946         return object.slice(lower, upper);
       
   947 
       
   948     return null;
       
   949     """)
       
   950 
       
   951 def str(text):
       
   952     JS("""
       
   953     if (pyjslib.hasattr(text,"__str__")) {
       
   954         return text.__str__();
       
   955     }
       
   956     return String(text);
       
   957     """)
       
   958 
       
   959 def ord(x):
       
   960     if(isString(x) and len(x) is 1):
       
   961         JS("""
       
   962             return x.charCodeAt(0);
       
   963         """)
       
   964     else:
       
   965         JS("""
       
   966             throw pyjslib.TypeError();
       
   967         """)
       
   968     return None
       
   969 
       
   970 def chr(x):
       
   971     JS("""
       
   972         return String.fromCharCode(x)
       
   973     """)
       
   974 
       
   975 def is_basetype(x):
       
   976     JS("""
       
   977        var t = typeof(x);
       
   978        return t == 'boolean' ||
       
   979        t == 'function' ||
       
   980        t == 'number' ||
       
   981        t == 'string' ||
       
   982        t == 'undefined'
       
   983        ;
       
   984     """)
       
   985 
       
   986 def get_pyjs_classtype(x):
       
   987     JS("""
       
   988        if (pyjslib.hasattr(x, "__class__"))
       
   989            if (pyjslib.hasattr(x.__class__, "__new__"))
       
   990                var src = x.__class__.__name__;
       
   991                return src;
       
   992        return null;
       
   993     """)
       
   994 
       
   995 def repr(x):
       
   996     """ Return the string representation of 'x'.
       
   997     """
       
   998     JS("""
       
   999        if (x === null)
       
  1000            return "null";
       
  1001 
       
  1002        if (x === undefined)
       
  1003            return "undefined";
       
  1004 
       
  1005        var t = typeof(x);
       
  1006 
       
  1007         //alert("repr typeof " + t + " : " + x);
       
  1008 
       
  1009        if (t == "boolean")
       
  1010            return x.toString();
       
  1011 
       
  1012        if (t == "function")
       
  1013            return "<function " + x.toString() + ">";
       
  1014 
       
  1015        if (t == "number")
       
  1016            return x.toString();
       
  1017 
       
  1018        if (t == "string") {
       
  1019            if (x.indexOf("'") == -1)
       
  1020                return "'" + x + "'";
       
  1021            if (x.indexOf('"') == -1)
       
  1022                return '"' + x + '"';
       
  1023            var s = x.replace(new RegExp('"', "g"), '\\\\"');
       
  1024            return '"' + s + '"';
       
  1025        };
       
  1026 
       
  1027        if (t == "undefined")
       
  1028            return "undefined";
       
  1029 
       
  1030        // If we get here, x is an object.  See if it's a Pyjamas class.
       
  1031 
       
  1032        if (!pyjslib.hasattr(x, "__init__"))
       
  1033            return "<" + x.toString() + ">";
       
  1034 
       
  1035        // Handle the common Pyjamas data types.
       
  1036 
       
  1037        var constructor = "UNKNOWN";
       
  1038 
       
  1039        constructor = pyjslib.get_pyjs_classtype(x);
       
  1040 
       
  1041         //alert("repr constructor: " + constructor);
       
  1042 
       
  1043        if (constructor == "Tuple") {
       
  1044            var contents = x.getArray();
       
  1045            var s = "(";
       
  1046            for (var i=0; i < contents.length; i++) {
       
  1047                s += pyjslib.repr(contents[i]);
       
  1048                if (i < contents.length - 1)
       
  1049                    s += ", ";
       
  1050            };
       
  1051            s += ")"
       
  1052            return s;
       
  1053        };
       
  1054 
       
  1055        if (constructor == "List") {
       
  1056            var contents = x.getArray();
       
  1057            var s = "[";
       
  1058            for (var i=0; i < contents.length; i++) {
       
  1059                s += pyjslib.repr(contents[i]);
       
  1060                if (i < contents.length - 1)
       
  1061                    s += ", ";
       
  1062            };
       
  1063            s += "]"
       
  1064            return s;
       
  1065        };
       
  1066 
       
  1067        if (constructor == "Dict") {
       
  1068            var keys = new Array();
       
  1069            for (var key in x.d)
       
  1070                keys.push(key);
       
  1071 
       
  1072            var s = "{";
       
  1073            for (var i=0; i<keys.length; i++) {
       
  1074                var key = keys[i]
       
  1075                s += pyjslib.repr(key) + ": " + pyjslib.repr(x.d[key]);
       
  1076                if (i < keys.length-1)
       
  1077                    s += ", "
       
  1078            };
       
  1079            s += "}";
       
  1080            return s;
       
  1081        };
       
  1082 
       
  1083        // If we get here, the class isn't one we know -> return the class name.
       
  1084        // Note that we replace underscores with dots so that the name will
       
  1085        // (hopefully!) look like the original Python name.
       
  1086 
       
  1087        //var s = constructor.replace(new RegExp('_', "g"), '.');
       
  1088        return "<" + constructor + " object>";
       
  1089     """)
       
  1090 
       
  1091 def float(text):
       
  1092     JS("""
       
  1093     return parseFloat(text);
       
  1094     """)
       
  1095 
       
  1096 def int(text, radix=0):
       
  1097     JS("""
       
  1098     return parseInt(text, radix);
       
  1099     """)
       
  1100 
       
  1101 def len(object):
       
  1102     JS("""
       
  1103     if (object==null) return 0;
       
  1104     if (pyjslib.isObject(object) && object.__len__) return object.__len__();
       
  1105     return object.length;
       
  1106     """)
       
  1107 
       
  1108 def isinstance(object_, classinfo):
       
  1109     if pyjslib.isUndefined(object_):
       
  1110         return False
       
  1111     if not pyjslib.isObject(object_):
       
  1112         
       
  1113         return False
       
  1114     if _isinstance(classinfo, Tuple):
       
  1115         for ci in classinfo:
       
  1116             if isinstance(object_, ci):
       
  1117                 return True
       
  1118         return False
       
  1119     else:
       
  1120         return _isinstance(object_, classinfo)
       
  1121 
       
  1122 def _isinstance(object_, classinfo):
       
  1123     if not pyjslib.isObject(object_):
       
  1124         return False
       
  1125     JS("""
       
  1126     if (object_.__class__){
       
  1127         var res =  object_ instanceof classinfo.constructor;
       
  1128         return res;
       
  1129     }
       
  1130     return false;
       
  1131     """)
       
  1132 
       
  1133 def getattr(obj, name, default_):
       
  1134     JS("""
       
  1135     if ((!pyjslib.isObject(obj))||(pyjslib.isUndefined(obj[name]))){
       
  1136         if (pyjslib.isUndefined(default_)){
       
  1137             throw pyjslib.AttributeError(obj, name);
       
  1138         }else{
       
  1139         return default_;
       
  1140         }
       
  1141     }
       
  1142     if (!pyjslib.isFunction(obj[name])) return obj[name];
       
  1143     var fnwrap = function() {
       
  1144         var args = [];
       
  1145         for (var i = 0; i < arguments.length; i++) {
       
  1146           args.push(arguments[i]);
       
  1147         }
       
  1148         return obj[name].apply(obj,args);
       
  1149         }
       
  1150     fnwrap.__name__ = name;
       
  1151     return fnwrap;
       
  1152     """)
       
  1153 
       
  1154 def setattr(obj, name, value):
       
  1155     JS("""
       
  1156     if (!pyjslib.isObject(obj)) return null;
       
  1157 
       
  1158     obj[name] = value;
       
  1159 
       
  1160     """)
       
  1161 
       
  1162 def hasattr(obj, name):
       
  1163     JS("""
       
  1164     if (!pyjslib.isObject(obj)) return false;
       
  1165     if (pyjslib.isUndefined(obj[name])) return false;
       
  1166 
       
  1167     return true;
       
  1168     """)
       
  1169 
       
  1170 def dir(obj):
       
  1171     JS("""
       
  1172     var properties=new pyjslib.List();
       
  1173     for (property in obj) properties.append(property);
       
  1174     return properties;
       
  1175     """)
       
  1176 
       
  1177 def filter(obj, method, sequence=None):
       
  1178     # object context is LOST when a method is passed, hence object must be passed separately
       
  1179     # to emulate python behaviour, should generate this code inline rather than as a function call
       
  1180     items = []
       
  1181     if sequence is None:
       
  1182         sequence = method
       
  1183         method = obj
       
  1184 
       
  1185         for item in sequence:
       
  1186             if method(item):
       
  1187                 items.append(item)
       
  1188     else:
       
  1189         for item in sequence:
       
  1190             if method.call(obj, item):
       
  1191                 items.append(item)
       
  1192 
       
  1193     return items
       
  1194 
       
  1195 
       
  1196 def map(obj, method, sequence=None):
       
  1197     items = []
       
  1198 
       
  1199     if sequence is None:
       
  1200         sequence = method
       
  1201         method = obj
       
  1202 
       
  1203         for item in sequence:
       
  1204             items.append(method(item))
       
  1205     else:
       
  1206         for item in sequence:
       
  1207             items.append(method.call(obj, item))
       
  1208 
       
  1209     return items
       
  1210 
       
  1211 
       
  1212 def enumerate(sequence):
       
  1213     enumeration = []
       
  1214     nextIndex = 0
       
  1215     for item in sequence:
       
  1216         enumeration.append([nextIndex, item])
       
  1217         nextIndex = nextIndex + 1
       
  1218     return enumeration
       
  1219 
       
  1220 
       
  1221 def min(*sequence):
       
  1222     minValue = None
       
  1223     for item in sequence:
       
  1224         if minValue is None:
       
  1225             minValue = item
       
  1226         elif item < minValue:
       
  1227             minValue = item
       
  1228     return minValue
       
  1229 
       
  1230 
       
  1231 def max(*sequence):
       
  1232     maxValue = None
       
  1233     for item in sequence:
       
  1234         if maxValue is None:
       
  1235             maxValue = item
       
  1236         elif item > maxValue:
       
  1237             maxValue = item
       
  1238     return maxValue
       
  1239 
       
  1240 
       
  1241 next_hash_id = 0
       
  1242 
       
  1243 def hash(obj):
       
  1244     JS("""
       
  1245     if (obj == null) return null;
       
  1246 
       
  1247     if (obj.$H) return obj.$H;
       
  1248     if (obj.__hash__) return obj.__hash__();
       
  1249     if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj;
       
  1250 
       
  1251     obj.$H = ++pyjslib.next_hash_id;
       
  1252     return obj.$H;
       
  1253     """)
       
  1254 
       
  1255 
       
  1256 # type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
       
  1257 def isObject(a):
       
  1258     JS("""
       
  1259     return (a != null && (typeof a == 'object')) || pyjslib.isFunction(a);
       
  1260     """)
       
  1261 
       
  1262 def isFunction(a):
       
  1263     JS("""
       
  1264     return typeof a == 'function';
       
  1265     """)
       
  1266 
       
  1267 def isString(a):
       
  1268     JS("""
       
  1269     return typeof a == 'string';
       
  1270     """)
       
  1271 
       
  1272 def isNull(a):
       
  1273     JS("""
       
  1274     return typeof a == 'object' && !a;
       
  1275     """)
       
  1276 
       
  1277 def isArray(a):
       
  1278     JS("""
       
  1279     return pyjslib.isObject(a) && a.constructor == Array;
       
  1280     """)
       
  1281 
       
  1282 def isUndefined(a):
       
  1283     JS("""
       
  1284     return typeof a == 'undefined';
       
  1285     """)
       
  1286 
       
  1287 def isIteratable(a):
       
  1288     JS("""
       
  1289     return pyjslib.isString(a) || (pyjslib.isObject(a) && a.__iter__);
       
  1290     """)
       
  1291 
       
  1292 def isNumber(a):
       
  1293     JS("""
       
  1294     return typeof a == 'number' && isFinite(a);
       
  1295     """)
       
  1296 
       
  1297 def toJSObjects(x):
       
  1298     """
       
  1299        Convert the pyjs pythonic List and Dict objects into javascript Object and Array
       
  1300        objects, recursively.
       
  1301     """
       
  1302     if isArray(x):
       
  1303         JS("""
       
  1304         var result = [];
       
  1305         for(var k=0; k < x.length; k++) {
       
  1306            var v = x[k];
       
  1307            var tv = pyjslib.toJSObjects(v);
       
  1308            result.push(tv);
       
  1309         }
       
  1310         return result;
       
  1311         """)
       
  1312     if isObject(x):
       
  1313         if isinstance(x, Dict):
       
  1314             JS("""
       
  1315             var o = x.getObject();
       
  1316             var result = {};
       
  1317             for (var i in o) {
       
  1318                result[o[i][0].toString()] = o[i][1];
       
  1319             }
       
  1320             return pyjslib.toJSObjects(result)
       
  1321             """)
       
  1322         elif isinstance(x, List):
       
  1323             return toJSObjects(x.l)
       
  1324         elif hasattr(x, '__class__'):
       
  1325             # we do not have a special implementation for custom
       
  1326             # classes, just pass it on
       
  1327             return x
       
  1328     if isObject(x):
       
  1329         JS("""
       
  1330         var result = {};
       
  1331         for(var k in x) {
       
  1332             var v = x[k];
       
  1333             var tv = pyjslib.toJSObjects(v)
       
  1334             result[k] = tv;
       
  1335             }
       
  1336             return result;
       
  1337          """)
       
  1338     return x
       
  1339 
       
  1340 def printFunc(objs):
       
  1341     JS("""
       
  1342     if ($wnd.console==undefined)  return;
       
  1343     var s = "";
       
  1344     for(var i=0; i < objs.length; i++) {
       
  1345         if(s != "") s += " ";
       
  1346         s += objs[i];
       
  1347     }
       
  1348     console.debug(s)
       
  1349     """)
       
  1350 
       
  1351 def type(clsname, bases=None, methods=None):
       
  1352     """ creates a class, derived from bases, with methods and variables
       
  1353     """
       
  1354 
       
  1355     JS(" var mths = {}; ")
       
  1356     if methods:
       
  1357         for k in methods.keys():
       
  1358             mth = methods[k]
       
  1359             JS(" mths[k] = mth; ")
       
  1360 
       
  1361     JS(" var bss = null; ")
       
  1362     if bases:
       
  1363         JS("bss = bases.l;")
       
  1364     JS(" return pyjs_type(clsname, bss, mths); ")
       
  1365