PageRenderTime 39ms CodeModel.GetById 8ms app.highlight 23ms RepoModel.GetById 2ms app.codeStats 0ms

/library/pyjslib.py

http://pyjamas.googlecode.com/
Python | 699 lines | 681 code | 3 blank | 15 comment | 0 complexity | e222c3da1675663a2d6d425a291eadb5 MD5 | raw file
  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# pyjs_extend from Kevin Lindsey's Inteheritance Tutorial (http://www.kevlindev.com/tutorials/javascript/inheritance/)
 18from __pyjamas__ import JS
 19
 20JS("""
 21StopIteration = function () {};
 22StopIteration.prototype = new Error();
 23StopIteration.name = 'StopIteration';
 24StopIteration.message = 'StopIteration';
 25
 26KeyError = function () {};
 27KeyError.prototype = new Error();
 28KeyError.name = 'KeyError';
 29KeyError.message = 'KeyError';
 30
 31function pyjslib_String_find(sub, start, end) {
 32    var pos=this.indexOf(sub, start);
 33    if (pyjslib_isUndefined(end)) return pos;
 34
 35    if (pos + sub.length>end) return -1;
 36    return pos;
 37}
 38    
 39function pyjslib_String_join(data) {
 40    var text="";
 41    
 42    if (pyjslib_isArray(data)) {
 43        return data.join(this);
 44    }
 45    else if (pyjslib_isIteratable(data)) {
 46        var iter=data.__iter__();
 47        try {
 48            text+=iter.next();
 49            while (true) {
 50                var item=iter.next();
 51                text+=this + item;
 52            }
 53        }
 54        catch (e) {
 55            if (e != StopIteration) throw e;
 56        }
 57    }
 58
 59    return text;
 60}
 61
 62function pyjslib_String_replace(old, replace, count) {
 63    var do_max=false;
 64    var start=0;
 65    var new_str="";
 66    var pos=0;
 67    
 68    if (!pyjslib_isString(old)) return this.__replace(old, replace);
 69    if (!pyjslib_isUndefined(count)) do_max=true;
 70    
 71    while (start<this.length) {
 72        if (do_max && !count--) break;
 73        
 74        pos=this.indexOf(old, start);
 75        if (pos<0) break;
 76        
 77        new_str+=this.substring(start, pos) + replace;
 78        start=pos+old.length;
 79    }
 80    if (start<this.length) new_str+=this.substring(start);
 81
 82    return new_str;
 83}
 84
 85function pyjslib_String_split(sep, maxsplit) {
 86    var items=new pyjslib_List();
 87    var do_max=false;
 88    var subject=this;
 89    var start=0;
 90    var pos=0;
 91    
 92    if (pyjslib_isUndefined(sep) || pyjslib_isNull(sep)) {
 93        sep=" ";
 94        subject=subject.strip();
 95        subject=subject.replace(/\s+/g, sep);
 96    }
 97    else if (!pyjslib_isUndefined(maxsplit)) do_max=true;
 98
 99    while (start<subject.length) {
100        if (do_max && !maxsplit--) break;
101    
102        pos=subject.indexOf(sep, start);
103        if (pos<0) break;
104        
105        items.append(subject.substring(start, pos));
106        start=pos+sep.length;
107    }
108    if (start<subject.length) items.append(subject.substring(start));
109    
110    return items;
111}
112
113function pyjslib_String_strip(chars) {
114    return this.lstrip(chars).rstrip(chars);
115}
116
117function pyjslib_String_lstrip(chars) {
118    if (pyjslib_isUndefined(chars)) return this.replace(/^\s+/, "");
119
120    return this.replace(new RegExp("^[" + chars + "]+"), "");
121}
122
123function pyjslib_String_rstrip(chars) {
124    if (pyjslib_isUndefined(chars)) return this.replace(/\s+$/, "");
125
126    return this.replace(new RegExp("[" + chars + "]+$"), "");
127}
128
129function pyjslib_String_startswith(prefix, start) {
130    if (pyjslib_isUndefined(start)) start = 0;
131
132    if (this.substring(start, prefix.length) == prefix) return true;
133    return false;
134}
135
136String.prototype.__getitem__ = String.prototype.charAt;
137String.prototype.upper = String.prototype.toUpperCase;
138String.prototype.lower = String.prototype.toLowerCase;
139String.prototype.find=pyjslib_String_find;
140String.prototype.join=pyjslib_String_join;
141
142String.prototype.__replace=String.prototype.replace;
143String.prototype.replace=pyjslib_String_replace;
144
145String.prototype.split=pyjslib_String_split;
146String.prototype.strip=pyjslib_String_strip;
147String.prototype.lstrip=pyjslib_String_lstrip;
148String.prototype.rstrip=pyjslib_String_rstrip;
149String.prototype.startswith=pyjslib_String_startswith;
150
151var str = String;
152
153var pyjslib_abs = Math.abs;
154
155function pyjs_extend(klass, base) {
156    function klass_object_inherit() {}
157    klass_object_inherit.prototype = base.prototype;
158    klass_object = new klass_object_inherit();
159    for (var i in base.prototype.__class__) {
160        v = base.prototype.__class__[i];
161        if (typeof v == "function" && (v.class_method || v.static_method || v.unbound_method))
162        {
163            klass_object[i] = v;
164        }
165    }
166    
167    function klass_inherit() {}
168    klass_inherit.prototype = klass_object;
169    klass.prototype = new klass_inherit();
170    klass_object.constructor = klass;
171    klass.prototype.__class__ = klass_object;
172    
173    for (var i in base.prototype) {
174        v = base.prototype[i];
175        if (typeof v == "function" && v.instance_method)
176        {
177            klass.prototype[i] = v;
178        }
179    }
180}
181
182function pyjs_kwargs_function_call(func, args)
183{
184    return func.apply(null, func.parse_kwargs.apply(null, args));
185}
186
187function pyjs_kwargs_method_call(obj, method_name, args)
188{
189    var method = obj[method_name];
190    return method.apply(obj, method.parse_kwargs.apply(null, args));
191}
192
193""")
194
195class Object:
196    pass
197
198class Class:
199    def __init__(self, name):
200        self.name = name
201        
202    def __str___(self):
203        return self.name
204
205def cmp(a,b):
206    if hasattr(a, "__cmp__"):
207        return a.__cmp__(b)
208    elif hasattr(a, "__cmp__"):
209        return -b.__cmp__(a)
210    if a > b:
211        return 1
212    elif b > a:
213        return -1
214    else:
215        return 0
216
217class List:
218    def __init__(self, data=None):
219        JS("""
220        this.l = [];
221        
222        if (pyjslib_isArray(data)) {
223            for (var i=0; i < data.length; i++) {
224                this.l[i]=data[i];
225                }
226            }
227        else if (pyjslib_isIteratable(data)) {
228            var iter=data.__iter__();
229            var i=0;
230            try {
231                while (true) {
232                    var item=iter.next();
233                    this.l[i++]=item;
234                    }
235                }
236            catch (e) {
237                if (e != StopIteration) throw e;
238                }
239            }
240        """)
241    
242    def append(self, item):
243        JS("""    this.l[this.l.length] = item;""")
244
245    def remove(self, value):
246        JS("""
247        var index=this.index(value);
248        if (index<0) return false;
249        this.l.splice(index, 1);
250        return true;
251        """)
252        
253    def index(self, value, start=0):
254        JS("""
255        var length=this.l.length;
256        for (var i=start; i<length; i++) {
257            if (this.l[i]==value) {
258                return i;
259                }
260            }
261        return -1;
262        """)
263
264    def insert(self, index, value):
265        JS("""    var a = this.l; this.l=a.slice(0, index).concat(value, a.slice(index));""")
266
267    def pop(self, index = -1):
268        JS("""
269        if (index<0) index = this.l.length + index;
270        var a = this.l[index];
271        this.l.splice(index, 1);
272        return a;
273        """)
274
275    def slice(self, lower, upper):
276        JS("""
277        if (upper==null) return pyjslib_List(this.l.slice(lower));
278        return pyjslib_List(this.l.slice(lower, upper));
279        """)
280
281    def __getitem__(self, index):
282        JS("""
283        if (index<0) index = this.l.length + index;
284        return this.l[index];
285        """)
286
287    def __setitem__(self, index, value):
288        JS("""    this.l[index]=value;""")
289
290    def __delitem__(self, index):
291        JS("""    this.l.splice(index, 1);""")
292
293    def __len__(self):
294        JS("""    return this.l.length;""")
295
296    def __contains__(self, value):
297        return self.index(value) >= 0
298
299    def __iter__(self):
300        JS("""
301        var i = 0;
302        var l = this.l;
303        
304        return {
305            'next': function() {
306                if (i >= l.length) {
307                    throw StopIteration;
308                }
309                return l[i++];
310            },
311            '__iter__': function() {
312                return this;
313            }
314        };
315        """)
316    
317    def sort(self, compareFunc=None, keyFunc=None, reverse=False):
318        if not compareFunc:
319            global cmp
320            compareFunc = cmp
321        if keyFunc and reverse:
322            def thisSort1(a,b):
323                return -compareFunc(keyFunc(a), keyFunc(b))
324            self.l.sort(thisSort1)
325        elif keyFunc:
326            def thisSort2(a,b):
327                return compareFunc(keyFunc(a), keyFunc(b))
328            self.l.sort(thisSort2)
329        elif reverse:
330            def thisSort3(a,b):
331                return -compareFunc(a, b)
332            self.l.sort(thisSort3)
333        else:
334            self.l.sort(compareFunc)
335    
336    def getArray(self):
337        """
338        Access the javascript Array that is used internally by this list
339        """
340        return self.l
341
342list = List
343
344class Tuple(List):
345    def __init__(self, data):
346        List.__init__(self, data)
347    
348tuple = Tuple
349
350
351class Dict:
352    def __init__(self, data=None):
353        JS("""
354        this.d = {};
355
356        if (pyjslib_isArray(data)) {
357            for (var i in data) {
358                var item=data[i];
359                this.d[item[0]]=item[1];
360                }
361            }
362        else if (pyjslib_isIteratable(data)) {
363            var iter=data.__iter__();
364            try {
365                while (true) {
366                    var item=iter.next();
367                    this.d[item.__getitem__(0)]=item.__getitem__(1);
368                    }
369                }
370            catch (e) {
371                if (e != StopIteration) throw e;
372                }
373            }
374        else if (pyjslib_isObject(data)) {
375            for (var key in data) {
376                this.d[key]=data[key];
377                }
378            }
379        """)
380    
381    def __setitem__(self, key, value):
382        JS(""" this.d[key]=value;""")
383
384    def __getitem__(self, key):
385        JS("""
386        var value=this.d[key];
387        // if (pyjslib_isUndefined(value)) throw KeyError;
388        return value;
389        """)
390
391    def __len__(self):
392        JS("""
393        var size=0;
394        for (var i in this.d) size++;
395        return size;
396        """)
397
398    def has_key(self, key):
399        JS("""
400        if (pyjslib_isUndefined(this.d[key])) return false;
401        return true;
402        """)
403    
404    def __delitem__(self, key):
405        JS(""" delete this.d[key];""")
406
407    def __contains__(self, key):
408        JS("""    return (pyjslib_isUndefined(this.d[key])) ? false : true;""")
409
410    def keys(self):
411        JS("""
412        var keys=new pyjslib_List();
413        for (var key in this.d) keys.append(key);
414        return keys;
415        """)
416
417    def values(self):
418        JS("""
419        var keys=new pyjslib_List();
420        for (var key in this.d) keys.append(this.d[key]);
421        return keys;
422        """)
423        
424    def __iter__(self):
425        JS("""
426        return this.keys().__iter__();
427        """)
428
429    def iterkeys(self):
430        JS("""
431        return this.keys().__iter__();
432        """)
433
434    def itervalues(self):
435        JS("""
436        return this.values().__iter__();
437        """)
438
439    def iteritems(self):
440        JS("""
441        var d = this.d;
442        var iter=this.keys().__iter__();
443        
444        return {
445            '__iter__': function() {
446                return this;
447            },
448
449            'next': function() {
450                var key;
451                while (key=iter.next()) {
452                    var item=new pyjslib_List();
453                    item.append(key);
454                    item.append(d[key]);
455                    return item;
456                }
457            }
458        };
459        """)
460        
461    def setdefault(self, key, default_value): 
462        if not self.has_key(key):
463            self[key] = default_value
464    
465    def get(self, key, default_value=None):    
466        value = self[key]
467        JS("if(pyjslib_isUndefined(value)) { value = default_value; }")
468        return value;
469    
470    def update(self, d):
471        for k,v in d.iteritems():
472            self[k] = v
473
474    def getObject(self):
475        """
476        Return the javascript Object which this class uses to store dictionary keys and values
477        """
478        return self.d
479dict = Dict
480            
481# taken from mochikit: range( [start,] stop[, step] )
482def range():
483    JS("""
484    var start = 0;
485    var stop = 0;
486    var step = 1;
487
488    if (arguments.length == 2) {
489        start = arguments[0];
490        stop = arguments[1];
491        }
492    else if (arguments.length == 3) {
493        start = arguments[0];
494        stop = arguments[1];
495        step = arguments[2];
496        }
497    else if (arguments.length>0) stop = arguments[0];
498
499    return {
500        'next': function() {
501            if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) throw StopIteration;
502            var rval = start;
503            start += step;
504            return rval;
505            },
506        '__iter__': function() {
507            return this;
508            }
509        }
510    """)
511
512def slice(object, lower, upper):
513    JS("""
514    if (pyjslib_isString(object)) {
515        if (pyjslib_isNull(upper)) upper=object.length;
516        return object.substring(lower, upper);
517        }
518    if (pyjslib_isObject(object) && object.slice) return object.slice(lower, upper);
519    
520    return null;
521    """)
522
523def str(text):
524    JS("""
525    return String(text);
526    """)
527
528def int(text, radix=0):
529    JS("""
530    return parseInt(text, radix);
531    """)
532
533def len(object):
534    JS("""
535    if (object==null) return 0;
536    if (pyjslib_isObject(object) && object.__len__) return object.__len__();
537    return object.length;
538    """)
539
540def getattr(obj, method):
541    JS("""
542    if (!pyjslib_isObject(obj)) return null;
543    if (!pyjslib_isFunction(obj[method])) return obj[method];
544
545    return function() {
546        obj[method].call(obj);
547        }
548    """)
549
550def hasattr(obj, method):
551    JS("""
552    if (!pyjslib_isObject(obj)) return false;
553    if (pyjslib_isUndefined(obj[method])) return false;
554
555    return true;
556    """)
557
558def dir(obj):
559    JS("""
560    var properties=new pyjslib_List();
561    for (property in obj) properties.append(property);
562    return properties;
563    """)
564
565def filter(obj, method, sequence=None):
566    # object context is LOST when a method is passed, hence object must be passed separately
567    # to emulate python behaviour, should generate this code inline rather than as a function call
568    items = []
569    if sequence == None:
570        sequence = method
571        method = obj
572
573        for item in sequence:
574            if method(item):
575                items.append(item)
576    else:
577        for item in sequence:
578            if method.call(obj, item):
579                items.append(item)
580
581    return items
582
583
584def map(obj, method, sequence=None):
585    items = []
586    
587    if sequence == None:
588        sequence = method
589        method = obj
590        
591        for item in sequence:
592            items.append(method(item))
593    else:
594        for item in sequence:
595            items.append(method.call(obj, item))
596    
597    return items
598
599
600next_hash_id = 0
601
602def hash(obj):
603    JS("""
604    if (obj == null) return null;
605    
606    if (obj.$H) return obj.$H;
607    if (obj.__hash__) return obj.__hash__();
608    if (obj.constructor == String || obj.constructor == Number || obj.constructor == Date) return obj;
609    
610    obj.$H = ++pyjslib_next_hash_id;
611    return obj.$H;
612    """)
613
614
615# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
616def isObject(a):
617    JS("""
618    return (a && typeof a == 'object') || pyjslib_isFunction(a);
619    """)
620
621def isFunction(a):
622    JS("""
623    return typeof a == 'function';
624    """)
625
626def isString(a):
627    JS("""
628    return typeof a == 'string';
629    """)
630
631def isNull(a):
632    JS("""
633    return typeof a == 'object' && !a;
634    """)
635
636def isArray(a):
637    JS("""
638    return pyjslib_isObject(a) && a.constructor == Array;
639    """)
640
641def isUndefined(a):
642    JS("""
643    return typeof a == 'undefined';
644    """)
645
646def isIteratable(a):
647    JS("""
648    return pyjslib_isObject(a) && a.__iter__;
649    """)
650
651def isNumber(a):
652    JS("""
653    return typeof a == 'number' && isFinite(a);
654    """)
655
656def toJSObjects(x):
657    """
658       Convert the pyjs pythonic List and Dict objects into javascript Object and Array
659       objects, recursively.
660    """
661    result = x
662   
663    if isObject(x) and x.__class__:
664        if x.__class__ == 'pyjslib_Dict':
665            return toJSObjects(x.d)
666        elif x.__class__ == 'pyjslib_List':
667            return toJSObjects(x.l)
668   
669    if isObject(x):
670        JS("""
671        result = {};
672        for(var k in x) {
673           var v = x[k];
674           var tv = pyjslib_toJSObjects(v)
675           result[k] = tv;
676        }
677        """)
678    if isArray(x):
679        JS("""
680        result = [];
681        for(var k=0; k < x.length; k++) {
682           var v = x[k];
683           var tv = pyjslib_toJSObjects(v);
684           result.push(tv);
685        }
686        """)
687        
688    return result
689
690def printFunc(objs):
691    JS("""
692    var s = "";
693    for(var i=0; i < objs.length; i++) {
694        if(s != "") s += " ";
695        s += objs[i];
696    }
697    console.debug(s)
698    """)
699