Permalink
Jan 14, 2015
Jan 14, 2015
Jan 1, 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
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
Feb 9, 2016
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Feb 9, 2016
Dec 3, 2015
Dec 3, 2015
Jan 6, 2016
Jan 1, 2015
Jan 1, 2015
Jan 30, 2016
Newer
100644
1702 lines (1535 sloc)
54.9 KB
13
function normalize_start_end($){
14
if($.start===null||$.start===_b_.None){$.start = 0}
15
else if($.start<0){$.start += $.self.length; $.start=Math.max(0, $.start)}
16
if($.end===null||$.end===_b_.None){$.end = $.self.length}
17
else if($.end<0){$.end += $.self.length; $.end=Math.max(0, $.end)}
18
19
if(!isinstance($.start,_b_.int)||!isinstance($.end,_b_.int)){
20
throw _b_.TypeError(
21
"slice indices must be integers or None or have an __index__ method")}
22
23
}
24
25
function reverse(s){
26
// Reverse a string
27
return s.split('').reverse().join('')
28
}
29
30
function check_str(obj){
31
if(!_b_.isinstance(obj,str)){throw _b_.TypeError("can't convert '"+
32
$B.get_class(obj).__name__+"' object to str implicitely")}
35
$StringDict.__add__ = function(self,other){
36
if(!(typeof other==="string")){
37
try{return getattr(other,'__radd__')(self)}
38
catch(err){throw _b_.TypeError(
39
"Can't convert "+$B.get_class(other).__name__+" to str implicitely")}
40
}
41
return self+other
42
}
43
44
$StringDict.__contains__ = function(self,item){
45
if(!(typeof item==="string")){throw _b_.TypeError(
46
"'in <string>' requires string as left operand, not "+item.__class__)}
47
var nbcar = item.length
48
if(nbcar==0) return true // a string contains the empty string
49
if(self.length==0) return nbcar==0
51
if(self.substr(i,nbcar)==item) return true
52
}
53
return false
54
}
55
56
$StringDict.__delitem__ = function(){
57
throw _b_.TypeError("'str' object doesn't support item deletion")
58
}
59
60
// __dir__must be assigned explicitely because attribute resolution for builtin
61
// classes doesn't use __mro__
62
$StringDict.__dir__ = $ObjectDict.__dir__
63
64
$StringDict.__eq__ = function(self,other){
65
if(other===undefined){ // compare object "self" to class "str"
66
return self===str
67
}
68
if (_b_.isinstance(other, _b_.str)) {
69
return other.valueOf() == self.valueOf()
70
}
74
function preformat(self, fmt){
75
if(fmt.empty){return _b_.str(self)}
76
if(fmt.type && fmt.type!='s'){
77
throw _b_.ValueError("Unknown format code '"+fmt.type+
78
"' for object of type 'str'")
79
}
80
return self
81
}
82
83
$StringDict.__format__ = function(self, format_spec) {
84
var fmt = new $B.parse_format_spec(format_spec)
85
// For strings, alignment default to left
86
fmt.align = fmt.align || '<'
87
return $B.format_width(preformat(self, fmt), fmt)
88
}
89
90
$StringDict.__getitem__ = function(self,arg){
91
if(isinstance(arg,_b_.int)){
92
var pos = arg
93
if(arg<0) pos+=self.length
94
if(pos>=0 && pos<self.length) return self.charAt(pos)
95
throw _b_.IndexError('string index out of range')
96
}
97
if(isinstance(arg,slice)) {
98
var s=_b_.slice.$dict.$conv_for_seq(arg, self.length),
99
start=s.start, stop=s.stop, step=s.step
100
var res = '',i=null
101
if(step>0){
102
if(stop<=start) return ''
103
for(var i=start;i<stop;i+=step) res += self.charAt(i)
104
} else {
105
if(stop>=start) return ''
107
}
108
return res
109
}
110
if(isinstance(arg,bool)) return self.__getitem__(_b_.int(arg))
115
if (self === undefined) {
116
return $StringDict.__hashvalue__ || $B.$py_next_hash-- // for hash of string type (not instance of string)
117
}
118
119
//http://stackoverflow.com/questions/2909106/python-whats-a-correct-and-good-way-to-implement-hash
120
// this implementation for strings maybe good enough for us..
121
122
var hash=1;
124
hash=(101*hash + self.charCodeAt(i)) & 0xFFFFFFFF
125
}
126
127
return hash
128
}
129
130
$StringDict.__init__ = function(self,arg){
131
self.valueOf = function(){return arg}
132
self.toString = function(){return arg}
134
}
135
136
var $str_iterator = $B.$iterator_class('str_iterator')
137
$StringDict.__iter__ = function(self){
138
var items = self.split('') // list of all characters in string
139
return $B.$iterator(items,$str_iterator)
140
}
141
142
$StringDict.__len__ = function(self){return self.length}
143
146
var kwarg_key = new RegExp('([^\\)]*)\\)')
147
148
var NotANumber = function() {
149
this.name = 'NotANumber'
150
}
151
152
var number_check=function(s) {
153
if(!isinstance(s,[_b_.int,_b_.float])){
154
throw new NotANumber()
155
}
156
}
157
158
var get_char_array = function(size, char) {
159
if (size <= 0)
160
return ''
161
return new Array(size + 1).join(char)
162
}
163
164
var format_padding = function(s, flags, minus_one) {
165
var padding = flags.padding
166
if (!padding) { // undefined
167
return s
168
}
169
s = s.toString()
170
padding = parseInt(padding, 10)
171
if (minus_one) { // numeric formatting where sign goes in front of padding
172
padding -= 1
173
}
174
if (!flags.left) {
175
return get_char_array(padding - s.length, flags.pad_char) + s
176
} else {
177
// left adjusted
178
return s + get_char_array(padding - s.length, flags.pad_char)
179
}
180
}
181
182
var format_int_precision = function(val, flags) {
183
var precision = flags.precision
184
if (!precision) {
185
return val.toString()
186
}
187
precision = parseInt(precision, 10)
188
var s
189
if (val.__class__ === $B.LongInt.$dict) {
190
s=$B.LongInt.$dict.to_base(val, 10)
191
} else {
192
s=val.toString()
193
}
194
var sign = s[0]
195
if (s[0] === '-') {
196
return '-' + get_char_array(precision - s.length + 1, '0') + s.slice(1)
197
}
198
return get_char_array(precision - s.length, '0') + s
199
}
200
201
var format_float_precision = function(val, upper, flags, modifier) {
202
var precision = flags.precision
203
// val is a float
204
if (isFinite(val)) {
205
val = modifier(val, precision, flags, upper)
206
return val
207
}
208
if (val === Infinity) {
209
val = 'inf'
210
} else if (val === -Infinity) {
211
val = '-inf'
212
} else {
213
val = 'nan'
214
}
215
if (upper) {
216
return val.toUpperCase()
217
}
218
return val
220
}
221
222
var format_sign = function(val, flags) {
223
if (flags.sign) {
224
if (val >= 0) {
225
return "+"
227
} else if (flags.space) {
228
if (val >= 0) {
229
return " "
230
}
231
}
232
return ""
233
}
235
var str_format = function(val, flags) {
236
// string format supports left and right padding
237
flags.pad_char = " " // even if 0 padding is defined, don't use it
238
return format_padding(str(val), flags)
239
}
243
if (val.__class__ === $B.LongInt.$dict) {
244
val = $B.LongInt.$dict.to_base(val, 10)
245
} else {
246
val = parseInt(val)
247
}
248
249
var s = format_int_precision(val, flags)
250
if (flags.pad_char === '0') {
251
if (val < 0) {
252
s = s.substring(1)
253
return '-' + format_padding(s, flags, true)
254
}
255
var sign = format_sign(val, flags)
256
if (sign !== '') {
257
return sign + format_padding(s, flags, true)
258
}
259
}
260
261
return format_padding(format_sign(val, flags) + s, flags)
262
}
264
var repr_format = function(val, flags) {
265
flags.pad_char = " " // even if 0 padding is defined, don't use it
266
return format_padding(repr(val), flags)
267
}
269
var ascii_format = function(val, flags) {
270
flags.pad_char = " " // even if 0 padding is defined, don't use it
271
return format_padding(ascii(val), flags)
272
}
274
// converts to val to float and sets precision if missing
275
var _float_helper = function(val, flags) {
276
number_check(val)
277
if (!flags.precision) {
278
if (!flags.decimal_point) {
279
flags.precision = 6
280
} else {
281
flags.precision = 0
282
}
283
} else {
284
flags.precision = parseInt(flags.precision, 10)
285
validate_precision(flags.precision)
286
}
287
return parseFloat(val)
288
}
290
// used to capture and remove trailing zeroes
291
var trailing_zeros = /(.*?)(0+)([eE].*)/
292
var leading_zeros = /\.(0*)/
293
var trailing_dot = /\.$/
295
var validate_precision = function(precision) {
296
// force precision to limits of javascript
298
}
299
300
// gG
301
var floating_point_format = function(val, upper, flags) {
302
val = _float_helper(val, flags)
303
var v = val.toString()
304
var v_len = v.length
305
var dot_idx = v.indexOf('.')
306
if (dot_idx < 0) {
307
dot_idx = v_len
308
}
309
if (val < 1 && val > -1) {
310
var zeros = leading_zeros.exec(v)
311
var numzeros
312
if (zeros) {
313
numzeros = zeros[1].length
314
} else {
315
numzeros = 0
316
}
317
if (numzeros >= 4) {
318
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
319
if (!flags.alternate) {
320
var trl = trailing_zeros.exec(val)
321
if (trl) {
322
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
328
}
329
return format_padding(val, flags)
330
}
331
flags.precision += numzeros
332
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
333
function(val, precision) {
334
val = val.toFixed(min(precision, v_len - dot_idx) + numzeros)
335
}), flags)
336
}
337
338
if (dot_idx > flags.precision) {
339
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
340
if (!flags.alternate) {
341
var trl = trailing_zeros.exec(val)
342
if (trl) {
343
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
344
}
345
} else {
346
if (flags.precision <= 1) {
347
val = val[0] + '.' + val.substring(1)
348
}
349
}
350
return format_padding(val, flags)
351
}
352
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
353
function(val, precision) {
354
if (!flags.decimal_point) {
355
precision = min(v_len - 1, 6)
356
} else if (precision > v_len) {
357
if (!flags.alternate) {
358
precision = v_len
360
}
361
if (precision < dot_idx) {
362
precision = dot_idx
363
}
364
return val.toFixed(precision - dot_idx)
365
}), flags)
366
}
368
var _floating_g_exp_helper = function(val, precision, flags, upper) {
369
if (precision) {
370
--precision
371
}
372
val = val.toExponential(precision)
373
// pad exponent to two digits
374
var e_idx = val.lastIndexOf('e')
375
if (e_idx > val.length - 4) {
376
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
377
}
378
if (upper) {
379
return val.toUpperCase()
380
}
381
return val
382
}
383
384
// fF
385
var floating_point_decimal_format = function(val, upper, flags) {
386
val = _float_helper(val, flags)
387
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
388
function(val, precision, flags) {
389
val = val.toFixed(precision)
390
if (precision === 0 && flags.alternate) {
391
val += '.'
392
}
393
return val
394
}), flags)
395
}
396
397
var _floating_exp_helper = function(val, precision, flags, upper) {
398
val = val.toExponential(precision)
399
// pad exponent to two digits
400
var e_idx = val.lastIndexOf('e')
401
if (e_idx > val.length - 4) {
402
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
403
}
404
if (upper) {
405
return val.toUpperCase()
406
}
407
return val
408
}
409
410
// eE
411
var floating_point_exponential_format = function(val, upper, flags) {
412
val = _float_helper(val, flags)
413
414
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_exp_helper), flags)
415
}
416
417
var signed_hex_format = function(val, upper, flags) {
420
421
if (val.__class__ === $B.LongInt.$dict) {
422
ret=$B.LongInt.$dict.to_base(val, 16)
423
} else {
424
ret = parseInt(val)
425
ret = ret.toString(16)
426
}
427
ret = format_int_precision(ret, flags)
428
if (upper) {
429
ret = ret.toUpperCase()
430
}
431
if (flags.pad_char === '0') {
432
if (val < 0) {
433
ret = ret.substring(1)
434
ret = '-' + format_padding(ret, flags, true)
435
}
436
var sign = format_sign(val, flags)
437
if (sign !== '') {
438
ret = sign + format_padding(ret, flags, true)
440
}
441
442
if (flags.alternate) {
443
if (ret.charAt(0) === '-') {
444
if (upper) {
445
ret = "-0X" + ret.slice(1)
446
} else {
447
ret = "-0x" + ret.slice(1)
448
}
449
} else {
450
if (upper) {
451
ret = "0X" + ret
452
} else {
453
ret = "0x" + ret
454
}
455
}
456
}
457
return format_padding(format_sign(val, flags) + ret, flags)
458
}
462
var ret
463
464
if (val.__class__ === $B.LongInt.$dict) {
465
ret = $B.LongInt.$dict.to_base(8)
466
} else {
467
ret = parseInt(val)
468
ret = ret.toString(8)
469
}
470
473
if (flags.pad_char === '0') {
474
if (val < 0) {
475
ret = ret.substring(1)
476
ret = '-' + format_padding(ret, flags, true)
477
}
478
var sign = format_sign(val, flags)
479
if (sign !== '') {
480
ret = sign + format_padding(ret, flags, true)
481
}
483
484
if (flags.alternate) {
485
if (ret.charAt(0) === '-') {
486
ret = "-0o" + ret.slice(1)
487
} else {
488
ret = "0o" + ret
489
}
491
return format_padding(ret, flags)
492
}
493
494
var single_char_format = function(val, flags) {
495
if(isinstance(val,str) && val.length==1) return val
496
try {
497
val = _b_.int(val) // yes, floats are valid (they are cast to int)
498
} catch (err) {
499
throw _b_.TypeError('%c requires int or char')
500
}
501
return format_padding(chr(val), flags)
502
}
503
504
var num_flag = function(c, flags) {
505
if (c === '0' && !flags.padding && !flags.decimal_point && !flags.left) {
506
flags.pad_char = '0'
507
return
508
}
509
if (!flags.decimal_point) {
510
flags.padding = (flags.padding || "") + c
511
} else {
512
flags.precision = (flags.precision || "") + c
513
}
514
}
515
516
var decimal_point_flag = function(val, flags) {
517
if (flags.decimal_point) {
518
// can only have one decimal point
519
throw new UnsupportedChar()
520
}
521
flags.decimal_point = true
522
}
523
524
var neg_flag = function(val, flags) {
525
flags.pad_char = ' ' // overrides '0' flag
526
flags.left = true
527
}
528
529
var space_flag = function(val, flags) {
530
flags.space = true
531
}
532
533
var sign_flag = function(val, flags) {
534
flags.sign = true
535
}
536
537
var alternate_flag = function(val, flags) {
538
flags.alternate = true
539
}
540
542
's': str_format,
543
'd': num_format,
544
'i': num_format,
545
'u': num_format,
546
'o': octal_format,
547
'r': repr_format,
548
'a': ascii_format,
549
'g': function(val, flags) {return floating_point_format(val, false, flags)},
550
'G': function(val, flags) {return floating_point_format(val, true, flags)},
551
'f': function(val, flags) {return floating_point_decimal_format(val, false, flags)},
552
'F': function(val, flags) {return floating_point_decimal_format(val, true, flags)},
553
'e': function(val, flags) {return floating_point_exponential_format(val, false, flags)},
554
'E': function(val, flags) {return floating_point_exponential_format(val, true, flags)},
555
'x': function(val, flags) {return signed_hex_format(val, false, flags)},
556
'X': function(val, flags) {return signed_hex_format(val, true, flags)},
557
'c': single_char_format,
558
'0': function(val, flags) {return num_flag('0', flags)},
559
'1': function(val, flags) {return num_flag('1', flags)},
560
'2': function(val, flags) {return num_flag('2', flags)},
561
'3': function(val, flags) {return num_flag('3', flags)},
562
'4': function(val, flags) {return num_flag('4', flags)},
563
'5': function(val, flags) {return num_flag('5', flags)},
564
'6': function(val, flags) {return num_flag('6', flags)},
565
'7': function(val, flags) {return num_flag('7', flags)},
566
'8': function(val, flags) {return num_flag('8', flags)},
567
'9': function(val, flags) {return num_flag('9', flags)},
568
'-': neg_flag,
569
' ': space_flag,
570
'+': sign_flag,
571
'.': decimal_point_flag,
572
'#': alternate_flag
573
}
574
575
// exception thrown when an unsupported char is encountered in legacy format
576
var UnsupportedChar = function() {
577
this.name = "UnsupportedChar"
578
}
579
582
var length = self.length,
583
pos = 0 |0,
584
argpos = null,
585
getitem
586
if (_b_.isinstance(args, _b_.tuple)) {
594
++pos
595
var rslt = kwarg_key.exec(s.substring(newpos))
596
if (!rslt) {
597
throw _b_.ValueError("incomplete format key")
598
}
599
var key = rslt[1]
600
newpos += rslt[0].length
601
try {
603
} catch(err) {
604
if (err.name === "KeyError") {
605
throw err
606
}
607
throw _b_.TypeError("format requires a mapping")
608
}
621
self = args[argpos++]
622
if(self===undefined){
623
throw _b_.TypeError("not enough arguments for format string")
629
// todo: get flags, type
630
// todo: string value based on flags, type, value
631
var flags = {'pad_char': ' '}
632
do {
639
if (ret !== undefined) {
640
return ret
641
}
642
++newpos
643
}
644
} catch (err) {
645
if (err.name === "UnsupportedChar") {
646
invalid_char = s[newpos]
647
if (invalid_char === undefined) {
648
throw _b_.ValueError("incomplete format")
649
}
650
throw _b_.ValueError("unsupported format character '" + invalid_char +
651
"' (0x" + invalid_char.charCodeAt(0).toString(16) + ") at index " + newpos)
652
} else if (err.name === "NotANumber") {
653
var try_char = s[newpos]
660
}
661
} else {
662
cls = cls.__name__
663
}
664
throw _b_.TypeError("%" + try_char + " format: a number is required, not " + cls)
665
} else {
666
throw err
667
}
690
}
691
}
692
} else {
693
// % at end of string
694
throw _b_.ValueError("incomplete format")
695
}
696
pos = newpos + 1
697
} while (pos < length)
698
699
if(argpos!==null){
700
if(args.length>argpos){
701
throw _b_.TypeError('not enough arguments for format string')
702
}else if(args.length<argpos){
703
throw _b_.TypeError('not all arguments converted during string formatting')
704
}
705
}else if(nbph==0){
706
throw _b_.TypeError('not all arguments converted during string formatting')
707
}
710
711
$StringDict.__mro__ = [$StringDict,$ObjectDict]
712
713
$StringDict.__mul__ = function(self,other){
714
var $=$B.args('__mul__',2,{self:null,other:null},['self','other'],
715
arguments,{},null,null)
716
if(!isinstance(other,_b_.int)){throw _b_.TypeError(
717
"Can't multiply sequence by non-int of type '"+
718
$B.get_class(other).__name__+"'")}
719
$res = ''
720
for(var i=0;i<other;i++){$res+=self.valueOf()}
721
return $res
722
}
723
724
$StringDict.__ne__ = function(self,other){return other!==self.valueOf()}
725
726
$StringDict.__repr__ = function(self){
727
var res = self.replace(/\n/g,'\\\\n')
728
// escape the escape char
729
res = res.replace(/\\/g, '\\\\')
730
if(res.search('"')==-1 && res.search("'")==-1){
731
return "'"+res+"'"
740
$StringDict.__setattr__ = function(self,attr,value){return setattr(self,attr,value)}
741
742
$StringDict.__setitem__ = function(self,attr,value){
743
throw _b_.TypeError("'str' object does not support item assignment")
744
}
745
$StringDict.__str__ = function(self){
746
if(self===undefined) return "<class 'str'>"
747
return self.toString()
748
}
749
$StringDict.toString = function(){return 'string!'}
750
751
// generate comparison methods
752
var $comp_func = function(self,other){
753
if(typeof other !=="string"){throw _b_.TypeError(
754
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
755
return self > other
756
}
757
$comp_func += '' // source code
758
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
759
for(var $op in $comps){
760
eval("$StringDict.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op))
761
}
762
763
// add "reflected" methods
764
$B.make_rmethods($StringDict)
765
766
// unsupported operations
767
var $notimplemented = function(self,other){
768
throw NotImplementedError("OPERATOR not implemented for class str")
769
}
770
771
$StringDict.title = unicode.title;
772
$StringDict.capitalize = unicode.capitalize;
773
$StringDict.casefold = unicode.casefold;
774
$StringDict.islower = unicode.islower;
775
$StringDict.isupper = unicode.isupper;
776
$StringDict.istitle = unicode.istitle;
777
$StringDict.isspace = unicode.isspace;
778
$StringDict.isalpha = unicode.isalpha;
779
$StringDict.isalnum = unicode.isalnum;
780
$StringDict.isdecimal = unicode.isdecimal;
781
$StringDict.isdigit = unicode.isdigit;
782
$StringDict.isnumeric = unicode.isnumeric;
783
$StringDict.isidentifier = unicode.isidentifier;
784
$StringDict.isprintable = unicode.isprintable;
785
$StringDict.lower = unicode.lower;
786
$StringDict.swapcase = unicode.swapcase;
787
$StringDict.upper = unicode.upper;
790
var $=$B.args("center",3,
791
{self:null, width:null, fillchar:null},
792
['self', 'width', 'fillchar'],
793
arguments,{fillchar:' '},null,null)
794
795
if($.width<=self.length) return self
804
$StringDict.count = function(){
805
var $ = $B.args('count', 4, {self:null, sub:null, start:null, stop:null},
810
var substr = $.self
811
if($.start!==null){
812
var _slice
813
if($.stop!==null){_slice = _b_.slice($.start, $.stop)}
814
else{_slice = _b_.slice($.start,$.self.length)}
815
substr = $StringDict.__getitem__.apply(null, [$.self].concat(_slice))
816
}else{
817
if($.self.length+$.sub.length==0){return 1} // ''.count('') = 1
818
}
819
if($.sub.length==0){
820
if($.start==$.self.length){return 1} // 'aaa'.count('',3) = 1
821
else if(substr.length==0){return 0} // 'aaa'.count('',4) = 0
822
return substr.length+1
823
}
824
var n=0, pos=0
825
while(pos<substr.length){
826
pos=substr.indexOf($.sub,pos)
828
}
829
return n
830
}
831
832
$StringDict.encode = function(self, encoding) {
833
if (encoding === undefined) encoding='utf-8'
834
if(encoding=='rot13' || encoding=='rot_13'){
835
// Special case : returns a string
836
var res = ''
837
for(var i=0, _len = self.length; i<_len ; i++){
838
var char = self.charAt(i)
839
if(('a'<=char && char<='m') || ('A'<=char && char<='M')){
840
res += String.fromCharCode(String.charCodeAt(char)+13)
841
}else if(('m'<char && char<='z') || ('M'<char && char<='Z')){
842
res += String.fromCharCode(String.charCodeAt(char)-13)
843
}else{res += char}
844
}
845
return res
846
}
851
// Return True if the string ends with the specified suffix, otherwise
852
// return False. suffix can also be a tuple of suffixes to look for.
853
// With optional start, test beginning at that position. With optional
854
// end, stop comparing at that position.
856
{self:null, suffix:null, start:null, end:null},
857
['self', 'suffix', 'start', 'end'],
858
arguments,{start:0, end:null},null,null)
859
860
normalize_start_end($)
861
862
var suffixes = $.suffix
868
if(!_b_.isinstance(suffix, str)){throw _b_.TypeError(
869
"endswith first arg must be str or a tuple of str, not int")}
870
if(suffix.length<=s.length &&
871
s.substr(s.length-suffix.length)==suffix) return true
872
}
873
return false
874
}
875
876
$StringDict.expandtabs = function(self, tabsize) {
877
var $ = $B.args('expandtabs', 2, {self:null, tabsize:null},
878
['self', 'tabsize'], arguments, {tabsize:8}, null, null)
879
var s=$B.$GetInt($.tabsize), col=0,pos=0,res=''
880
if(s==1){return self.replace(/\t/g,' ')}
881
while(pos<self.length){
882
var car = self.charAt(pos)
883
switch(car){
884
case '\t':
885
while(col%s > 0){res += ' ';col++}
886
break
887
case '\r':
888
case '\n':
889
res += car
890
col = 0
891
break
892
default:
893
res += car
894
col++
895
break
896
}
897
pos++
898
}
899
900
return res
904
// Return the lowest index in the string where substring sub is found,
905
// such that sub is contained in the slice s[start:end]. Optional
906
// arguments start and end are interpreted as in slice notation.
907
// Return -1 if sub is not found.
916
throw _b_.TypeError(
917
"slice indices must be integers or None or have an __index__ method")}
918
var s = $.self.substring($.start,$.end)
919
920
if($.sub.length==0 && $.start==$.self.length){return $.self.length}
921
if(s.length+$.sub.length==0){return -1}
922
923
var last_search = s.length-$.sub.length
924
for(var i=0;i<=last_search;i++){
925
if(s.substr(i, $.sub.length)==$.sub){return $.start+i}
934
// Parse a "format string", as described in the Python documentation
935
// Return a format object. For the format string
936
// a.x[z]!r:...
937
// the object has attributes :
938
// - name : "a"
939
// - name_ext : [".x", "[z]"]
940
// - conv : r
941
// - spec : rest of string after :
943
var elts = fmt_string.split(':'), name, conv, spec, name_ext=[]
944
if(elts.length==1){
945
// No : in the string : it only contains a name
946
name = fmt_string
947
}else{
948
// name is before the first ":"
949
// spec (the format specification) is after
950
name = elts[0]
951
spec = elts.splice(1).join(':')
952
}
953
954
var elts = name.split('!')
955
if(elts.length>1){
956
name=elts[0]
957
conv=elts[1] // conversion flag
958
if(conv.length!==1 || 'ras'.search(conv)==-1){
959
throw _b_.ValueError('wrong conversion flag '+conv)
960
}
961
}
963
if(name!==undefined){
964
// "name' may be a subscription or attribute
965
// Put these "extensions" in the list "name_ext"
966
function name_repl(match){
967
name_ext.push(match)
968
return ''
969
}
970
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
971
name = name.replace(name_ext_re, name_repl)
972
}
981
arguments, {}, 'args', 'kw')
982
983
// Parse self to detect formatting instructions
984
// Create a list "parts" made of sections of the string :
985
// - elements of even rank are literal text
986
// - elements of odd rank are "format objects", built from the
987
// format strings in self (of the form {...})
988
var pos=0, _len=self.length, car, text='', parts=[], rank=0, defaults={}
989
990
while(pos<_len){
991
car = self.charAt(pos)
992
if(car=='{' && self.charAt(pos+1)=='{'){
993
// replace {{ by literal {
994
text += '{'
995
pos+=2
996
}else if(car=='}' && self.charAt(pos+1)=='}'){
997
// replace }} by literal }
998
text += '}'
999
pos+=2
1000
}else if(car=='{'){
1001
// Start of a format string
1002
1003
// Store current literal text
1004
parts.push(text)
1005
1006
// Search the end of the format string, ie the } closing the
1007
// opening {. Since the string can contain other pairs {} for
1008
// nested formatting, an integer nb is incremented for each { and
1009
// decremented for each } ; the end of the format string is
1010
// reached when nb==0
1011
var end = pos+1, nb=1
1012
while(end<_len){
1013
if(self.charAt(end)=='{'){nb++;end++}
1014
else if(self.charAt(end)=='}'){
1015
nb--;end++
1016
if(nb==0){
1017
// End of format string
1018
var fmt_string = self.substring(pos+1, end-1)
1019
1020
// Create a format object, by function parse_format
1021
var fmt_obj = parse_format(fmt_string)
1022
1023
// If no name is explicitely provided, use the rank
1024
if(!fmt_obj.name){
1025
fmt_obj.name=rank+''
1026
rank++
1027
}
1031
// In this case, evaluate them using the positional
1032
// or keyword arguments passed to format()
1034
if(/\d+/.exec(key)){
1035
// If key is numeric, search in positional
1036
// arguments
1037
return _b_.tuple.$dict.__getitem__($.args,
1038
parseInt(key))
1039
}else{
1040
// Else try in keyword arguments
1041
return _b_.dict.$dict.__getitem__($.kw, key)
1042
}
1043
}
1044
fmt_obj.spec = fmt_obj.spec.replace(/\{(.+?)\}/g,
1045
replace_nested)
1046
}
1047
1048
// Store format object in list "parts"
1049
parts.push(fmt_obj)
1050
text = ''
1051
break
1052
}
1053
}else{end++}
1055
if(nb>0){throw ValueError("wrong format "+self)}
1056
pos = end
1057
}else{text += car;pos++}
1061
// Apply formatting to the values passed to format()
1062
var res = '', fmt
1063
for(var i=0;i<parts.length;i++){
1064
// Literal text is added unchanged
1065
if(typeof parts[i]=='string'){res += parts[i];continue}
1066
1067
// Format objects
1068
fmt = parts[i]
1069
if(fmt.name.charAt(0).search(/\d/)>-1){
1070
// Numerical reference : use positional arguments
1071
var pos = parseInt(fmt.name),
1072
value = _b_.tuple.$dict.__getitem__($.args, pos)
1073
}else{
1074
// Use keyword arguments
1075
var value = _b_.dict.$dict.__getitem__($.kw, fmt.name)
1076
}
1077
// If name has extensions (attributes or subscriptions)
1078
for(var j=0;j<fmt.name_ext.length;j++){
1079
var ext = fmt.name_ext[j]
1080
if(ext.charAt(0)=='.'){
1081
// Attribute
1082
value = _b_.getattr(value, ext.substr(1))
1083
}else{
1084
// Subscription
1085
var key = ext.substr(1, ext.length-2)
1086
// An index made of digits is transformed into an integer
1087
if(key.charAt(0).search(/\d/)>-1){key = parseInt(key)}
1088
value = _b_.getattr(value, '__getitem__')(key)
1089
}
1090
}
1091
// If the conversion flag is set, first call a function to convert
1092
// the value
1093
if(fmt.conv=='a'){value = _b_.ascii(value)}
1094
else if(fmt.conv=='r'){value = _b_.repr(value)}
1095
else if(fmt.conv=='s'){value = _b_.str(value)}
1096
1097
// Call attribute __format__ to perform the actual formatting
1098
res += _b_.getattr(value, '__format__')(fmt.spec)
1101
}
1102
1103
$StringDict.format_map = function(self) {
1104
throw NotImplementedError("function format_map not implemented yet");
1105
}
1106
1107
$StringDict.index = function(self){
1108
// Like find(), but raise ValueError when the substring is not found.
1110
if(res===-1) throw _b_.ValueError("substring not found")
1111
return res
1112
}
1113
1114
$StringDict.join = function(){
1115
var $=$B.args('join',2,{self:null,iterable:null},
1116
['self', 'iterable'], arguments, {}, null, null)
1117
1118
var iterable=_b_.iter($.iterable)
1119
var res = [],count=0
1123
if(!isinstance(obj2,str)){throw _b_.TypeError(
1124
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1134
$StringDict.ljust = function(self) {
1135
var $=$B.args('ljust',3,{self:null,width:null,fillchar:null},
1136
['self','width','fillchar'],arguments,{fillchar:' '},null,null)
1137
1138
if ($.width <= self.length) return self
1139
return self + $.fillchar.repeat($.width - self.length)
1143
var $=$B.args('lstrip',2,{self:null,chars:null},['self','chars'],
1144
arguments,{chars:_b_.None},null,null)
1145
if($.chars===_b_.None){return $.self.replace(/^\s+/,'')}
1146
return $.self.replace(new RegExp("^["+$.chars+"]*"),"")
1150
$StringDict.maketrans = function() {
1151
var $ = $B.args('maketrans', 3, {x:null,y:null,z:null},['x','y','z'],
1152
arguments, {y:null, z:null}, null, null)
1153
1154
var _t=_b_.dict()
1155
// make 'default' translate table
1156
for(var i=0; i < 256; i++) _t.$numeric_dict[i]=i
1157
1158
if($.y===null && $.z===null){
1159
// If there is only one argument, it must be a dictionary mapping
1160
// Unicode ordinals (integers) or characters (strings of length 1) to
1161
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1162
// keys will then be converted to ordinals.
1163
if(!_b_.isinstance($.x, _b_.dict)){
1164
throw _b_.TypeError('maketrans only argument must be a dict')
1165
}
1166
var items = _b_.list(_b_.dict.$dict.items($.x))
1167
for(var i=0, len=items.length;i<len;i++){
1168
var k = items[i][0], v=items[i][1]
1169
if(!_b_.isinstance(k, _b_.int)){
1170
if(_b_.isinstance(k, _b_.str) && k.length==1){k = _b_.ord(k)}
1171
else{throw _b_.TypeError("dictionary key "+k+
1172
" is not int or 1-char string")}
1173
}
1174
if(v!==_b_.None && !_b_.isinstance(v, [_b_.int, _b_.str])){
1175
throw _b_.TypeError("dictionary value "+v+
1176
" is not None, integer or string")
1177
}
1178
_t.$numeric_dict[k] = v
1179
}
1180
return _t
1181
}else{
1182
// If there are two arguments, they must be strings of equal length,
1183
// and in the resulting dictionary, each character in x will be mapped
1184
// to the character at the same position in y
1185
if(!(_b_.isinstance($.x, _b_.str) && _b_.isinstance($.y, _b_.str))){
1186
throw _b_.TypeError("maketrans arguments must be strings")
1187
}else if($.x.length!==$.y.length){
1188
throw _b_.TypeError("maketrans arguments must be strings or same length")
1189
}else{
1190
var toNone = {}
1191
if($.z!==null){
1192
// If there is a third argument, it must be a string, whose
1193
// characters will be mapped to None in the result
1194
if(!_b_.isinstance($.z, _b_.str)){
1195
throw _b_.TypeError('maketrans third argument must be a string')
1196
}
1197
for(var i=0,len=$.z.length;i<len;i++){
1198
toNone[_b_.ord($.z.charAt(i))] = true
1199
}
1200
}
1201
for(var i=0,len=$.x.length;i<len;i++){
1202
_t.$numeric_dict[_b_.ord($.x.charAt(i))] = _b_.ord($.y.charAt(i))
1203
}
1204
for(var k in toNone){
1205
_t.$numeric_dict[k] = _b_.None
1206
}
1207
return _t
1208
}
1209
}
1212
$StringDict.partition = function() {
1213
var $=$B.args('partition',2,{self:null,sep:null},['self','sep'],
1214
arguments,{},null,null)
1215
if($.sep==''){throw _b_.ValueError('empty separator')}
1216
check_str($.sep)
1217
var i=$.self.indexOf($.sep)
1218
if (i== -1) return _b_.tuple([$.self, '', ''])
1219
return _b_.tuple([$.self.substring(0,i), $.sep,
1220
$.self.substring(i+$.sep.length)])
1227
var re = new RegExp('\\'+specials.charAt(i),'g')
1228
str = str.replace(re, "\\"+specials.charAt(i))
1229
}
1230
return str
1231
}
1232
1233
$StringDict.replace = function(self, old, _new, count) {
1234
// Replaces occurrences of 'old' by '_new'. Count references
1235
// the number of times to replace. In CPython, negative or undefined
1236
// values of count means replace all.
1237
var $ = $B.args('replace', 4, {self:null,old:null,$$new:null,count:null},
1238
['self','old','$$new','count'], arguments, {count:-1},null,null),
1239
count=$.count,self=$.self,old=$.old,_new=$.$$new
1243
// Validate instance type of 'count'
1244
if (!isinstance(count,[_b_.int,_b_.float])) {
1245
throw _b_.TypeError("'" + $B.get_class(count).__name__ +
1246
"' object cannot be interpreted as an integer");
1247
} else if (isinstance(count, _b_.float)) {
1248
throw _b_.TypeError("integer argument expected, got float");
1249
}
1250
if(count==0){return self}
1251
if(count.__class__==$B.LongInt.$dict){count=parseInt(count.value)}
1252
if(old==''){
1253
if(_new==''){return self}
1254
if(self==''){return _new}
1255
var elts=self.split('')
1256
if(count>-1 && elts.length>=count){
1257
var rest = elts.slice(count).join('')
1258
return _new+elts.slice(0, count).join(_new)+rest
1259
}else{return _new+elts.join(_new)+_new}
1260
}else{
1261
var elts = $StringDict.split(self,old,count)
1264
var res = self, pos = -1
1265
if(old.length==0){
1266
var res = _new
1267
for(var i=0;i<elts.length;i++){
1268
res += elts[i]+_new
1269
}
1270
return res+rest
1271
}
1272
1273
if (count < 0) count = res.length;
1274
while (count > 0) {
1275
pos = res.indexOf(old, pos);
1276
if (pos < 0)
1277
break;
1278
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1279
pos = pos + _new.length;
1280
count--;
1281
}
1282
return res;
1283
}
1284
1285
$StringDict.rfind = function(self){
1286
// Return the highest index in the string where substring sub is found,
1287
// such that sub is contained within s[start:end]. Optional arguments
1288
// start and end are interpreted as in slice notation. Return -1 on failure.
1298
if($.sub.length==0){
1299
if($.start>$.self.length){return -1}
1300
else{return $.self.length}
1301
}
1302
var sublen = $.sub.length
1303
1304
for(var i=$.end-sublen;i>=$.start;i--){
1305
if($.self.substr(i, sublen)==$.sub){return i}
1306
}
1307
return -1
1308
}
1309
1310
$StringDict.rindex = function(){
1311
// Like rfind() but raises ValueError when the substring sub is not found
1313
if(res==-1){throw _b_.ValueError("substring not found")}
1314
return res
1315
}
1316
1317
$StringDict.rjust = function(self) {
1319
{self:null, width:null, fillchar:null},
1320
['self', 'width', 'fillchar'],
1321
arguments,{fillchar:' '},null,null)
1329
var $=$B.args('rpartition',2,{self:null,sep:null},['self','sep'],
1330
arguments,{},null,null)
1331
check_str($.sep)
1332
var self = reverse($.self),
1333
sep = reverse($.sep)
1334
var items = $StringDict.partition(self,sep).reverse()
1335
for(var i=0;i<items.length;i++){
1336
items[i]=items[i].split('').reverse().join('')
1337
}
1338
return items
1342
var $=$B.args("rsplit",3,{self:null,sep:null,maxsplit:null},
1343
['self','sep','maxsplit'],arguments,
1344
{sep:_b_.None, maxsplit:-1},null,null),
1345
sep=$.sep,maxsplit=$.maxsplit,self=$.self
1346
1347
// Use split on the reverse of the string and of separator
1348
var rev_str = reverse($.self),
1349
rev_sep = sep === _b_.None ? sep : reverse($.sep),
1352
// Reverse the list, then each string inside the list
1353
rev_res.reverse()
1354
for(var i=0;i<rev_res.length;i++){
1361
var $=$B.args('rstrip',2,{self:null,chars:null},['self','chars'],
1362
arguments,{chars:_b_.None},null,null)
1363
if($.chars===_b_.None){return $.self.replace(/\s+$/,'')}
1364
return $.self.replace(new RegExp("["+$.chars+"]*$"),"")
1369
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1370
['self','sep','maxsplit'],arguments,
1371
{sep:_b_.None, maxsplit:-1},null,null)
1372
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
1373
if(maxsplit.__class__===$B.LongInt.$dict){maxsplit=parseInt(maxsplit.value)}
1376
var res = []
1377
var pos = 0
1378
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1380
var name = ''
1381
while(1){
1382
if(self.charAt(pos).search(/\s/)===-1){
1383
if(name===''){name=self.charAt(pos)}
1384
else{name+=self.charAt(pos)}
1385
}else{
1386
if(name!==''){
1387
res.push(name)
1388
if(maxsplit!==-1&&res.length===maxsplit+1){
1389
res.pop()
1390
res.push(name+self.substr(pos))
1391
return res
1392
}
1393
name=''
1394
}
1395
}
1396
pos++
1397
if(pos>self.length-1){
1398
if(name){res.push(name)}
1399
break
1400
}
1401
}
1402
return res
1403
}else{
1404
var res = [],s='',pos=0,seplen=sep.length
1405
if(maxsplit==0){return [self]}
1406
while(pos<self.length){
1407
if(self.substr(pos,seplen)==sep){
1408
res.push(s)
1409
pos += seplen
1410
if(maxsplit>-1 && res.length>=maxsplit){
1411
res.push(self.substr(pos))
1412
return res
1413
}
1414
s= ''
1415
}else{
1416
s += self.charAt(pos)
1417
pos++
1425
$StringDict.splitlines = function(self){
1426
var $=$B.args('splitlines',2,{self:null,keepends:null},
1427
['self','keepends'],arguments,{keepends:false},null,null)
1428
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
1429
throw _b_.TypeError('integer argument expected, got '+
1430
$B.get_class($.keepends).__name)
1431
}
1432
var keepends = _b_.int($.keepends)
1433
// Remove trailing line breaks
1434
if(keepends){
1435
var res = [],start=pos,pos=0,x,self=$.self
1436
while(pos<self.length){
1437
if(self.substr(pos,2)=='\r\n'){
1438
res.push(self.substring(start,pos+2))
1439
start = pos+2
1440
pos = start
1441
}else if(self.charAt(pos)=='\r' || self.charAt(pos)=='\n'){
1442
res.push(self.substring(start,pos+1))
1443
start = pos+1
1444
pos = start
1445
}else{pos++}
1446
}
1447
var rest = self.substr(start)
1448
if(rest){res.push(rest)}
1449
return res
1450
}else{
1451
var self = $.self.replace(/[\r\n]$/,'')
1452
return self.split(/\n|\r\n|\r/)
1453
}
1454
}
1457
// Return True if string starts with the prefix, otherwise return False.
1458
// prefix can also be a tuple of prefixes to look for. With optional
1459
// start, test string beginning at that position. With optional end,
1460
// stop comparing string at that position.
1462
{self:null, prefix:null, start:null, end:null},
1463
['self', 'prefix', 'start', 'end'],
1466
normalize_start_end($)
1467
1468
var prefixes = $.prefix
1469
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1470
1471
var s = $.self.substring($.start,$.end)
1472
for(var i=0, _len_i = prefixes.length; i < _len_i;i++){
1473
prefix = prefixes[i]
1474
if(!_b_.isinstance(prefix, str)){throw _b_.TypeError(
1475
"endswith first arg must be str or a tuple of str, not int")}
1476
if(s.substr(0,prefix.length)==prefix) return true
1482
$StringDict.strip = function(){
1483
var $=$B.args('strip',2,{self:null,chars:null},['self','chars'],
1484
arguments,{chars:_b_.None},null,null)
1485
return $StringDict.rstrip($StringDict.lstrip($.self,$.chars),$.chars)
1501
var $=$B.args('zfill',2,{self:null,width:null},
1502
['self','width'],arguments,{},null,null)
1503
if ($.width <= self.length) {return self}
1504
switch(self.charAt(0)){
1505
case '+':
1506
case '-':
1507
return self.charAt(0)+'0'.repeat($.width-self.length)+self.substr(1)
1508
default:
1509
return '0'.repeat(width - self.length)+self
1510
}
1516
case 'string':
1517
return arg
1518
case 'number':
1519
if(isFinite(arg)){return arg.toString()}
1526
// class or its subclasses, but the attribute __str__ of the
1527
// class metaclass (usually "type") or its subclasses (usually
1528
// "object")
1529
// The metaclass is the attribute __class__ of the class dictionary
1530
var func = $B.$type.__getattribute__(arg.$dict.__class__,'__str__')
1535
var f = getattr(arg,'__str__')
1536
// XXX fix : if not better than object.__str__, try __repr__
1537
return f()
1538
}
1539
catch(err){
1545
if($B.debug>1){console.log(err)}
1546
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1548
}
1549
}
1550
}
1551
str.__class__ = $B.$factory
1552
str.$dict = $StringDict
1553
$StringDict.$factory = str
1554
$StringDict.__new__ = function(cls){
1555
if(cls===undefined){
1556
throw _b_.TypeError('str.__new__(): not enough arguments')
1557
}
1558
return {__class__:cls.$dict}
1559
}
1560
1563
// dictionary and factory for subclasses of string
1564
var $StringSubclassDict = {
1565
__class__:$B.$type,
1566
__name__:'str'
1567
}
1568
1569
// the methods in subclass apply the methods in $StringDict to the
1570
// result of instance.valueOf(), which is a Javascript string
1571
for(var $attr in $StringDict){
1572
if(typeof $StringDict[$attr]=='function'){
1573
$StringSubclassDict[$attr]=(function(attr){
1574
return function(){
1580
}
1581
}
1582
return $StringDict[attr].apply(null,args)
1583
}
1584
})($attr)
1585
}
1586
}
1587
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1588
1589
// factory for str subclasses
1590
$B.$StringSubclassFactory = {
1591
__class__:$B.$factory,
1592
$dict:$StringSubclassDict
1593
}
1594
1595
_b_.str = str
1596
1597
// Function to parse the 2nd argument of format()
1598
$B.parse_format_spec = function(spec){
1608
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1609
// If the second char is also an alignment specifier, the
1610
// first char is the fill value
1611
this.fill = spec.charAt(0)
1612
this.align = spec.charAt(1)
1613
pos = 2
1614
}else{
1615
// The first character defines alignment : fill defaults to ' '
1616
this.align=aligns[align_pos];
1617
this.fill=' ';
1618
pos++
1619
}
1620
}else{
1621
align_pos = aligns.indexOf(spec.charAt(1))
1622
if(spec.charAt(1) && align_pos!=-1){
1623
// The second character defines alignment : fill is the first one
1624
this.align=aligns[align_pos]
1625
this.fill=spec.charAt(0)
1626
pos = 2
1627
}
1628
}
1629
var car = spec.charAt(pos)
1630
if(car=='+'||car=='-'||car==' '){
1631
this.sign=car;
1632
pos++;
1633
car=spec.charAt(pos);
1636
if(car=='0'){
1637
// sign-aware : equivalent to fill=0 and align=='='
1638
this.fill='0'
1639
this.align = '='
1640
pos++;car=spec.charAt(pos)
1641
}
1643
if(this.width===undefined){this.width=car}
1644
else{this.width+=car}
1645
pos++;car=spec.charAt(pos)
1647
if(this.width!==undefined){this.width=parseInt(this.width)}
1648
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1649
if(car=='.'){
1650
if(digits.indexOf(spec.charAt(pos+1))==-1){
1651
throw _b_.ValueError("Missing precision in format spec")
1652
}
1653
this.precision = spec.charAt(pos+1)
1654
pos+=2;car=spec.charAt(pos)
1655
while(car && digits.indexOf(car)>-1){
1656
this.precision+=car;pos++;car=spec.charAt(pos)
1657
}
1658
this.precision = parseInt(this.precision)
1659
}
1660
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1661
if(pos!==spec.length){
1663
throw _b_.ValueError("Invalid format specifier")
1664
}
1665
}
1666
this.toString = function(){
1667
return (this.fill===undefined ? '' : _b_.str(this.fill))+
1668
(this.align||'')+
1669
(this.sign||'')+
1670
(this.alternate ? '#' : '')+
1671
(this.sign_aware ? '0' : '')+
1672
(this.width || '')+
1673
(this.comma ? ',' : '')+
1674
(this.precision ? '.'+this.precision : '')+
1675
(this.type || '')
1676
}
1677
}
1678
1679
$B.format_width = function(s, fmt){
1680
if(fmt.width && s.length<fmt.width){
1681
var fill=fmt.fill || ' ', align = fmt.align || '<',
1682
missing = fmt.width-s.length
1683
switch(align){
1684
case '<':
1685
return s+fill.repeat(missing)
1686
case '>':
1687
return fill.repeat(missing)+s
1688
case '=':
1689
if('+-'.indexOf(s.charAt(0))>-1){
1690
return s.charAt(0)+fill.repeat(missing)+s.substr(1)
1691
}else{
1692
return fill.repeat(missing)+s
1693
}
1694
case '^':
1695
left = parseInt(missing/2)