/library/pyjslib.py
Python | 699 lines | 681 code | 3 blank | 15 comment | 0 complexity | e222c3da1675663a2d6d425a291eadb5 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
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