Permalink
Jan 14, 2015
Jan 14, 2015
Feb 10, 2018
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Aug 31, 2017
Jan 14, 2015
Aug 31, 2017
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Aug 31, 2017
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Feb 9, 2016
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Feb 10, 2018
Feb 10, 2018
Feb 10, 2018
Feb 9, 2018
Feb 11, 2018
Aug 31, 2017
Aug 31, 2017
Dec 3, 2015
Dec 3, 2015
Dec 28, 2017
Jan 6, 2016
Jan 6, 2016
Aug 31, 2017
Jan 6, 2016
Jan 6, 2016
Jan 6, 2016
Jan 6, 2016
Jan 6, 2016
Feb 10, 2018
Jan 6, 2016
Jan 6, 2016
Jan 6, 2016
Feb 11, 2018
Jan 1, 2015
Aug 31, 2017
Aug 31, 2017
Feb 10, 2018
Jul 10, 2017
Jun 29, 2017
Jun 29, 2017
Jun 29, 2017
Jun 29, 2017
Jul 10, 2017
Jul 10, 2017
Jul 14, 2017
Jun 29, 2017
Newer
100644
1947 lines (1780 sloc)
63.2 KB
5
if (!String.prototype.trim) {
6
// Polyfill for older browsers
7
// The code does not use a regex to make it a bit faster.
8
// Implementation taken from a comment by Timo on the blog:
9
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
10
String.prototype.trim = function () {
11
var c;
12
for (var i = 0; i < this.length; i++) {
13
c = this.charCodeAt(i);
14
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
15
continue; else break;
16
}
17
for (var j = this.length - 1; j >= i; j--) {
18
c = this.charCodeAt(j);
19
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
20
continue; else break;
21
}
22
return this.substring(i, j + 1);
23
}
24
}
25
if (!String.prototype.trimLeft) {
26
// Convenience method for browsers which do not have a native trimLeft
27
// (which is a nonstandard extension in Firefox and Chrome)
28
String.prototype.trimLeft = function () {
29
var c;
30
for (var i = 0; i < this.length; i++) {
31
c = this.charCodeAt(i);
32
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
33
continue; else break;
34
}
35
return this.substring(i);
36
};
37
}
38
if (!String.prototype.trimRight) {
39
String.prototype.trimRight = function () {
40
// Convenience method for browsers which do not have a native trimRight
41
// (which is a nonstandard extension in Firefox and Chrome)
42
var c;
43
for (var j = this.length - 1; j >= 0; j--) {
44
c = this.charCodeAt(j);
45
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
46
continue; else break;
47
}
48
return this.substring(0, j + 1);
49
};
50
}
62
function normalize_start_end($){
63
if($.start===null||$.start===_b_.None){$.start = 0}
64
else if($.start<0){$.start += $.self.length; $.start=Math.max(0, $.start)}
65
if($.end===null||$.end===_b_.None){$.end = $.self.length}
66
else if($.end<0){$.end += $.self.length; $.end=Math.max(0, $.end)}
67
68
if(!isinstance($.start,_b_.int)||!isinstance($.end,_b_.int)){
74
function reverse(s){
75
// Reverse a string
76
return s.split('').reverse().join('')
77
}
78
79
function check_str(obj){
88
"Can't convert "+$B.get_class(other).__name__+" to str implicitely")}
89
}
90
return self+other
91
}
92
95
"'in <string>' requires string as left operand, not "+item.__class__)}
96
var nbcar = item.length
97
if(nbcar==0) return true // a string contains the empty string
98
if(self.length==0) return nbcar==0
109
// __dir__must be assigned explicitely because attribute resolution for builtin
110
// classes doesn't use __mro__
114
if(other===undefined){ // compare object "self" to class "str"
115
return self===str
116
}
117
if (_b_.isinstance(other, _b_.str)) {
118
return other.valueOf() == self.valueOf()
119
}
137
// For strings, alignment default to left
138
fmt.align = fmt.align || '<'
139
return $B.format_width(preformat(self, fmt), fmt)
143
if(isinstance(arg,_b_.int)){
144
var pos = arg
145
if(arg<0) pos+=self.length
146
if(pos>=0 && pos<self.length) return self.charAt(pos)
152
var res = '',i=null
153
if(step>0){
154
if(stop<=start) return ''
155
for(var i=start;i<stop;i+=step) res += self.charAt(i)
156
} else {
157
if(stop>=start) return ''
168
return str.__hashvalue__ || $B.$py_next_hash-- // for hash of string type (not instance of string)
171
//http://stackoverflow.com/questions/2909106/python-whats-a-correct-and-good-way-to-implement-hash
172
// this implementation for strings maybe good enough for us..
173
174
var hash=1;
176
hash=(101*hash + self.charCodeAt(i)) & 0xFFFFFFFF
177
}
178
179
return hash
180
}
181
190
var items = self.split('') // list of all characters in string
191
return $B.$iterator(items,$str_iterator)
192
}
193
198
var kwarg_key = new RegExp('([^\\)]*)\\)')
199
200
var NotANumber = function() {
201
this.name = 'NotANumber'
202
}
203
204
var number_check=function(s) {
205
if(!isinstance(s,[_b_.int,_b_.float])){
206
throw new NotANumber()
207
}
208
}
209
210
var get_char_array = function(size, char) {
211
if (size <= 0)
212
return ''
213
return new Array(size + 1).join(char)
214
}
215
216
var format_padding = function(s, flags, minus_one) {
217
var padding = flags.padding
218
if (!padding) { // undefined
219
return s
220
}
221
s = s.toString()
222
padding = parseInt(padding, 10)
223
if (minus_one) { // numeric formatting where sign goes in front of padding
224
padding -= 1
225
}
226
if (!flags.left) {
227
return get_char_array(padding - s.length, flags.pad_char) + s
228
} else {
229
// left adjusted
230
return s + get_char_array(padding - s.length, flags.pad_char)
231
}
232
}
233
234
var format_int_precision = function(val, flags) {
235
var precision = flags.precision
236
if (!precision) {
237
return val.toString()
238
}
239
precision = parseInt(precision, 10)
246
if (s[0] === '-') {
247
return '-' + get_char_array(precision - s.length + 1, '0') + s.slice(1)
248
}
249
return get_char_array(precision - s.length, '0') + s
250
}
251
252
var format_float_precision = function(val, upper, flags, modifier) {
253
var precision = flags.precision
254
// val is a float
255
if (isFinite(val)) {
257
}
258
if (val === Infinity) {
259
val = 'inf'
260
} else if (val === -Infinity) {
261
val = '-inf'
262
} else {
263
val = 'nan'
264
}
265
if (upper) {
266
return val.toUpperCase()
267
}
268
return val
270
}
271
272
var format_sign = function(val, flags) {
273
if (flags.sign) {
274
if (val >= 0) {
275
return "+"
277
} else if (flags.space) {
278
if (val >= 0) {
279
return " "
280
}
281
}
282
return ""
283
}
285
var str_format = function(val, flags) {
286
// string format supports left and right padding
287
flags.pad_char = " " // even if 0 padding is defined, don't use it
299
var s = format_int_precision(val, flags)
300
if (flags.pad_char === '0') {
301
if (val < 0) {
302
s = s.substring(1)
303
return '-' + format_padding(s, flags, true)
304
}
305
var sign = format_sign(val, flags)
306
if (sign !== '') {
307
return sign + format_padding(s, flags, true)
308
}
309
}
314
var repr_format = function(val, flags) {
315
flags.pad_char = " " // even if 0 padding is defined, don't use it
316
return format_padding(repr(val), flags)
317
}
319
var ascii_format = function(val, flags) {
320
flags.pad_char = " " // even if 0 padding is defined, don't use it
321
return format_padding(ascii(val), flags)
322
}
325
var _float_helper = function(val, flags) {
326
number_check(val)
327
if (!flags.precision) {
328
if (!flags.decimal_point) {
329
flags.precision = 6
330
} else {
331
flags.precision = 0
332
}
333
} else {
334
flags.precision = parseInt(flags.precision, 10)
335
validate_precision(flags.precision)
336
}
337
return parseFloat(val)
338
}
340
// used to capture and remove trailing zeroes
341
var trailing_zeros = /(.*?)(0+)([eE].*)/
342
var leading_zeros = /\.(0*)/
343
var trailing_dot = /\.$/
345
var validate_precision = function(precision) {
346
// force precision to limits of javascript
348
}
349
350
// gG
351
var floating_point_format = function(val, upper, flags) {
352
val = _float_helper(val, flags)
353
var v = val.toString()
354
var v_len = v.length
355
var dot_idx = v.indexOf('.')
356
if (dot_idx < 0) {
357
dot_idx = v_len
358
}
359
if (val < 1 && val > -1) {
360
var zeros = leading_zeros.exec(v)
361
var numzeros
362
if (zeros) {
363
numzeros = zeros[1].length
364
} else {
365
numzeros = 0
366
}
367
if (numzeros >= 4) {
368
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
369
if (!flags.alternate) {
370
var trl = trailing_zeros.exec(val)
371
if (trl) {
372
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
382
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
388
if (dot_idx > flags.precision) {
389
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
390
if (!flags.alternate) {
391
var trl = trailing_zeros.exec(val)
392
if (trl) {
393
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
394
}
395
} else {
396
if (flags.precision <= 1) {
397
val = val[0] + '.' + val.substring(1)
398
}
399
}
400
return format_padding(val, flags)
401
}
402
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
403
function(val, precision) {
404
if (!flags.decimal_point) {
405
precision = min(v_len - 1, 6)
406
} else if (precision > v_len) {
407
if (!flags.alternate) {
408
precision = v_len
410
}
411
if (precision < dot_idx) {
412
precision = dot_idx
413
}
414
return val.toFixed(precision - dot_idx)
415
}), flags)
416
}
418
var _floating_g_exp_helper = function(val, precision, flags, upper) {
419
if (precision) {
420
--precision
421
}
422
val = val.toExponential(precision)
423
// pad exponent to two digits
424
var e_idx = val.lastIndexOf('e')
425
if (e_idx > val.length - 4) {
427
}
428
if (upper) {
429
return val.toUpperCase()
430
}
431
return val
432
}
433
434
// fF
435
var floating_point_decimal_format = function(val, upper, flags) {
436
val = _float_helper(val, flags)
437
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
438
function(val, precision, flags) {
439
val = val.toFixed(precision)
440
if (precision === 0 && flags.alternate) {
441
val += '.'
442
}
443
return val
444
}), flags)
445
}
446
447
var _floating_exp_helper = function(val, precision, flags, upper) {
448
val = val.toExponential(precision)
449
// pad exponent to two digits
450
var e_idx = val.lastIndexOf('e')
451
if (e_idx > val.length - 4) {
453
}
454
if (upper) {
455
return val.toUpperCase()
456
}
457
return val
458
}
459
460
// eE
461
var floating_point_exponential_format = function(val, upper, flags) {
462
val = _float_helper(val, flags)
464
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_exp_helper), flags)
465
}
466
467
var signed_hex_format = function(val, upper, flags) {
477
ret = format_int_precision(ret, flags)
478
if (upper) {
479
ret = ret.toUpperCase()
480
}
481
if (flags.pad_char === '0') {
482
if (val < 0) {
483
ret = ret.substring(1)
484
ret = '-' + format_padding(ret, flags, true)
485
}
486
var sign = format_sign(val, flags)
487
if (sign !== '') {
488
ret = sign + format_padding(ret, flags, true)
492
if (flags.alternate) {
493
if (ret.charAt(0) === '-') {
494
if (upper) {
495
ret = "-0X" + ret.slice(1)
496
} else {
497
ret = "-0x" + ret.slice(1)
498
}
499
} else {
500
if (upper) {
501
ret = "0X" + ret
502
} else {
503
ret = "0x" + ret
504
}
505
}
506
}
507
return format_padding(format_sign(val, flags) + ret, flags)
508
}
523
if (flags.pad_char === '0') {
524
if (val < 0) {
525
ret = ret.substring(1)
526
ret = '-' + format_padding(ret, flags, true)
527
}
528
var sign = format_sign(val, flags)
529
if (sign !== '') {
530
ret = sign + format_padding(ret, flags, true)
531
}
534
if (flags.alternate) {
535
if (ret.charAt(0) === '-') {
536
ret = "-0o" + ret.slice(1)
537
} else {
538
ret = "0o" + ret
539
}
541
return format_padding(ret, flags)
542
}
543
544
var single_char_format = function(val, flags) {
545
if(isinstance(val,str) && val.length==1) return val
546
try {
550
}
551
return format_padding(chr(val), flags)
552
}
553
554
var num_flag = function(c, flags) {
555
if (c === '0' && !flags.padding && !flags.decimal_point && !flags.left) {
556
flags.pad_char = '0'
557
return
558
}
559
if (!flags.decimal_point) {
560
flags.padding = (flags.padding || "") + c
561
} else {
562
flags.precision = (flags.precision || "") + c
563
}
564
}
565
566
var decimal_point_flag = function(val, flags) {
567
if (flags.decimal_point) {
568
// can only have one decimal point
569
throw new UnsupportedChar()
570
}
571
flags.decimal_point = true
572
}
573
574
var neg_flag = function(val, flags) {
575
flags.pad_char = ' ' // overrides '0' flag
576
flags.left = true
577
}
578
579
var space_flag = function(val, flags) {
580
flags.space = true
581
}
582
583
var sign_flag = function(val, flags) {
584
flags.sign = true
585
}
586
587
var alternate_flag = function(val, flags) {
588
flags.alternate = true
589
}
590
592
's': str_format,
593
'd': num_format,
594
'i': num_format,
595
'u': num_format,
596
'o': octal_format,
597
'r': repr_format,
598
'a': ascii_format,
599
'g': function(val, flags) {return floating_point_format(val, false, flags)},
600
'G': function(val, flags) {return floating_point_format(val, true, flags)},
601
'f': function(val, flags) {return floating_point_decimal_format(val, false, flags)},
602
'F': function(val, flags) {return floating_point_decimal_format(val, true, flags)},
603
'e': function(val, flags) {return floating_point_exponential_format(val, false, flags)},
604
'E': function(val, flags) {return floating_point_exponential_format(val, true, flags)},
605
'x': function(val, flags) {return signed_hex_format(val, false, flags)},
606
'X': function(val, flags) {return signed_hex_format(val, true, flags)},
607
'c': single_char_format,
608
'0': function(val, flags) {return num_flag('0', flags)},
609
'1': function(val, flags) {return num_flag('1', flags)},
610
'2': function(val, flags) {return num_flag('2', flags)},
611
'3': function(val, flags) {return num_flag('3', flags)},
612
'4': function(val, flags) {return num_flag('4', flags)},
613
'5': function(val, flags) {return num_flag('5', flags)},
614
'6': function(val, flags) {return num_flag('6', flags)},
615
'7': function(val, flags) {return num_flag('7', flags)},
616
'8': function(val, flags) {return num_flag('8', flags)},
617
'9': function(val, flags) {return num_flag('9', flags)},
618
'-': neg_flag,
619
' ': space_flag,
620
'+': sign_flag,
621
'.': decimal_point_flag,
622
'#': alternate_flag
623
}
624
625
// exception thrown when an unsupported char is encountered in legacy format
626
var UnsupportedChar = function() {
627
this.name = "UnsupportedChar"
628
}
629
632
var length = self.length,
633
pos = 0 |0,
634
argpos = null,
635
getitem
636
if (_b_.isinstance(args, _b_.tuple)) {
679
// todo: get flags, type
680
// todo: string value based on flags, type, value
681
var flags = {'pad_char': ' '}
682
do {
689
if (ret !== undefined) {
690
return ret
691
}
692
++newpos
693
}
694
} catch (err) {
695
if (err.name === "UnsupportedChar") {
696
invalid_char = s[newpos]
697
if (invalid_char === undefined) {
701
"' (0x" + invalid_char.charCodeAt(0).toString(16) + ") at index " + newpos)
702
} else if (err.name === "NotANumber") {
703
var try_char = s[newpos]
714
throw _b_.TypeError.$factory("%" + try_char + " format: a number is required, not " + cls)
753
throw _b_.TypeError.$factory('not all arguments converted during string formatting')
756
throw _b_.TypeError.$factory('not all arguments converted during string formatting')
764
var $=$B.args('__mul__',2,{self:null,other:null},['self','other'],
765
arguments,{},null,null)
777
var res = self.replace(/\n/g,'\\\\n')
778
// escape the escape char
779
res = res.replace(/\\/g, '\\\\')
780
if(res.search('"')==-1 && res.search("'")==-1){
781
return "'"+res+"'"
802
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
803
return self > other
804
}
805
$comp_func += '' // source code
806
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
807
for(var $op in $comps){
819
// Copy static methods from unicode
820
var from_unicode = [
821
"title",
822
"capitalize",
823
"casefold",
824
"islower",
825
"isupper",
826
"istitle",
827
"isspace",
828
"isalpha",
829
"isalnum",
830
"isdecimal",
831
"isdigit",
832
"isnumeric",
833
"isidentifier",
834
"isprintable",
835
"lower",
836
"swapcase",
837
"upper"
838
]
839
for(var i=0;i<from_unicode.length;i++){
840
var name = from_unicode[i]
845
var $=$B.args("center",3,
846
{self:null, width:null, fillchar:null},
847
['self', 'width', 'fillchar'],
848
arguments,{fillchar:' '},null,null)
849
850
if($.width<=self.length) return self
868
if($.stop!==null){_slice = _b_.slice.$factory($.start, $.stop)}
869
else{_slice = _b_.slice.$factory($.start,$.self.length)}
871
}else{
872
if($.self.length+$.sub.length==0){return 1} // ''.count('') = 1
873
}
874
if($.sub.length==0){
875
if($.start==$.self.length){return 1} // 'aaa'.count('',3) = 1
876
else if(substr.length==0){return 0} // 'aaa'.count('',4) = 0
877
return substr.length+1
878
}
879
var n=0, pos=0
880
while(pos<substr.length){
881
pos=substr.indexOf($.sub,pos)
889
if(encoding=='rot13' || encoding=='rot_13'){
890
// Special case : returns a string
891
var res = ''
892
for(var i=0, _len = self.length; i<_len ; i++){
893
var char = self.charAt(i)
894
if(('a'<=char && char<='m') || ('A'<=char && char<='M')){
895
res += String.fromCharCode(String.charCodeAt(char)+13)
896
}else if(('m'<char && char<='z') || ('M'<char && char<='Z')){
897
res += String.fromCharCode(String.charCodeAt(char)-13)
898
}else{res += char}
899
}
900
return res
901
}
906
// Return True if the string ends with the specified suffix, otherwise
907
// return False. suffix can also be a tuple of suffixes to look for.
908
// With optional start, test beginning at that position. With optional
913
arguments,{start:0, end:null},null,null)
914
915
normalize_start_end($)
916
917
var suffixes = $.suffix
925
if(suffix.length<=s.length &&
926
s.substr(s.length-suffix.length)==suffix) return true
927
}
928
return false
929
}
930
932
var $ = $B.args('expandtabs', 2, {self:null, tabsize:null},
933
['self', 'tabsize'], arguments, {tabsize:8}, null, null)
934
var s=$B.$GetInt($.tabsize), col=0,pos=0,res=''
935
if(s==1){return self.replace(/\t/g,' ')}
936
while(pos<self.length){
937
var car = self.charAt(pos)
938
switch(car){
939
case '\t':
940
while(col%s > 0){res += ' ';col++}
941
break
942
case '\r':
943
case '\n':
944
res += car
945
col = 0
946
break
947
default:
948
res += car
949
col++
950
break
951
}
952
pos++
953
}
959
// Return the lowest index in the string where substring sub is found,
960
// such that sub is contained in the slice s[start:end]. Optional
961
// arguments start and end are interpreted as in slice notation.
973
var s = $.self.substring($.start,$.end)
974
975
if($.sub.length==0 && $.start==$.self.length){return $.self.length}
976
if(s.length+$.sub.length==0){return -1}
977
978
var last_search = s.length-$.sub.length
979
for(var i=0;i<=last_search;i++){
980
if(s.substr(i, $.sub.length)==$.sub){return $.start+i}
991
// a.x[z]!r:...
992
// the object has attributes :
993
// - name : "a"
994
// - name_ext : [".x", "[z]"]
995
// - conv : r
996
// - spec : rest of string after :
998
var elts = fmt_string.split(':'), name, conv, spec, name_ext=[]
999
if(elts.length==1){
1000
// No : in the string : it only contains a name
1001
name = fmt_string
1002
}else{
1003
// name is before the first ":"
1004
// spec (the format specification) is after
1005
name = elts[0]
1006
spec = elts.splice(1).join(':')
1007
}
1008
1009
var elts = name.split('!')
1010
if(elts.length>1){
1011
name=elts[0]
1012
conv=elts[1] // conversion flag
1013
if(conv.length!==1 || 'ras'.search(conv)==-1){
1018
if(name!==undefined){
1019
// "name' may be a subscription or attribute
1020
// Put these "extensions" in the list "name_ext"
1021
function name_repl(match){
1022
name_ext.push(match)
1023
return ''
1024
}
1025
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1026
name = name.replace(name_ext_re, name_repl)
1027
}
1036
1037
// Parse self to detect formatting instructions
1038
// Create a list "parts" made of sections of the string :
1039
// - elements of even rank are literal text
1040
// - elements of odd rank are "format objects", built from the
1041
// format strings in self (of the form {...})
1048
while(pos<_len){
1049
car = self.charAt(pos)
1050
if(car=='{' && self.charAt(pos+1)=='{'){
1051
// replace {{ by literal {
1052
text += '{'
1053
pos+=2
1054
}else if(car=='}' && self.charAt(pos+1)=='}'){
1055
// replace }} by literal }
1056
text += '}'
1057
pos+=2
1058
}else if(car=='{'){
1059
// Start of a format string
1061
// Store current literal text
1062
parts.push(text)
1063
1064
// Search the end of the format string, ie the } closing the
1065
// opening {. Since the string can contain other pairs {} for
1066
// nested formatting, an integer nb is incremented for each { and
1067
// decremented for each } ; the end of the format string is
1068
// reached when nb==0
1069
var end = pos+1, nb=1
1070
while(end<_len){
1071
if(self.charAt(end)=='{'){nb++;end++}
1072
else if(self.charAt(end)=='}'){
1073
nb--;end++
1074
if(nb==0){
1075
// End of format string
1076
var fmt_string = self.substring(pos+1, end-1)
1077
1078
// Create a format object, by function parse_format
1079
var fmt_obj = parse_format(fmt_string)
1080
1081
// If no name is explicitely provided, use the rank
1082
if(!fmt_obj.name){
1083
fmt_obj.name=rank+''
1084
rank++
1085
}
1089
// In this case, evaluate them using the positional
1090
// or keyword arguments passed to format()
1092
if(/\d+/.exec(key)){
1093
// If key is numeric, search in positional
1094
// arguments
1106
// Store format object in list "parts"
1107
parts.push(fmt_obj)
1108
text = ''
1109
break
1110
}
1111
}else{end++}
1117
if(text){parts.push(text)}
1118
// Apply formatting to the values passed to format()
1119
var res = '', fmt
1120
for(var i=0;i<parts.length;i++){
1121
// Literal text is added unchanged
1122
if(typeof parts[i]=='string'){res += parts[i];continue}
1124
// Format objects
1125
fmt = parts[i]
1126
if(fmt.name.charAt(0).search(/\d/)>-1){
1127
// Numerical reference : use positional arguments
1128
var pos = parseInt(fmt.name),
1133
}
1134
// If name has extensions (attributes or subscriptions)
1135
for(var j=0;j<fmt.name_ext.length;j++){
1136
var ext = fmt.name_ext[j]
1137
if(ext.charAt(0)=='.'){
1138
// Attribute
1139
value = _b_.getattr(value, ext.substr(1))
1140
}else{
1141
// Subscription
1142
var key = ext.substr(1, ext.length-2)
1143
// An index made of digits is transformed into an integer
1144
if(key.charAt(0).search(/\d/)>-1){key = parseInt(key)}
1145
value = _b_.getattr(value, '__getitem__')(key)
1146
}
1147
}
1149
// If the conversion flag is set, first call a function to convert
1150
// the value
1151
if(fmt.conv=='a'){value = _b_.ascii(value)}
1152
else if(fmt.conv=='r'){value = _b_.repr(value)}
1178
var $=$B.args('join',2,{self:null,iterable:null},
1179
['self', 'iterable'], arguments, {}, null, null)
1189
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1192
if(_b_.isinstance(err, _b_.StopIteration)){
1193
$B.current_exception = ce
1194
break
1195
}
1203
var $=$B.args('ljust',3,{self:null,width:null,fillchar:null},
1204
['self','width','fillchar'],arguments,{fillchar:' '},null,null)
1205
1206
if ($.width <= self.length) return self
1207
return self + $.fillchar.repeat($.width - self.length)
1211
var $=$B.args('lstrip',2,{self:null,chars:null},['self','chars'],
1212
arguments,{chars:_b_.None},null,null)
1213
if($.chars===_b_.None){return $.self.trimLeft()}
1214
for (var i = 0; i < $.self.length; i++) {
1215
if ($.chars.indexOf($.self.charAt(i)) === -1) {
1216
return $.self.substring(i);
1217
}
1218
}
1219
return '';
1224
var $ = $B.args('maketrans', 3, {x:null,y:null,z:null},['x','y','z'],
1225
arguments, {y:null, z:null}, null, null)
1228
// make 'default' translate table
1229
for(var i=0; i < 256; i++) _t.$numeric_dict[i]=i
1230
1231
if($.y===null && $.z===null){
1232
// If there is only one argument, it must be a dictionary mapping
1233
// Unicode ordinals (integers) or characters (strings of length 1) to
1234
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1235
// keys will then be converted to ordinals.
1236
if(!_b_.isinstance($.x, _b_.dict)){
1240
for(var i=0, len=items.length;i<len;i++){
1241
var k = items[i][0], v=items[i][1]
1242
if(!_b_.isinstance(k, _b_.int)){
1243
if(_b_.isinstance(k, _b_.str) && k.length==1){k = _b_.ord(k)}
1245
" is not int or 1-char string")}
1246
}
1247
if(v!==_b_.None && !_b_.isinstance(v, [_b_.int, _b_.str])){
1249
" is not None, integer or string")
1250
}
1251
_t.$numeric_dict[k] = v
1252
}
1253
return _t
1254
}else{
1256
// and in the resulting dictionary, each character in x will be mapped
1257
// to the character at the same position in y
1258
if(!(_b_.isinstance($.x, _b_.str) && _b_.isinstance($.y, _b_.str))){
1261
throw _b_.TypeError.$factory("maketrans arguments must be strings or same length")
1266
// characters will be mapped to None in the result
1267
if(!_b_.isinstance($.z, _b_.str)){
1269
}
1270
for(var i=0,len=$.z.length;i<len;i++){
1271
toNone[_b_.ord($.z.charAt(i))] = true
1272
}
1274
for(var i=0,len=$.x.length;i<len;i++){
1275
_t.$numeric_dict[_b_.ord($.x.charAt(i))] = _b_.ord($.y.charAt(i))
1276
}
1277
for(var k in toNone){
1278
_t.$numeric_dict[k] = _b_.None
1279
}
1280
return _t
1281
}
1282
}
1286
var $=$B.args('partition',2,{self:null,sep:null},['self','sep'],
1287
arguments,{},null,null)
1291
if (i== -1) return _b_.tuple.$factory([$.self, '', ''])
1292
return _b_.tuple.$factory([$.self.substring(0,i), $.sep,
1300
var re = new RegExp('\\'+specials.charAt(i),'g')
1301
str = str.replace(re, "\\"+specials.charAt(i))
1302
}
1303
return str
1304
}
1305
1310
var $ = $B.args('replace', 4, {self:null,old:null,$$new:null,count:null},
1311
['self','old','$$new','count'], arguments, {count:-1},null,null),
1312
count=$.count,self=$.self,old=$.old,_new=$.$$new
1316
// Validate instance type of 'count'
1317
if (!isinstance(count,[_b_.int,_b_.float])) {
1319
"' object cannot be interpreted as an integer");
1320
} else if (isinstance(count, _b_.float)) {
1325
if(old==''){
1326
if(_new==''){return self}
1327
if(self==''){return _new}
1328
var elts=self.split('')
1329
if(count>-1 && elts.length>=count){
1330
var rest = elts.slice(count).join('')
1331
return _new+elts.slice(0, count).join(_new)+rest
1332
}else{return _new+elts.join(_new)+_new}
1333
}else{
1337
var res = self, pos = -1
1338
if(old.length==0){
1339
var res = _new
1340
for(var i=0;i<elts.length;i++){
1341
res += elts[i]+_new
1342
}
1343
return res+rest
1344
}
1346
if (count < 0) count = res.length;
1347
while (count > 0) {
1348
pos = res.indexOf(old, pos);
1349
if (pos < 0)
1350
break;
1351
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1352
pos = pos + _new.length;
1353
count--;
1354
}
1355
return res;
1359
// Return the highest index in the string where substring sub is found,
1360
// such that sub is contained within s[start:end]. Optional arguments
1371
if($.sub.length==0){
1372
if($.start>$.self.length){return -1}
1373
else{return $.self.length}
1374
}
1375
var sublen = $.sub.length
1377
for(var i=$.end-sublen;i>=$.start;i--){
1378
if($.self.substr(i, sublen)==$.sub){return i}
1379
}
1380
return -1
1392
{self:null, width:null, fillchar:null},
1393
['self', 'width', 'fillchar'],
1394
arguments,{fillchar:' '},null,null)
1402
var $=$B.args('rpartition',2,{self:null,sep:null},['self','sep'],
1403
arguments,{},null,null)
1404
check_str($.sep)
1408
for(var i=0;i<items.length;i++){
1409
items[i]=items[i].split('').reverse().join('')
1410
}
1411
return items
1415
var $=$B.args("rsplit",3,{self:null,sep:null,maxsplit:null},
1416
['self','sep','maxsplit'],arguments,
1417
{sep:_b_.None, maxsplit:-1},null,null),
1421
var rev_str = reverse($.self),
1422
rev_sep = sep === _b_.None ? sep : reverse($.sep),
1425
// Reverse the list, then each string inside the list
1426
rev_res.reverse()
1427
for(var i=0;i<rev_res.length;i++){
1434
var $=$B.args('rstrip',2,{self:null,chars:null},['self','chars'],
1435
arguments,{chars:_b_.None},null,null)
1436
if($.chars===_b_.None){return $.self.trimRight()}
1437
for (var j = $.self.length-1; j >= 0; j--) {
1438
if ($.chars.indexOf($.self.charAt(j)) === -1) {
1439
return $.self.substring(0,j+1);
1440
}
1441
}
1442
return '';
1447
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1448
['self','sep','maxsplit'],arguments,
1449
{sep:_b_.None, maxsplit:-1},null,null)
1450
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
1457
var name = ''
1458
while(1){
1459
if(self.charAt(pos).search(/\s/)===-1){
1460
if(name===''){name=self.charAt(pos)}
1461
else{name+=self.charAt(pos)}
1462
}else{
1463
if(name!==''){
1464
res.push(name)
1465
if(maxsplit!==-1&&res.length===maxsplit+1){
1466
res.pop()
1467
res.push(name+self.substr(pos))
1468
return res
1469
}
1470
name=''
1471
}
1472
}
1473
pos++
1474
if(pos>self.length-1){
1475
if(name){res.push(name)}
1476
break
1477
}
1478
}
1479
return res
1480
}else{
1482
if(maxsplit==0){return [self]}
1483
while(pos<self.length){
1484
if(self.substr(pos,seplen)==sep){
1485
res.push(s)
1486
pos += seplen
1487
if(maxsplit>-1 && res.length>=maxsplit){
1488
res.push(self.substr(pos))
1489
return res
1490
}
1491
s= ''
1492
}else{
1493
s += self.charAt(pos)
1494
pos++
1503
var $=$B.args('splitlines',2,{self:null,keepends:null},
1504
['self','keepends'],arguments,{keepends:false},null,null)
1505
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
1516
while(pos<self.length){
1517
if(self.substr(pos,2)=='\r\n'){
1518
res.push(self.substring(start,pos+2))
1519
start = pos+2
1520
pos = start
1521
}else if(self.charAt(pos)=='\r' || self.charAt(pos)=='\n'){
1522
res.push(self.substring(start,pos+1))
1523
start = pos+1
1524
pos = start
1525
}else{pos++}
1526
}
1527
var rest = self.substr(start)
1528
if(rest){res.push(rest)}
1529
return res
1530
}else{
1531
var self = $.self.replace(/[\r\n]$/,'')
1532
return self.split(/\n|\r\n|\r/)
1533
}
1534
}
1537
// Return True if string starts with the prefix, otherwise return False.
1538
// prefix can also be a tuple of prefixes to look for. With optional
1539
// start, test string beginning at that position. With optional end,
1546
normalize_start_end($)
1547
1548
var prefixes = $.prefix
1549
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1551
var s = $.self.substring($.start,$.end)
1552
for(var i=0, _len_i = prefixes.length; i < _len_i;i++){
1553
prefix = prefixes[i]
1555
"endswith first arg must be str or a tuple of str, not int")}
1556
if(s.substr(0,prefix.length)==prefix) return true
1563
var $=$B.args('strip',2,{self:null,chars:null},['self','chars'],
1564
arguments,{chars:_b_.None},null,null)
1565
if($.chars===_b_.None){return $.self.trim()}
1566
for (var i = 0; i < $.self.length; i++) {
1567
if ($.chars.indexOf($.self.charAt(i)) === -1) {
1568
break;
1569
}
1570
}
1571
for (var j = $.self.length-1; j >= i; j--) {
1572
if ($.chars.indexOf($.self.charAt(j)) === -1) {
1573
break;
1574
}
1575
}
1576
return $.self.substring(i,j+1);
1592
var $=$B.args('zfill',2,{self:null,width:null},
1593
['self','width'],arguments,{},null,null)
1594
if ($.width <= self.length) {return self}
1595
switch(self.charAt(0)){
1596
case '+':
1597
case '-':
1598
return self.charAt(0)+'0'.repeat($.width-self.length)+self.substr(1)
1599
default:
1600
return '0'.repeat(width - self.length)+self
1601
}
1617
// class or its subclasses, but the attribute __str__ of the
1618
// class metaclass (usually "type") or its subclasses (usually
1619
// "object")
1620
// The metaclass is the attribute __class__ of the class dictionary
1624
var f = getattr(arg,'__str__')
1625
// XXX fix : if not better than object.__str__, try __repr__
1635
if($B.debug>1){console.log(err)}
1636
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1662
for(var $attr in str){
1663
if(typeof str[$attr]=='function'){
1664
StringSubclass[$attr]=(function(attr){
1686
// Function to parse the 2nd argument of format()
1687
$B.parse_format_spec = function(spec){
1697
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1698
// If the second char is also an alignment specifier, the
1699
// first char is the fill value
1700
this.fill = spec.charAt(0)
1701
this.align = spec.charAt(1)
1702
pos = 2
1703
}else{
1704
// The first character defines alignment : fill defaults to ' '
1705
this.align=aligns[align_pos];
1706
this.fill=' ';
1707
pos++
1708
}
1709
}else{
1710
align_pos = aligns.indexOf(spec.charAt(1))
1711
if(spec.charAt(1) && align_pos!=-1){
1712
// The second character defines alignment : fill is the first one
1713
this.align=aligns[align_pos]
1714
this.fill=spec.charAt(0)
1715
pos = 2
1716
}
1717
}
1718
var car = spec.charAt(pos)
1719
if(car=='+'||car=='-'||car==' '){
1720
this.sign=car;
1721
pos++;
1722
car=spec.charAt(pos);
1725
if(car=='0'){
1726
// sign-aware : equivalent to fill=0 and align=='='
1727
this.fill='0'
1728
this.align = '='
1729
pos++;car=spec.charAt(pos)
1730
}
1732
if(this.width===undefined){this.width=car}
1733
else{this.width+=car}
1734
pos++;car=spec.charAt(pos)
1736
if(this.width!==undefined){this.width=parseInt(this.width)}
1737
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1738
if(car=='.'){
1739
if(digits.indexOf(spec.charAt(pos+1))==-1){
1741
}
1742
this.precision = spec.charAt(pos+1)
1743
pos+=2;car=spec.charAt(pos)
1744
while(car && digits.indexOf(car)>-1){
1745
this.precision+=car;pos++;car=spec.charAt(pos)
1746
}
1747
this.precision = parseInt(this.precision)
1748
}
1749
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1750
if(pos!==spec.length){
1757
(this.align||'')+
1758
(this.sign||'')+
1759
(this.alternate ? '#' : '')+
1760
(this.sign_aware ? '0' : '')+
1761
(this.width || '')+
1762
(this.comma ? ',' : '')+
1763
(this.precision ? '.'+this.precision : '')+
1764
(this.type || '')
1765
}
1766
}
1767
1768
$B.format_width = function(s, fmt){
1769
if(fmt.width && s.length<fmt.width){
1770
var fill=fmt.fill || ' ', align = fmt.align || '<',
1771
missing = fmt.width-s.length
1772
switch(align){
1773
case '<':
1774
return s+fill.repeat(missing)
1775
case '>':
1776
return fill.repeat(missing)+s
1777
case '=':
1778
if('+-'.indexOf(s.charAt(0))>-1){
1779
return s.charAt(0)+fill.repeat(missing)+s.substr(1)
1791
function fstring_expression(){
1792
this.type = 'expression'
1793
this.expression = ''
1794
this.conversion = null
1795
this.fmt = null
1796
}
1797
1798
$B.parse_fstring = function(string){
1799
// Parse a f-string
1800
var elts = [],
1801
pos = 0,
1802
current = '',
1803
ctype = null,
1804
nb_braces = 0,
1805
car
1806
1807
while(pos<string.length){
1808
if(ctype===null){
1809
car = string.charAt(pos)
1810
if(car=='{'){
1811
if(string.charAt(pos+1)=='{'){
1812
ctype = 'string'
1813
current = '{'
1814
pos += 2
1815
}else{
1816
ctype = 'expression'
1817
nb_braces = 1
1818
pos++
1819
}
1820
}else if(car=='}'){
1821
if(string.charAt(pos+1)==car){
1822
ctype = 'string'
1823
current = '}'
1825
}else{
1826
throw Error(" f-string: single '}' is not allowed")
1827
}
1828
}else{
1829
ctype = 'string'
1830
current = car
1832
}
1833
}else if(ctype=='string'){
1834
// end of string is the first single { or end of string
1836
while(i<string.length){
1837
car = string.charAt(i)
1838
if(car=='{'){
1839
if(string.charAt(i+1)=='{'){
1840
current += '{'
1841
i+=2
1842
}else{
1843
elts.push(current)
1844
ctype = 'expression'
1845
pos = i+1
1846
break
1847
}
1848
}else if(car=='}'){
1849
if(string.charAt(i+1)==car){
1850
current += car
1851
i += 2
1852
}else{
1853
throw Error(" f-string: single '}' is not allowed")
1854
}
1855
}else{
1856
current += car
1857
i++
1858
}
1859
}
1860
pos = i+1
1861
}else{
1862
// End of expression is the } matching the opening {
1863
// There may be nested braces
1864
var i = pos,
1865
nb_braces = 1,
1886
}else if(car=='\\'){
1887
// backslash is not allowed in expressions
1888
throw Error("f-string expression part cannot include a" +
1889
" backslash")
1892
if(current.expression.length==0){
1893
throw Error("f-string: empty expression not allowed")
1894
}
1895
if('ars'.indexOf(string.charAt(i+1)) == -1){
1896
throw Error("f-string: invalid conversion character:" +
1897
" expected 's', 'r', or 'a'")
1898
}else{
1899
current.conversion = string.charAt(i+1)
1900
i += 2
1901
}
1902
}else if(car=='('){
1903
nb_paren++
1904
current.expression += car
1905
i++
1906
}else if(car==')'){
1907
nb_paren--
1908
current.expression += car
1909
i++
1910
}else if(car=='"'){
1911
// triple string ?
1912
if(string.substr(i, 3)=='"""'){
1913
var end = string.indexOf('"""', i+3)
1914
if(end==-1){throw Error("f-string: unterminated string")}
1915
else{
1916
var trs = string.substring(i, end+3)
1917
trs = trs.replace('\n', '\\n\\')
1918
current.expression += trs
1919
i = end+3
1920
}
1921
}else{
1922
var end = string.indexOf('"', i+1)
1923
if(end==-1){throw Error("f-string: unterminated string")}
1924
else{
1925
current.expression += string.substring(i, end+1)
1926
i = end+1
1927
}
1928
}
1929
}else if(nb_paren == 0 && car==':'){
1935
i++
1936
}
1937
}
1938
if(nb_braces>0){
1939
throw Error("f-string: expected '}'")
1940
}
1941
}
1942
}
1943
if(current.length>0){elts.push(current)}
1944
return elts
1945
}
1946