Skip to content
Permalink
Newer
Older
100644 2092 lines (1921 sloc) 66.4 KB
Sep 5, 2014
1
;(function($B){
2
3
var bltns = $B.InjectBuiltins()
4
eval(bltns)
Sep 5, 2014
5
Mar 23, 2018
6
if(!String.prototype.trim){
Mar 19, 2018
7
// Polyfill for older browsers
8
// The code does not use a regex to make it a bit faster.
9
// Implementation taken from a comment by Timo on the blog:
10
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
11
String.prototype.trim = function () {
12
var c
13
for(var i = 0; i < this.length; i++){
14
c = this.charCodeAt(i)
15
if([32, 10, 13, 9, 12, 11, 160, 5760, 6158, 8192, 8193, 8194,
16
8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232,
17
8233, 8239, 8287, 12288, 65279].indexOf(c) > -1){
18
continue
19
}else{break}
20
}
21
for(var j = this.length - 1; j >= i; j--){
22
c = this.charCodeAt(j)
Mar 23, 2018
23
if([32, 10, 13, 9, 12, 11, 160, 5760, 6158, 8192, 8193, 8194,
Mar 19, 2018
24
8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232,
25
8233, 8239, 8287, 12288, 65279].indexOf(c) > -1){
26
continue
27
}else{break}
28
}
29
return this.substring(i, j + 1);
30
}
Mar 23, 2018
32
if(!String.prototype.trimLeft) {
33
// Convenience method for browsers which do not have a native trimLeft
34
// (which is a nonstandard extension in Firefox and Chrome)
Mar 19, 2018
35
String.prototype.trimLeft = function () {
36
var c
37
for(var i = 0; i < this.length; i++){
38
c = this.charCodeAt(i)
Mar 23, 2018
39
if([32, 10, 13, 9, 12, 11, 160, 5760, 6158, 8192, 8193, 8194,
Mar 19, 2018
40
8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232,
41
8233, 8239, 8287, 12288, 65279].indexOf(c) > -1){
42
continue
43
}else{break}
44
}
45
return this.substring(i)
Mar 23, 2018
48
if(!String.prototype.trimRight) {
Mar 19, 2018
49
String.prototype.trimRight = function () {
50
// Convenience method for browsers which do not have a native trimRight
51
// (which is a nonstandard extension in Firefox and Chrome)
52
var c
53
for(var j = this.length - 1; j >= 0; j--){
54
c = this.charCodeAt(j)
55
if([32, 10, 13, 9, 12, 11, 160, 5760, 6158, 8192, 8193, 8194,
56
8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232,
57
8233, 8239, 8287, 12288, 65279].indexOf(c) > -1){
58
continue
59
}else{break}
60
}
61
return this.substring(0, j + 1)
Sep 5, 2014
66
str
Feb 10, 2018
67
var str = {
Mar 19, 2018
68
__class__: _b_.type,
69
__dir__: object.__dir__,
70
$infos: {
71
__module__: "builtins",
72
__name__: "str"
73
},
str
Feb 10, 2018
74
$is_class: true,
Mar 19, 2018
75
$native: true
Sep 5, 2014
76
}
77
Mar 19, 2018
79
if($.start === null || $.start === _b_.None){$.start = 0}
80
else if($.start < 0){
81
$.start += $.self.length
82
$.start = Math.max(0, $.start)
83
}
84
if($.end === null || $.end === _b_.None){$.end = $.self.length}
85
else if($.end < 0){
86
$.end += $.self.length
87
$.end = Math.max(0, $.end)
88
}
Mar 19, 2018
90
if(! isinstance($.start, _b_.int) || ! isinstance($.end, _b_.int)){
91
throw _b_.TypeError.$factory("slice indices must be integers " +
92
"or None or have an __index__ method")
93
}
97
function reverse(s){
98
// Reverse a string
Mar 19, 2018
99
return s.split("").reverse().join("")
100
}
101
102
function check_str(obj){
Mar 19, 2018
103
if(! _b_.isinstance(obj, str)){
Mar 21, 2018
104
throw _b_.TypeError.$factory("can't convert '" +
105
$B.class_name(obj) + "' object to str implicitly")
Mar 19, 2018
106
}
str
Feb 10, 2018
109
str.__add__ = function(self,other){
Mar 19, 2018
110
if(!(typeof other === "string")){
111
try{return getattr(other, "__radd__")(self)}
112
catch(err){
113
throw _b_.TypeError.$factory("Can't convert " +
114
$B.class_name(other) + " to str implicitly")}
Sep 5, 2014
115
}
Mar 19, 2018
116
return self + other
Sep 5, 2014
117
}
118
Mar 19, 2018
119
str.__contains__ = function(self, item){
120
if(!(typeof item == "string")){
121
throw _b_.TypeError.$factory("'in <string>' requires " +
122
"string as left operand, not " + item.__class__)
123
}
Sep 5, 2014
124
var nbcar = item.length
Mar 19, 2018
125
if(nbcar == 0) {return true} // a string contains the empty string
126
if(self.length == 0){return nbcar == 0}
127
for(var i = 0, len = self.length; i < len; i++){
128
if(self.substr(i, nbcar) == item){return true}
Sep 5, 2014
129
}
130
return false
131
}
132
str
Feb 10, 2018
133
str.__delitem__ = function(){
134
throw _b_.TypeError.$factory("'str' object doesn't support item deletion")
Sep 5, 2014
135
}
136
Mar 19, 2018
137
// __dir__must be assigned explicitely because attribute resolution for
138
// builtin classes doesn't use __mro__
str
Feb 10, 2018
139
str.__dir__ = object.__dir__
str
Feb 10, 2018
141
str.__eq__ = function(self,other){
Mar 19, 2018
142
if(other === undefined){ // compare object "self" to class "str"
143
return self === str
Sep 5, 2014
144
}
Mar 23, 2018
145
if(_b_.isinstance(other, _b_.str)){
146
return other.valueOf() == self.valueOf()
147
}
148
return _b_.NotImplemented
Sep 5, 2014
149
}
150
151
function preformat(self, fmt){
str
Feb 10, 2018
152
if(fmt.empty){return _b_.str.$factory(self)}
Mar 19, 2018
153
if(fmt.type && fmt.type != "s"){
154
throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
155
"' for object of type 'str'")
157
return self
158
}
159
str
Feb 10, 2018
160
str.__format__ = function(self, format_spec) {
161
var fmt = new $B.parse_format_spec(format_spec)
Mar 19, 2018
162
if(fmt.sign !== undefined){
163
throw _b_.ValueError.$factory(
164
"Sign not allowed in string format specifier")
166
// For strings, alignment default to left
Mar 19, 2018
167
fmt.align = fmt.align || "<"
168
return $B.format_width(preformat(self, fmt), fmt)
Sep 5, 2014
169
}
170
str
Feb 10, 2018
171
str.__getitem__ = function(self,arg){
Mar 19, 2018
172
if(isinstance(arg, _b_.int)){
Sep 5, 2014
173
var pos = arg
Mar 19, 2018
174
if(arg < 0) {pos += self.length}
175
if(pos >= 0 && pos < self.length){return self.charAt(pos)}
176
throw _b_.IndexError.$factory("string index out of range")
177
}
178
if(isinstance(arg, slice)) {
179
var s = _b_.slice.$conv_for_seq(arg, self.length),
180
start = s.start,
181
stop = s.stop,
182
step = s.step
183
var res = "",
Mar 19, 2018
184
i = null
Mar 19, 2018
185
if(step > 0){
186
if(stop <= start){return ""}
187
for(var i = start; i < stop; i += step){res += self.charAt(i)}
Mar 23, 2018
188
}else{
Mar 19, 2018
189
if(stop >= start){return ''}
190
for(var i = start; i > stop; i += step){res += self.charAt(i)}
Sep 5, 2014
192
return res
193
}
194
if(isinstance(arg, _b_.bool)){return self.__getitem__(_b_.int.$factory(arg))}
Mar 19, 2018
195
throw _b_.TypeError.$factory("string indices must be integers")
Sep 5, 2014
196
}
197
198
var prefix = 2,
199
suffix = 3,
200
mask = (2 ** 32 - 1)
201
function fnv(p){
202
if(p.length == 0){
203
return 0
204
}
Sep 5, 2014
205
206
var x = prefix
207
x = (x ^ (p.charCodeAt(0) << 7)) & mask
208
for(var i = 0, len = p.length; i < len; i++){
209
x = ((1000003 * x) ^ p.charCodeAt(i)) & mask
210
}
211
x = (x ^ p.length) & mask
212
x = (x ^ suffix) & mask
Sep 5, 2014
213
214
if(x == -1){
215
x = -2
216
}
217
return x
218
}
220
str.__hash__ = function(self) {
221
return fnv(self)
Sep 5, 2014
222
}
223
Mar 19, 2018
224
str.__init__ = function(self, arg){
Sep 5, 2014
225
self.valueOf = function(){return arg}
226
self.toString = function(){return arg}
Sep 5, 2014
228
}
229
Mar 19, 2018
230
var $str_iterator = $B.$iterator_class("str_iterator")
str
Feb 10, 2018
231
str.__iter__ = function(self){
Mar 19, 2018
232
var items = self.split("") // list of all characters in string
233
return $B.$iterator(items, $str_iterator)
Sep 5, 2014
234
}
235
str
Feb 10, 2018
236
str.__len__ = function(self){return self.length}
Sep 5, 2014
237
238
// Start of section for legacy formatting (with %)
239
Mar 19, 2018
240
var kwarg_key = new RegExp("([^\\)]*)\\)")
241
242
var NotANumber = function() {
Mar 19, 2018
243
this.name = "NotANumber"
244
}
245
Mar 19, 2018
246
var number_check = function(s){
247
if(! isinstance(s, [_b_.int, _b_.float])){
248
throw new NotANumber()
249
}
250
}
251
Mar 19, 2018
252
var get_char_array = function(size, char){
Mar 23, 2018
253
if(size <= 0){return ""}
254
return new Array(size + 1).join(char)
255
}
256
Mar 19, 2018
257
var format_padding = function(s, flags, minus_one){
258
var padding = flags.padding
Mar 23, 2018
259
if(! padding){ // undefined
260
return s
261
}
262
s = s.toString()
263
padding = parseInt(padding, 10)
Mar 23, 2018
264
if(minus_one){ // numeric formatting where sign goes in front of padding
265
padding -= 1
266
}
Mar 19, 2018
267
if(! flags.left){
268
return get_char_array(padding - s.length, flags.pad_char) + s
Mar 19, 2018
269
}else{
270
// left adjusted
271
return s + get_char_array(padding - s.length, flags.pad_char)
272
}
273
}
274
Mar 19, 2018
275
var format_int_precision = function(val, flags){
276
var precision = flags.precision
Mar 19, 2018
277
if(!precision){
278
return val.toString()
279
}
280
precision = parseInt(precision, 10)
Mar 19, 2018
282
if(val.__class__ === $B.long_int){
283
s = $B.long_int.to_base(val, 10)
284
}else{
285
s = val.toString()
Mar 19, 2018
287
if(s[0] === "-"){
288
return "-" + get_char_array(precision - s.length + 1, "0") + s.slice(1)
Mar 19, 2018
290
return get_char_array(precision - s.length, "0") + s
291
}
292
Mar 19, 2018
293
var format_float_precision = function(val, upper, flags, modifier){
294
var precision = flags.precision
295
// val is a float
Mar 19, 2018
296
if(isFinite(val)){
297
return modifier(val, precision, flags, upper)
Mar 19, 2018
299
if(val === Infinity){
300
val = "inf"
301
}else if(val === -Infinity){
302
val = "-inf"
303
}else{
304
val = "nan"
Mar 19, 2018
306
if(upper){
307
return val.toUpperCase()
308
}
309
return val
311
}
312
Mar 19, 2018
313
var format_sign = function(val, flags){
314
if(flags.sign){
315
if(val >= 0){
316
return "+"
Sep 5, 2014
317
}
Mar 19, 2018
318
}else if (flags.space){
319
if(val >= 0){
320
return " "
321
}
322
}
323
return ""
324
}
Sep 5, 2014
325
326
var str_format = function(val, flags) {
327
// string format supports left and right padding
328
flags.pad_char = " " // even if 0 padding is defined, don't use it
str
Feb 10, 2018
329
return format_padding(str.$factory(val), flags)
Sep 5, 2014
331
332
var num_format = function(val, flags) {
333
number_check(val)
Mar 19, 2018
334
if(val.__class__ === $B.long_int){
335
val = $B.long_int.to_base(val, 10)
336
}else{
337
val = parseInt(val)
340
var s = format_int_precision(val, flags)
Mar 19, 2018
341
if(flags.pad_char === "0"){
342
if(val < 0){
343
s = s.substring(1)
Mar 19, 2018
344
return "-" + format_padding(s, flags, true)
345
}
346
var sign = format_sign(val, flags)
Mar 19, 2018
347
if(sign !== ""){
348
return sign + format_padding(s, flags, true)
349
}
350
}
352
return format_padding(format_sign(val, flags) + s, flags)
353
}
Sep 5, 2014
354
355
var repr_format = function(val, flags) {
356
flags.pad_char = " " // even if 0 padding is defined, don't use it
357
return format_padding(repr(val), flags)
358
}
Sep 5, 2014
359
360
var ascii_format = function(val, flags) {
361
flags.pad_char = " " // even if 0 padding is defined, don't use it
362
return format_padding(ascii(val), flags)
363
}
Sep 5, 2014
364
365
// converts val to float and sets precision if missing
Mar 19, 2018
366
var _float_helper = function(val, flags){
367
number_check(val)
Mar 19, 2018
368
if(! flags.precision){
369
if(! flags.decimal_point){
370
flags.precision = 6
Mar 19, 2018
371
}else{
372
flags.precision = 0
373
}
Mar 19, 2018
374
}else{
375
flags.precision = parseInt(flags.precision, 10)
376
validate_precision(flags.precision)
377
}
378
return parseFloat(val)
379
}
Sep 5, 2014
380
381
// used to capture and remove trailing zeroes
Mar 19, 2018
382
var trailing_zeros = /(.*?)(0+)([eE].*)/,
383
leading_zeros = /\.(0*)/,
384
trailing_dot = /\.$/
Sep 5, 2014
385
386
var validate_precision = function(precision) {
387
// force precision to limits of javascript
Mar 19, 2018
388
if(precision > 20){precision = 20}
389
}
390
391
// gG
Mar 19, 2018
392
var floating_point_format = function(val, upper, flags){
393
val = _float_helper(val, flags),
394
v = val.toString(),
395
v_len = v.length,
396
dot_idx = v.indexOf('.')
397
if(dot_idx < 0){dot_idx = v_len}
398
if(val < 1 && val > -1){
399
var zeros = leading_zeros.exec(v),
400
numzeros
401
if(zeros){
402
numzeros = zeros[1].length
Mar 19, 2018
403
}else{
404
numzeros = 0
405
}
Mar 19, 2018
406
if(numzeros >= 4){
407
val = format_sign(val, flags) + format_float_precision(val, upper,
408
flags, _floating_g_exp_helper)
409
if(!flags.alternate){
410
var trl = trailing_zeros.exec(val)
Mar 19, 2018
411
if(trl){
412
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
414
}else{
415
if(flags.precision <= 1){
416
val = val[0] + "." + val.substring(1)
418
}
419
return format_padding(val, flags)
420
}
421
flags.precision = (flags.precision || 0) + numzeros
Mar 19, 2018
422
return format_padding(format_sign(val, flags) +
423
format_float_precision(val, upper, flags,
424
function(val, precision) {
425
return val.toFixed(min(precision, v_len - dot_idx) +
426
numzeros)
427
}),
428
flags
429
)
430
}
431
432
if(dot_idx > flags.precision){
433
val = format_sign(val, flags) + format_float_precision(val, upper,
434
flags, _floating_g_exp_helper)
435
if(! flags.alternate){
436
var trl = trailing_zeros.exec(val)
Mar 19, 2018
437
if(trl){
438
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
440
}else{
441
if(flags.precision <= 1){
442
val = val[0] + "." + val.substring(1)
443
}
444
}
445
return format_padding(val, flags)
446
}
Mar 19, 2018
447
return format_padding(format_sign(val, flags) +
448
format_float_precision(val, upper, flags,
449
function(val, precision) {
450
if(!flags.decimal_point){
451
precision = min(v_len - 1, 6)
452
}else if (precision > v_len){
453
if(! flags.alternate){
454
precision = v_len
455
}
Sep 5, 2014
456
}
Mar 19, 2018
457
if(precision < dot_idx){
458
precision = dot_idx
459
}
460
return val.toFixed(precision - dot_idx)
461
}),
462
flags
463
)
Sep 5, 2014
465
Mar 19, 2018
466
var _floating_g_exp_helper = function(val, precision, flags, upper){
467
if(precision){--precision}
468
val = val.toExponential(precision)
469
// pad exponent to two digits
Mar 19, 2018
470
var e_idx = val.lastIndexOf("e")
471
if(e_idx > val.length - 4){
472
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
474
if(upper){return val.toUpperCase()}
475
return val
476
}
477
478
// fF
479
var floating_point_decimal_format = function(val, upper, flags) {
480
val = _float_helper(val, flags)
Mar 19, 2018
481
return format_padding(format_sign(val, flags) +
482
format_float_precision(val, upper, flags,
483
function(val, precision, flags) {
484
val = val.toFixed(precision)
485
if(precision === 0 && flags.alternate){
486
val += '.'
487
}
488
return val
489
}),
490
flags
491
)
492
}
493
494
var _floating_exp_helper = function(val, precision, flags, upper) {
495
val = val.toExponential(precision)
496
// pad exponent to two digits
Mar 19, 2018
497
var e_idx = val.lastIndexOf("e")
Mar 23, 2018
498
if(e_idx > val.length - 4){
Mar 19, 2018
499
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
501
if(upper){return val.toUpperCase()}
502
return val
503
}
504
505
// eE
Mar 19, 2018
506
var floating_point_exponential_format = function(val, upper, flags){
507
val = _float_helper(val, flags)
Mar 19, 2018
509
return format_padding(format_sign(val, flags) +
510
format_float_precision(val, upper, flags, _floating_exp_helper), flags)
511
}
512
Mar 19, 2018
513
var signed_hex_format = function(val, upper, flags){
515
number_check(val)
Mar 23, 2018
517
if(val.__class__ === $B.long_int){
Mar 19, 2018
518
ret = $B.long_int.to_base(val, 16)
519
}else{
520
ret = parseInt(val)
521
ret = ret.toString(16)
522
}
523
ret = format_int_precision(ret, flags)
Mar 19, 2018
524
if(upper){ret = ret.toUpperCase()}
Mar 23, 2018
525
if(flags.pad_char === "0"){
Mar 19, 2018
526
if(val < 0){
527
ret = ret.substring(1)
Mar 19, 2018
528
ret = "-" + format_padding(ret, flags, true)
529
}
530
var sign = format_sign(val, flags)
Mar 19, 2018
531
if(sign !== ""){
532
ret = sign + format_padding(ret, flags, true)
Sep 5, 2014
533
}
Mar 19, 2018
536
if(flags.alternate){
537
if(ret.charAt(0) === "-"){
538
if(upper){ret = "-0X" + ret.slice(1)}
539
else{ret = "-0x" + ret.slice(1)}
540
}else{
541
if(upper){ret = "0X" + ret}
542
else{ret = "0x" + ret}
543
}
544
}
545
return format_padding(format_sign(val, flags) + ret, flags)
546
}
Sep 5, 2014
547
548
var octal_format = function(val, flags) {
549
number_check(val)
Mar 19, 2018
552
if(val.__class__ === $B.long_int){
553
ret = $B.long_int.to_base(8)
554
}else{
555
ret = parseInt(val)
556
ret = ret.toString(8)
559
ret = format_int_precision(ret, flags)
Mar 19, 2018
561
if(flags.pad_char === "0"){
562
if(val < 0){
563
ret = ret.substring(1)
Mar 19, 2018
564
ret = "-" + format_padding(ret, flags, true)
565
}
566
var sign = format_sign(val, flags)
Mar 19, 2018
567
if(sign !== ""){
568
ret = sign + format_padding(ret, flags, true)
569
}
Sep 5, 2014
570
}
Mar 19, 2018
572
if(flags.alternate){
573
if(ret.charAt(0) === "-"){ret = "-0o" + ret.slice(1)}
574
else{ret = "0o" + ret}
Sep 5, 2014
575
}
576
return format_padding(ret, flags)
577
}
578
Mar 19, 2018
579
var single_char_format = function(val, flags){
580
if(isinstance(val, str) && val.length == 1) return val
581
try{
582
val = _b_.int.$factory(val) // yes, floats are valid (they are cast to int)
Mar 19, 2018
583
}catch (err){
584
throw _b_.TypeError.$factory("%c requires int or char")
585
}
586
return format_padding(chr(val), flags)
587
}
588
Mar 19, 2018
589
var num_flag = function(c, flags){
590
if(c === "0" && ! flags.padding && ! flags.decimal_point && ! flags.left){
591
flags.pad_char = "0"
592
return
593
}
Mar 19, 2018
594
if(!flags.decimal_point){
595
flags.padding = (flags.padding || "") + c
Mar 19, 2018
596
}else{
597
flags.precision = (flags.precision || "") + c
598
}
599
}
600
601
var decimal_point_flag = function(val, flags) {
Mar 23, 2018
602
if(flags.decimal_point){
603
// can only have one decimal point
604
throw new UnsupportedChar()
605
}
606
flags.decimal_point = true
607
}
608
Mar 19, 2018
609
var neg_flag = function(val, flags){
610
flags.pad_char = " " // overrides '0' flag
611
flags.left = true
612
}
613
Mar 19, 2018
614
var space_flag = function(val, flags){
615
flags.space = true
616
}
617
Mar 19, 2018
618
var sign_flag = function(val, flags){
619
flags.sign = true
620
}
621
Mar 19, 2018
622
var alternate_flag = function(val, flags){
623
flags.alternate = true
624
}
625
626
var char_mapping = {
Mar 19, 2018
627
"s": str_format,
628
"d": num_format,
629
"i": num_format,
630
"u": num_format,
631
"o": octal_format,
632
"r": repr_format,
633
"a": ascii_format,
634
"g": function(val, flags){
635
return floating_point_format(val, false, flags)
636
},
637
"G": function(val, flags){return floating_point_format(val, true, flags)},
638
"f": function(val, flags){
639
return floating_point_decimal_format(val, false, flags)
640
},
641
"F": function(val, flags){
642
return floating_point_decimal_format(val, true, flags)
643
},
644
"e": function(val, flags){
645
return floating_point_exponential_format(val, false, flags)
646
},
647
"E": function(val, flags){
648
return floating_point_exponential_format(val, true, flags)
649
},
650
"x": function(val, flags){return signed_hex_format(val, false, flags)},
651
"X": function(val, flags){return signed_hex_format(val, true, flags)},
652
"c": single_char_format,
653
"0": function(val, flags){return num_flag("0", flags)},
654
"1": function(val, flags){return num_flag("1", flags)},
655
"2": function(val, flags){return num_flag("2", flags)},
656
"3": function(val, flags){return num_flag("3", flags)},
657
"4": function(val, flags){return num_flag("4", flags)},
658
"5": function(val, flags){return num_flag("5", flags)},
659
"6": function(val, flags){return num_flag("6", flags)},
660
"7": function(val, flags){return num_flag("7", flags)},
661
"8": function(val, flags){return num_flag("8", flags)},
662
"9": function(val, flags){return num_flag("9", flags)},
663
"-": neg_flag,
664
" ": space_flag,
665
"+": sign_flag,
666
".": decimal_point_flag,
667
"#": alternate_flag
668
}
669
670
// exception thrown when an unsupported char is encountered in legacy format
Mar 19, 2018
671
var UnsupportedChar = function(){
672
this.name = "UnsupportedChar"
673
}
674
str
Feb 10, 2018
675
str.__mod__ = function(self, args) {
677
var length = self.length,
Mar 19, 2018
678
pos = 0 | 0,
679
argpos = null,
680
getitem
Mar 19, 2018
681
if(_b_.isinstance(args, _b_.tuple)){
682
argpos = 0 | 0
Mar 19, 2018
684
getitem = _b_.getattr(args, "__getitem__", _b_.None)
685
}
686
var ret = ''
687
var $get_kwarg_string = function(s) {
688
// returns [self, newpos]
689
++pos
690
var rslt = kwarg_key.exec(s.substring(newpos))
Mar 19, 2018
691
if(! rslt){
692
throw _b_.ValueError.$factory("incomplete format key")
693
}
694
var key = rslt[1]
695
newpos += rslt[0].length
Mar 23, 2018
696
try{
697
var self = getitem(key)
Mar 19, 2018
698
}catch(err){
699
if(err.name === "KeyError"){
700
throw err
701
}
702
throw _b_.TypeError.$factory("format requires a mapping")
704
return get_string_value(s, self)
705
}
706
707
var $get_arg_string = function(s) {
708
// returns [self, newpos]
709
var self
711
// non-tuple args
Mar 19, 2018
712
if(argpos === null){
713
// args is the value
Mar 19, 2018
715
}else{
716
self = args[argpos++]
Mar 19, 2018
717
if(self === undefined){
718
throw _b_.TypeError.$factory(
719
"not enough arguments for format string")
Sep 5, 2014
720
}
721
}
722
return get_string_value(s, self)
724
var get_string_value = function(s, self) {
725
// todo: get flags, type
726
// todo: string value based on flags, type, value
Mar 19, 2018
727
var flags = {"pad_char": " "}
728
do{
729
var func = char_mapping[s[newpos]]
Mar 23, 2018
730
try{
Mar 19, 2018
731
if(func === undefined){
732
throw new UnsupportedChar()
Mar 19, 2018
733
}else{
734
var ret = func(self, flags)
Mar 19, 2018
735
if(ret !== undefined){
736
return ret
737
}
738
++newpos
739
}
Mar 19, 2018
740
}catch (err){
741
if(err.name == "UnsupportedChar"){
742
invalid_char = s[newpos]
Mar 19, 2018
743
if(invalid_char === undefined){
744
throw _b_.ValueError.$factory("incomplete format")
Mar 19, 2018
746
throw _b_.ValueError.$factory(
747
"unsupported format character '" + invalid_char +
748
"' (0x" + invalid_char.charCodeAt(0).toString(16) +
749
") at index " + newpos)
750
}else if(err.name === "NotANumber"){
751
var try_char = s[newpos],
752
cls = self.__class__
753
if(!cls){
754
if(typeof(self) === "string"){
755
cls = "str"
756
}else{
757
cls = typeof(self)
Mar 19, 2018
759
}else{
Mar 19, 2018
762
throw _b_.TypeError.$factory("%" + try_char +
763
" format: a number is required, not " + cls)
764
}else{
765
throw err
766
}
Sep 5, 2014
767
}
Mar 19, 2018
768
}while (true)
Sep 5, 2014
769
}
770
var nbph = 0 // number of placeholders
Mar 19, 2018
771
do{
772
var newpos = self.indexOf("%", pos)
773
if(newpos < 0){
774
ret += self.substring(pos)
775
break
776
}
777
ret += self.substring(pos, newpos)
778
++newpos
Mar 19, 2018
779
if(newpos < length){
780
if(self[newpos] === "%"){
781
ret += "%"
782
}else{
Mar 19, 2018
784
if(self[newpos] === "("){
785
++newpos
786
ret += $get_kwarg_string(self)
Mar 23, 2018
787
}else{
788
ret += $get_arg_string(self)
789
}
790
}
Mar 19, 2018
791
}else{
792
// % at end of string
793
throw _b_.ValueError.$factory("incomplete format")
794
}
795
pos = newpos + 1
Mar 19, 2018
796
}while(pos < length)
797
798
if(argpos !== null){
799
if(args.length > argpos){
800
throw _b_.TypeError.$factory(
801
"not enough arguments for format string")
802
}else if(args.length < argpos){
803
throw _b_.TypeError.$factory(
804
"not all arguments converted during string formatting")
Mar 19, 2018
806
}else if(nbph == 0){
807
throw _b_.TypeError.$factory(
808
"not all arguments converted during string formatting")
Sep 5, 2014
812
str
Feb 10, 2018
813
str.__mro__ = [object]
Sep 5, 2014
814
str
Feb 10, 2018
815
str.__mul__ = function(){
Mar 19, 2018
816
var $ = $B.args("__mul__", 2, {self: null, other: null},
817
["self", "other"], arguments, {}, null, null)
818
if(! isinstance($.other, _b_.int)){throw _b_.TypeError.$factory(
819
"Can't multiply sequence by non-int of type '" +
Mar 19, 2018
821
var $res = ""
822
for(var i = 0; i< $.other; i++){$res += $.self.valueOf()}
Sep 5, 2014
823
return $res
824
}
825
Mar 19, 2018
826
str.__ne__ = function(self,other){return other !== self.valueOf()}
Sep 5, 2014
827
str
Feb 10, 2018
828
str.__repr__ = function(self){
830
// escape the escape char
831
res = self.replace(/\\/g, "\\\\")
832
// special cases
833
res = res.replace(new RegExp("\u0007", "g"), "\\x07").
834
replace(new RegExp("\b", "g"), "\\x08").
835
replace(new RegExp("\f", "g"), "\\x0c").
836
replace(new RegExp("\n", "g"), "\\n").
837
replace(new RegExp("\r", "g"), "\\r").
838
replace(new RegExp("\t", "g"), "\\t")
Mar 19, 2018
839
if(res.search('"') == -1 && res.search("'") == -1){
840
return "'" + res + "'"
841
}else if(self.search('"') == -1){
842
return '"' + res + '"'
843
}
844
var qesc = new RegExp("'", "g") // to escape single quote
845
res = "'" + res.replace(qesc, "\\'") + "'"
Sep 5, 2014
846
return res
847
}
848
Mar 19, 2018
849
str.__setitem__ = function(self, attr, value){
850
throw _b_.TypeError.$factory(
851
"'str' object does not support item assignment")
Sep 5, 2014
852
}
str
Feb 10, 2018
854
str.__str__ = function(self){
Sep 5, 2014
856
}
Mar 19, 2018
857
str.toString = function(){return "string!"}
Sep 5, 2014
858
859
// generate comparison methods
860
var $comp_func = function(self,other){
861
if(typeof other !== "string"){return _b_.NotImplemented}
Sep 5, 2014
862
return self > other
863
}
Mar 19, 2018
864
$comp_func += "" // source code
865
var $comps = {">": "gt", ">=": "ge", "<": "lt", "<=": "le"}
Sep 5, 2014
866
for(var $op in $comps){
Mar 19, 2018
867
eval("str.__" + $comps[$op] + '__ = ' + $comp_func.replace(/>/gm,$op))
Sep 5, 2014
868
}
869
870
// add "reflected" methods
str
Feb 10, 2018
871
$B.make_rmethods(str)
Sep 5, 2014
872
873
// unsupported operations
Mar 19, 2018
874
var $notimplemented = function(self, other){
875
throw NotImplementedError.$factory(
876
"OPERATOR not implemented for class str")
Sep 5, 2014
877
}
878
879
// Copy static methods from unicode
880
var from_unicode = [
881
"title",
882
"capitalize",
883
"casefold",
884
"islower",
885
"isupper",
886
"istitle",
887
"isspace",
888
"isalpha",
889
"isalnum",
890
"isdecimal",
891
"isdigit",
892
"isnumeric",
893
"isidentifier",
894
"isprintable",
895
"lower",
896
"swapcase",
897
"upper"
898
]
899
// uses the object unicode, defined in unicode.min.js
Mar 19, 2018
900
from_unicode.forEach(function(name){
str
Feb 10, 2018
901
str[name] = unicode[name]
Mar 19, 2018
902
})
Sep 5, 2014
903
Mar 19, 2018
904
str.center = function(){
905
var $ = $B.args("center", 3, {self: null, width: null, fillchar: null},
906
["self", "width", "fillchar"],
907
arguments, {fillchar:" "}, null, null),
908
self = $.self
Mar 19, 2018
910
if($.width <= self.length) {return self}
Mar 19, 2018
912
var pad = parseInt(($.width - self.length) / 2),
913
res = $.fillchar.repeat(pad)
Sep 5, 2014
914
res += self + res
Mar 19, 2018
915
if(res.length < $.width){res += $.fillchar}
Sep 5, 2014
916
return res
917
}
918
str
Feb 10, 2018
919
str.count = function(){
Mar 19, 2018
920
var $ = $B.args("count", 4, {self:null, sub:null, start:null, stop:null},
921
["self", "sub", "start", "stop"], arguments, {start:null, stop:null},
Mar 19, 2018
923
if(!(typeof $.sub == "string")){throw _b_.TypeError.$factory(
924
"Can't convert '" + $B.class_name($.sub) +
Mar 19, 2018
925
"' object to str implicitly")}
Mar 19, 2018
927
if($.start !== null){
Mar 19, 2018
929
if($.stop !== null){_slice = _b_.slice.$factory($.start, $.stop)}
930
else{_slice = _b_.slice.$factory($.start, $.self.length)}
str
Feb 10, 2018
931
substr = str.__getitem__.apply(null, [$.self].concat(_slice))
Mar 19, 2018
933
if($.self.length + $.sub.length == 0){return 1}
Mar 19, 2018
935
if($.sub.length == 0){
936
if($.start == $.self.length){return 1}
937
else if(substr.length == 0){return 0}
938
return substr.length + 1
Mar 19, 2018
940
var n = 0,
941
pos = 0
942
while(pos < substr.length){
943
pos = substr.indexOf($.sub, pos)
944
if(pos >= 0){n++; pos += $.sub.length}
945
else{break}
Sep 5, 2014
946
}
947
return n
948
}
949
str
Feb 10, 2018
950
str.encode = function(self, encoding) {
Mar 23, 2018
951
if(encoding === undefined){encoding = "utf-8"}
Mar 19, 2018
952
if(encoding == "rot13" || encoding == "rot_13"){
953
// Special case : returns a string
Mar 19, 2018
954
var res = ""
955
for(var i = 0, len = self.length; i < len ; i++){
956
var char = self.charAt(i)
Mar 19, 2018
957
if(("a" <= char && char <= "m") || ("A" <= char && char <= "M")){
958
res += String.fromCharCode(String.charCodeAt(char) + 13)
959
}else if(("m" < char && char <= "z") ||
960
("M" < char && char <= "Z")){
961
res += String.fromCharCode(String.charCodeAt(char) - 13)
962
}else{res += char}
963
}
964
return res
965
}
966
return _b_.bytes.$factory(self, encoding)
Sep 5, 2014
967
}
968
str
Feb 10, 2018
969
str.endswith = function(){
970
// Return True if the string ends with the specified suffix, otherwise
971
// return False. suffix can also be a tuple of suffixes to look for.
972
// With optional start, test beginning at that position. With optional
Sep 5, 2014
973
// end, stop comparing at that position.
Mar 19, 2018
974
var $ = $B.args("endswith", 4,
975
{self:null, suffix:null, start:null, end:null},
Mar 19, 2018
976
["self", "suffix", "start", "end"],
977
arguments, {start: 0, end: null}, null, null)
Sep 20, 2015
978
979
normalize_start_end($)
980
981
var suffixes = $.suffix
Mar 19, 2018
982
if(! isinstance(suffixes,_b_.tuple)){suffixes = [suffixes]}
Mar 19, 2018
984
var s = $.self.substring($.start, $.end)
985
for(var i = 0, len = suffixes.length; i < len; i++){
986
var suffix = suffixes[i]
Mar 19, 2018
987
if(! _b_.isinstance(suffix, str)){throw _b_.TypeError.$factory(
Sep 20, 2015
988
"endswith first arg must be str or a tuple of str, not int")}
Mar 19, 2018
989
if(suffix.length <= s.length &&
990
s.substr(s.length - suffix.length) == suffix){return true}
Sep 5, 2014
991
}
992
return false
993
}
994
str
Feb 10, 2018
995
str.expandtabs = function(self, tabsize) {
Mar 19, 2018
996
var $ = $B.args("expandtabs", 2, {self: null, tabsize: null},
997
["self", "tabsize"], arguments, {tabsize: 8}, null, null)
998
var s = $B.$GetInt($.tabsize),
999
col = 0,
1000
pos = 0,
1001
res = ""
1002
if(s == 1){return self.replace(/\t/g," ")}
1003
while(pos < self.length){
1004
var car = self.charAt(pos)
1005
switch(car){
Mar 19, 2018
1006
case "\t":
Mar 21, 2018
1007
while(col % s > 0){res += " "; col++}
Mar 19, 2018
1009
case "\r":
1010
case "\n":
1011
res += car
1012
col = 0
1013
break
1014
default:
1015
res += car
1016
col++
1017
break
1018
}
1019
pos++
1020
}
Sep 5, 2014
1023
}
1024
str
Feb 10, 2018
1025
str.find = function(){
1026
// Return the lowest index in the string where substring sub is found,
1027
// such that sub is contained in the slice s[start:end]. Optional
1028
// arguments start and end are interpreted as in slice notation.
Sep 5, 2014
1029
// Return -1 if sub is not found.
Mar 19, 2018
1030
var $ = $B.args("str.find", 4,
Mar 19, 2018
1031
{self: null, sub: null, start: null, end: null},
1032
["self", "sub", "start", "end"],
1033
arguments, {start: 0, end: null}, null, null)
1034
check_str($.sub)
Mar 19, 2018
1037
if(!isinstance($.start, _b_.int)||!isinstance($.end, _b_.int)){
1038
throw _b_.TypeError.$factory("slice indices must be " +
1039
"integers or None or have an __index__ method")}
1040
var s = $.self.substring($.start, $.end)
Mar 19, 2018
1042
if($.sub.length == 0 && $.start == $.self.length){return $.self.length}
1043
if(s.length + $.sub.length == 0){return -1}
Mar 19, 2018
1045
var last_search = s.length - $.sub.length
1046
for(var i = 0; i <= last_search; i++){
1047
if(s.substr(i, $.sub.length) == $.sub){return $.start + i}
Sep 5, 2014
1048
}
Sep 5, 2014
1050
}
1051
1052
// Next function used by method .format()
1053
1054
$B.parse_format = function(fmt_string){
Sep 5, 2014
1055
1056
// Parse a "format string", as described in the Python documentation
1057
// Return a format object. For the format string
1058
// a.x[z]!r:...
1059
// the object has attributes :
1060
// - name : "a"
1061
// - name_ext : [".x", "[z]"]
1062
// - conv : r
1063
// - spec : rest of string after :
Sep 5, 2014
1064
Mar 19, 2018
1065
var elts = fmt_string.split(":"),
1066
name,
1067
conv,
1068
spec,
Mar 19, 2018
1069
name_ext = []
Mar 19, 2018
1070
if(elts.length == 1){
1071
// No : in the string : it only contains a name
1072
name = fmt_string
1073
}else{
1074
// name is before the first ":"
1075
// spec (the format specification) is after
1076
name = elts[0]
Mar 19, 2018
1077
spec = elts.splice(1).join(":")
Mar 19, 2018
1080
var elts = name.split("!")
1081
if(elts.length > 1){
1082
name = elts[0]
1083
conv = elts[1] // conversion flag
Sep 5, 2014
1085
Mar 19, 2018
1086
if(name !== undefined){
1087
// "name' may be a subscription or attribute
1088
// Put these "extensions" in the list "name_ext"
1089
function name_repl(match){
1090
name_ext.push(match)
Mar 19, 2018
1091
return ""
1092
}
1093
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1094
name = name.replace(name_ext_re, name_repl)
1095
}
Sep 5, 2014
1096
1097
return {name: name, name_ext: name_ext,
1098
conv: conv, spec: spec || "", string: fmt_string}
Sep 5, 2014
1100
1101
$B.split_format = function(self){
1102
// Parse self to detect formatting instructions
1103
// Create a list "parts" made of sections of the string :
1104
// - elements of even rank are literal text
1105
// - elements of odd rank are "format objects", built from the
1106
// format strings in self (of the form {...})
Mar 19, 2018
1107
var pos = 0,
1108
_len = self.length,
Mar 19, 2018
1110
text = "",
1111
parts = [],
1112
rank = 0
1113
while(pos < _len){
1114
car = self.charAt(pos)
Mar 21, 2018
1115
if(car == "{" && self.charAt(pos + 1) == "{"){
1116
// replace {{ by literal {
Mar 19, 2018
1117
text += "{"
1118
pos += 2
1119
}else if(car == "}" && self.charAt(pos + 1) == "}"){
1120
// replace }} by literal }
Mar 19, 2018
1121
text += "}"
1122
pos += 2
1123
}else if(car == "{"){
1124
// Start of a format string
1126
// Store current literal text
1127
parts.push(text)
1128
1129
// Search the end of the format string, ie the } closing the
1130
// opening {. Since the string can contain other pairs {} for
1131
// nested formatting, an integer nb is incremented for each { and
1132
// decremented for each } ; the end of the format string is
Mar 19, 2018
1133
// reached when nb == 0
1134
var end = pos + 1,
1135
nb = 1
1136
while(end < _len){
1137
if(self.charAt(end) == "{"){nb++; end++}
1138
else if(self.charAt(end) == "}"){
1139
nb--; end++
1140
if(nb == 0){
1141
// End of format string
Mar 19, 2018
1142
var fmt_string = self.substring(pos + 1, end - 1)
1143
1144
// Create a format object, by function parse_format
1145
var fmt_obj = $B.parse_format(fmt_string)
1146
fmt_obj.raw_name = fmt_obj.name
1147
fmt_obj.raw_spec = fmt_obj.spec
1148
1149
// If no name is explicitely provided, use the rank
1150
if(!fmt_obj.name){
Mar 19, 2018
1151
fmt_obj.name = rank + ""
Sep 5, 2014
1154
Mar 19, 2018
1155
if(fmt_obj.spec !== undefined){
1156
// "spec" may contain "nested replacement fields"
1157
// Replace empty fields by the rank in positional
1158
// arguments
1159
function replace_nested(name, key){
1160
if(key == ""){
1161
// Use implicit rank
1162
return "{" + rank++ + "}"
1166
fmt_obj.spec = fmt_obj.spec.replace(/\{(.*?)\}/g,
1167
replace_nested)
1168
}
1170
// Store format object in list "parts"
1171
parts.push(fmt_obj)
Mar 19, 2018
1172
text = ""
1173
break
1174
}
1175
}else{end++}
Sep 5, 2014
1176
}
Mar 19, 2018
1177
if(nb > 0){throw ValueError.$factory("wrong format " + self)}
Mar 19, 2018
1179
}else{text += car; pos++}
Sep 5, 2014
1180
}
1181
if(text){parts.push(text)}
1182
return parts
1183
}
1184
1185
str.format = function(self) {
1186
var $ = $B.args("format", 1, {self: null}, ["self"],
1187
arguments, {}, "$args", "$kw")
1188
1189
var parts = $B.split_format($.self)
1190
1191
// Apply formatting to the values passed to format()
Mar 19, 2018
1192
var res = "",
1193
fmt
Mar 19, 2018
1195
for(var i = 0; i < parts.length; i++){
1196
// Literal text is added unchanged
Mar 19, 2018
1197
if(typeof parts[i] == "string"){res += parts[i]; continue}
1199
// Format objects
1200
fmt = parts[i]
1201
1202
if(fmt.spec !== undefined){
1203
// "spec" may contain "nested replacement fields"
1204
// In this case, evaluate them using the positional
1205
// or keyword arguments passed to format()
1206
function replace_nested(name, key){
1207
if(/\d+/.exec(key)){
1208
// If key is numeric, search in positional
1209
// arguments
1210
return _b_.tuple.__getitem__($.$args,
1211
parseInt(key))
1212
}else{
1213
// Else try in keyword arguments
1214
return _b_.dict.__getitem__($.$kw, key)
1215
}
1216
}
1217
fmt.spec = fmt.spec.replace(/\{(.*?)\}/g,
1218
replace_nested)
1219
}
Mar 21, 2018
1220
if(fmt.name.charAt(0).search(/\d/) > -1){
1221
// Numerical reference : use positional arguments
1222
var pos = parseInt(fmt.name),
Feb 11, 2018
1223
value = _b_.tuple.__getitem__($.$args, pos)
1224
}else{
1225
// Use keyword arguments
Feb 11, 2018
1226
var value = _b_.dict.__getitem__($.$kw, fmt.name)
1227
}
1228
// If name has extensions (attributes or subscriptions)
Mar 19, 2018
1229
for(var j = 0; j < fmt.name_ext.length; j++){
1230
var ext = fmt.name_ext[j]
Mar 19, 2018
1231
if(ext.charAt(0) == "."){
1232
// Attribute
1233
value = _b_.getattr(value, ext.substr(1))
1234
}else{
1235
// Subscription
Mar 19, 2018
1236
var key = ext.substr(1, ext.length - 2)
1237
// An index made of digits is transformed into an integer
Mar 19, 2018
1238
if(key.charAt(0).search(/\d/) > -1){key = parseInt(key)}
1239
value = _b_.getattr(value, "__getitem__")(key)
Feb 12, 2018
1242
1243
// If the conversion flag is set, first call a function to convert
1244
// the value
Mar 19, 2018
1245
if(fmt.conv == "a"){value = _b_.ascii(value)}
1246
else if(fmt.conv == "r"){value = _b_.repr(value)}
1247
else if(fmt.conv == "s"){value = _b_.str.$factory(value)}
1249
// Call attribute __format__ to perform the actual formatting
1250
if(value.$is_class || value.$factory){
1251
// For classes, don't use the class __format__ method
1252
res += value.__class__.__format__(value, fmt.spec)
Mar 19, 2018
1254
res += _b_.getattr(value, "__format__")(fmt.spec)
Sep 5, 2014
1256
}
Sep 5, 2014
1258
}
1259
str
Feb 10, 2018
1260
str.format_map = function(self) {
Mar 19, 2018
1261
throw NotImplementedError.$factory(
1262
"function format_map not implemented yet")
Sep 5, 2014
1263
}
1264
str
Feb 10, 2018
1265
str.index = function(self){
Sep 5, 2014
1266
// Like find(), but raise ValueError when the substring is not found.
str
Feb 10, 2018
1267
var res = str.find.apply(null,arguments)
Mar 19, 2018
1268
if(res === -1){throw _b_.ValueError.$factory("substring not found")}
Sep 5, 2014
1269
return res
1270
}
1271
str
Feb 10, 2018
1272
str.join = function(){
Mar 19, 2018
1273
var $ = $B.args("join", 2, {self: null, iterable: null},
Mar 19, 2018
1274
["self", "iterable"], arguments, {}, null, null)
Mar 19, 2018
1276
var iterable = _b_.iter($.iterable),
Mar 19, 2018
1277
res = [],
Sep 5, 2014
1279
while(1){
1280
try{
1281
var obj2 = _b_.next(iterable)
Mar 19, 2018
1282
if(! isinstance(obj2, str)){throw _b_.TypeError.$factory(
1283
"sequence item " + count + ": expected str instance, " +
1284
$B.class_name(obj2) + " found")}
1285
res.push(obj2)
Sep 5, 2014
1286
}catch(err){
1287
if(_b_.isinstance(err, _b_.StopIteration)){
1288
break
1289
}
Sep 5, 2014
1290
else{throw err}
1291
}
1292
}
1293
return res.join($.self)
Sep 5, 2014
1294
}
1295
str
Feb 10, 2018
1296
str.ljust = function(self) {
Mar 19, 2018
1297
var $ = $B.args("ljust", 3, {self: null, width: null, fillchar:null},
1298
["self", "width", "fillchar"],
1299
arguments, {fillchar: " "}, null, null)
Mar 19, 2018
1301
if($.width <= self.length){return self}
1302
return self + $.fillchar.repeat($.width - self.length)
Sep 5, 2014
1303
}
1304
str
Feb 10, 2018
1305
str.lstrip = function(self,x){
Mar 19, 2018
1306
var $ = $B.args("lstrip", 2, {self: null, chars: null}, ["self", "chars"],
1307
arguments, {chars:_b_.None}, null, null)
1308
if($.chars === _b_.None){return $.self.trimLeft()}
1309
for(var i = 0; i < $.self.length; i++){
1310
if($.chars.indexOf($.self.charAt(i)) === -1){
1311
return $.self.substring(i)
Mar 19, 2018
1314
return ""
Sep 5, 2014
1315
}
1316
1317
// note, maketrans should be a static function.
str
Feb 10, 2018
1318
str.maketrans = function() {
Mar 19, 2018
1319
var $ = $B.args("maketrans", 3, {x: null, y: null, z: null},
1320
["x", "y", "z"], arguments, {y: null, z: null}, null, null)
Mar 19, 2018
1322
var _t = _b_.dict.$factory()
Mar 19, 2018
1324
if($.y === null && $.z === null){
1325
// If there is only one argument, it must be a dictionary mapping
1326
// Unicode ordinals (integers) or characters (strings of length 1) to
1327
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1328
// keys will then be converted to ordinals.
Mar 19, 2018
1329
if(! _b_.isinstance($.x, _b_.dict)){
1330
throw _b_.TypeError.$factory(
1331
"maketrans only argument must be a dict")
Feb 11, 2018
1333
var items = _b_.list.$factory(_b_.dict.items($.x))
Mar 19, 2018
1334
for(var i = 0, len = items.length; i < len; i++){
1335
var k = items[i][0],
1336
v = items[i][1]
1337
if(! _b_.isinstance(k, _b_.int)){
1338
if(_b_.isinstance(k, _b_.str) && k.length == 1){
1339
k = _b_.ord(k)
1340
}else{throw _b_.TypeError.$factory("dictionary key " + k +
1341
" is not int or 1-char string")}
1342
}
Mar 19, 2018
1343
if(v !== _b_.None && ! _b_.isinstance(v, [_b_.int, _b_.str])){
1344
throw _b_.TypeError.$factory("dictionary value " + v +
1345
" is not None, integer or string")
1346
}
1347
_b_.dict.$setitem(_t, k, v)
1348
}
1349
return _t
1350
}else{
1351
// If there are two arguments, they must be strings of equal length,
1352
// and in the resulting dictionary, each character in x will be mapped
1353
// to the character at the same position in y
Mar 19, 2018
1354
if(! (_b_.isinstance($.x, _b_.str) && _b_.isinstance($.y, _b_.str))){
1355
throw _b_.TypeError.$factory("maketrans arguments must be strings")
Mar 19, 2018
1356
}else if($.x.length !== $.y.length){
1357
throw _b_.TypeError.$factory(
1358
"maketrans arguments must be strings or same length")
1359
}else{
1360
var toNone = {}
Mar 19, 2018
1361
if($.z !== null){
1362
// If there is a third argument, it must be a string, whose
1363
// characters will be mapped to None in the result
Mar 19, 2018
1364
if(! _b_.isinstance($.z, _b_.str)){
1365
throw _b_.TypeError.$factory(
1366
"maketrans third argument must be a string")
Mar 19, 2018
1368
for(var i = 0, len = $.z.length; i < len; i++){
1369
toNone[_b_.ord($.z.charAt(i))] = true
1370
}
Mar 19, 2018
1372
for(var i = 0, len = $.x.length; i < len; i++){
1373
var key = _b_.ord($.x.charAt(i)),
1374
value = $.y.charAt(i)
1375
_b_.dict.$setitem(_t, key, value)
1376
}
1377
for(var k in toNone){
1378
_b_.dict.$setitem(_t, parseInt(k), _b_.None)
1379
}
1380
return _t
1381
}
1382
}
Sep 5, 2014
1383
}
1384
str
Feb 10, 2018
1385
str.partition = function() {
Mar 19, 2018
1386
var $ = $B.args("partition", 2, {self: null, sep: null}, ["self", "sep"],
1387
arguments, {}, null, null)
Mar 19, 2018
1388
if($.sep == ""){throw _b_.ValueError.$factory("empty separator")}
Mar 19, 2018
1389
check_str($.sep)
1390
var i = $.self.indexOf($.sep)
Mar 23, 2018
1391
if(i == -1){return _b_.tuple.$factory([$.self, "", ""])}
Mar 19, 2018
1392
return _b_.tuple.$factory([$.self.substring(0, i), $.sep,
1393
$.self.substring(i + $.sep.length)])
1394
}
1395
1396
function $re_escape(str){
1397
var specials = "[.*+?|()$^"
1398
for(var i = 0, len = specials.length; i < len; i++){
1399
var re = new RegExp("\\"+specials.charAt(i), "g")
1400
str = str.replace(re, "\\"+specials.charAt(i))
1401
}
1402
return str
Sep 5, 2014
1403
}
1404
str
Feb 10, 2018
1405
str.replace = function(self, old, _new, count) {
1406
// Replaces occurrences of 'old' by '_new'. Count references
1407
// the number of times to replace. In CPython, negative or undefined
1408
// values of count means replace all.
Mar 19, 2018
1409
var $ = $B.args("replace", 4,
1410
{self: null, old: null, $$new: null, count: null},
1411
["self", "old", "$$new", "count"],
1412
arguments, {count: -1}, null, null),
1413
count = $.count,
1414
self = $.self,
1415
old = $.old,
1416
_new = $.$$new
1417
// Validate type of old
1418
check_str(old)
1419
check_str(_new)
1420
// Validate instance type of 'count'
Mar 23, 2018
1421
if(! isinstance(count,[_b_.int, _b_.float])){
1422
throw _b_.TypeError.$factory("'" + $B.class_name(count) +
Mar 19, 2018
1423
"' object cannot be interpreted as an integer")
1424
}else if(isinstance(count, _b_.float)){
1425
throw _b_.TypeError.$factory("integer argument expected, got float")
1426
}
1427
if(count == 0){return self}
1428
if(count.__class__ == $B.long_int){count = parseInt(count.value)}
1429
if(old == ""){
1430
if(_new == ""){return self}
1431
if(self == ""){return _new}
1432
var elts = self.split("")
1433
if(count > -1 && elts.length >= count){
1434
var rest = elts.slice(count).join("")
1435
return _new + elts.slice(0, count).join(_new) + rest
1436
}else{return _new + elts.join(_new) + _new}
Mar 19, 2018
1438
var elts = str.split(self, old, count)
Sep 5, 2014
1439
}
Mar 19, 2018
1441
var res = self,
1442
pos = -1
1443
if(old.length == 0){
Mar 19, 2018
1445
for(var i = 0; i < elts.length; i++){
1446
res += elts[i] + _new
Mar 19, 2018
1448
return res + rest
Mar 19, 2018
1451
if(count < 0){count = res.length}
1452
while(count > 0){
1453
pos = res.indexOf(old, pos)
1454
if(pos < 0){break}
1455
res = res.substr(0, pos) + _new + res.substr(pos + old.length)
1456
pos = pos + _new.length
1457
count--
Mar 19, 2018
1459
return res
Sep 5, 2014
1460
}
1461
str
Feb 10, 2018
1462
str.rfind = function(self){
1463
// Return the highest index in the string where substring sub is found,
1464
// such that sub is contained within s[start:end]. Optional arguments
Sep 5, 2014
1465
// start and end are interpreted as in slice notation. Return -1 on failure.
Mar 19, 2018
1466
var $ = $B.args("rfind", 4,
Mar 19, 2018
1467
{self: null, sub: null, start: null, end: null},
1468
["self", "sub", "start", "end"],
1469
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
1470
1473
check_str($.sub)
Mar 19, 2018
1475
if($.sub.length == 0){
1476
if($.start > $.self.length){return -1}
1477
else{return $.self.length}
1478
}
1479
var sublen = $.sub.length
Mar 19, 2018
1481
for(var i = $.end - sublen; i >= $.start; i--){
1482
if($.self.substr(i, sublen) == $.sub){return i}
Sep 5, 2014
1485
}
1486
str
Feb 10, 2018
1487
str.rindex = function(){
Sep 5, 2014
1488
// Like rfind() but raises ValueError when the substring sub is not found
Mar 19, 2018
1489
var res = str.rfind.apply(null, arguments)
1490
if(res == -1){throw _b_.ValueError.$factory("substring not found")}
Sep 5, 2014
1491
return res
1492
}
1493
str
Feb 10, 2018
1494
str.rjust = function(self) {
Mar 19, 2018
1495
var $ = $B.args("rjust",3,
1496
{self: null, width: null, fillchar: null},
1497
["self", "width", "fillchar"],
1498
arguments, {fillchar: " "}, null, null)
Sep 5, 2014
1499
Mar 19, 2018
1500
if($.width <= self.length){return self}
Sep 5, 2014
1501
1502
return $.fillchar.repeat($.width - self.length) + self
Sep 5, 2014
1503
}
1504
str
Feb 10, 2018
1505
str.rpartition = function(self,sep) {
Mar 19, 2018
1506
var $ = $B.args("rpartition", 2, {self: null, sep: null}, ["self", "sep"],
1507
arguments, {}, null, null)
1508
check_str($.sep)
1509
var self = reverse($.self),
1510
sep = reverse($.sep)
Mar 19, 2018
1511
var items = str.partition(self, sep).reverse()
1512
for(var i = 0; i < items.length; i++){
1513
items[i] = items[i].split("").reverse().join("")
1514
}
1515
return items
Sep 5, 2014
1516
}
1517
str
Feb 10, 2018
1518
str.rsplit = function(self) {
Mar 19, 2018
1519
var $ = $B.args("rsplit", 3, {self: null, sep: null, maxsplit: null},
1520
["self", "sep", "maxsplit"], arguments,
1521
{sep: _b_.None, maxsplit: -1}, null, null),
1522
sep = $.sep
1523
1524
// Use split on the reverse of the string and of separator
1525
var rev_str = reverse($.self),
1526
rev_sep = sep === _b_.None ? sep : reverse($.sep),
str
Feb 10, 2018
1527
rev_res = str.split(rev_str, rev_sep, $.maxsplit)
1529
// Reverse the list, then each string inside the list
1530
rev_res.reverse()
Mar 19, 2018
1531
for(var i = 0; i < rev_res.length; i++){
1532
rev_res[i] = reverse(rev_res[i])
Sep 5, 2014
1535
}
1536
Mar 19, 2018
1537
str.rstrip = function(self, x){
1538
var $ = $B.args("rstrip", 2, {self: null, chars: null}, ["self", "chars"],
Mar 19, 2018
1539
arguments, {chars: _b_.None}, null, null)
1540
if($.chars === _b_.None){return $.self.trimRight()}
Mar 21, 2018
1541
for(var j = $.self.length - 1; j >= 0; j--){
Mar 19, 2018
1542
if($.chars.indexOf($.self.charAt(j)) == -1){
1543
return $.self.substring(0, j + 1)
Mar 19, 2018
1546
return ""
Sep 5, 2014
1547
}
1548
str
Feb 10, 2018
1549
str.split = function(){
Mar 19, 2018
1550
var $ = $B.args("split", 3, {self: null, sep: null, maxsplit: null},
1551
["self", "sep", "maxsplit"], arguments,
1552
{sep: _b_.None, maxsplit: -1}, null, null),
1553
sep = $.sep,
1554
maxsplit = $.maxsplit,
1555
self = $.self,
1556
pos = 0
1557
if(maxsplit.__class__ === $B.long_int){maxsplit = parseInt(maxsplit.value)}
1558
if(sep == ""){throw _b_.ValueError.$factory("empty separator")}
1559
if(sep === _b_.None){
Sep 5, 2014
1560
var res = []
Mar 19, 2018
1561
while(pos < self.length && self.charAt(pos).search(/\s/) > -1){pos++}
1562
if(pos === self.length - 1){return [self]}
1563
var name = ""
Sep 5, 2014
1564
while(1){
Mar 19, 2018
1565
if(self.charAt(pos).search(/\s/) == -1){
1566
if(name == ""){name = self.charAt(pos)}
1567
else{name += self.charAt(pos)}
Sep 5, 2014
1568
}else{
Mar 19, 2018
1569
if(name !== ""){
Sep 5, 2014
1570
res.push(name)
Mar 19, 2018
1571
if(maxsplit !== -1 && res.length == maxsplit + 1){
Sep 5, 2014
1572
res.pop()
Mar 19, 2018
1573
res.push(name + self.substr(pos))
Sep 5, 2014
1574
return res
1575
}
Mar 19, 2018
1576
name = ""
Sep 5, 2014
1577
}
1578
}
1579
pos++
Mar 19, 2018
1580
if(pos > self.length - 1){
Sep 5, 2014
1581
if(name){res.push(name)}
1582
break
1583
}
1584
}
1585
return res
1586
}else{
Mar 19, 2018
1587
var res = [],
1588
s = "",
1589
seplen = sep.length
1590
if(maxsplit == 0){return [self]}
1591
while(pos < self.length){
1592
if(self.substr(pos, seplen) == sep){
Mar 19, 2018
1595
if(maxsplit > -1 && res.length >= maxsplit){
1596
res.push(self.substr(pos))
1597
return res
1598
}
Mar 19, 2018
1599
s = ""
1600
}else{
1601
s += self.charAt(pos)
1602
pos++
Sep 5, 2014
1603
}
1604
}
Sep 5, 2014
1607
}
1608
}
1609
str
Feb 10, 2018
1610
str.splitlines = function(self){
Mar 19, 2018
1611
var $ = $B.args("splitlines", 2, {self: null, keepends: null},
Mar 19, 2018
1612
["self", "keepends"], arguments, {keepends: false}, null, null)
1613
if(! _b_.isinstance($.keepends, [_b_.bool, _b_.int])){
1614
throw _b_.TypeError.$factory("integer argument expected, got " +
1615
$B.get_class($.keepends).__name)
1616
}
1617
var keepends = _b_.int.$factory($.keepends)
1618
// Remove trailing line breaks
1619
if(keepends){
1620
var res = [],
Mar 19, 2018
1621
start = pos,
1622
pos = 0,
1623
self = $.self
1624
while(pos < self.length){
1625
if(self.substr(pos, 2) == "\r\n"){
1626
res.push(self.substring(start, pos + 2))
1627
start = pos + 2
1628
pos = start
Mar 19, 2018
1629
}else if(self.charAt(pos) == "\r" || self.charAt(pos) == "\n"){
1630
res.push(self.substring(start, pos + 1))
1631
start = pos + 1
1632
pos = start
1633
}else{pos++}
1634
}
1635
var rest = self.substr(start)
1636
if(rest){res.push(rest)}
1637
return res
1638
}else{
Mar 19, 2018
1639
var self = $.self.replace(/[\r\n]$/, "")
1640
return self.split(/\n|\r\n|\r/)
1641
}
1642
}
Sep 5, 2014
1643
str
Feb 10, 2018
1644
str.startswith = function(){
1645
// Return True if string starts with the prefix, otherwise return False.
1646
// prefix can also be a tuple of prefixes to look for. With optional
1647
// start, test string beginning at that position. With optional end,
Sep 5, 2014
1648
// stop comparing string at that position.
Mar 19, 2018
1649
var $ = $B.args("startswith", 4,
1650
{self: null, prefix: null, start: null, end: null},
1651
["self", "prefix", "start", "end"],
1652
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
1653
1654
normalize_start_end($)
1655
1656
var prefixes = $.prefix
Mar 19, 2018
1657
if(! isinstance(prefixes, _b_.tuple)){prefixes = [prefixes]}
Mar 19, 2018
1659
var s = $.self.substring($.start, $.end)
1660
for(var i = 0, len = prefixes.length; i < len; i++){
1661
var prefix = prefixes[i]
Mar 19, 2018
1662
if(! _b_.isinstance(prefix, str)){throw _b_.TypeError.$factory(
1663
"endswith first arg must be str or a tuple of str, not int")}
Mar 19, 2018
1664
if(s.substr(0, prefix.length) == prefix){return true}
Sep 5, 2014
1665
}
1666
return false
1667
Sep 5, 2014
1668
}
1669
str
Feb 10, 2018
1670
str.strip = function(){
Mar 19, 2018
1671
var $ = $B.args("strip", 2, {self: null, chars: null}, ["self", "chars"],
1672
arguments, {chars: _b_.None}, null, null)
1673
if($.chars === _b_.None){return $.self.trim()}
1674
for(var i = 0; i < $.self.length; i++){
1675
if($.chars.indexOf($.self.charAt(i)) == -1){
1676
break
Mar 19, 2018
1679
for(var j = $.self.length - 1; j >= i; j--){
1680
if($.chars.indexOf($.self.charAt(j)) == -1){
1681
break
Mar 19, 2018
1684
return $.self.substring(i, j + 1)
Sep 5, 2014
1685
}
1686
1687
str.translate = function(self, table){
Mar 19, 2018
1688
var res = [],
1689
getitem = $B.$getattr(table, "__getitem__")
1690
for(var i = 0, len = self.length; i < len; i++){
1691
try{
1692
var repl = getitem(self.charCodeAt(i))
1693
if(repl !== _b_.None){
1694
res.push(repl)
1695
}
1696
}catch(err){
1697
res.push(self.charAt(i))
1698
}
Sep 5, 2014
1699
}
Mar 19, 2018
1700
return res.join("")
Sep 5, 2014
1701
}
1702
Mar 19, 2018
1703
str.zfill = function(self, width){
Mar 19, 2018
1704
var $ = $B.args("zfill", 2, {self: null, width: null},
Mar 19, 2018
1705
["self", "width"], arguments, {}, null, null)
1706
if($.width <= self.length){return self}
Mar 19, 2018
1708
case "+":
1709
case "-":
1710
return self.charAt(0) +
1711
"0".repeat($.width - self.length) + self.substr(1)
Mar 19, 2018
1713
return "0".repeat(width - self.length) + self
Sep 5, 2014
1715
}
1716
1717
str.$factory = function(arg, encoding, errors){
Mar 19, 2018
1718
if(arg === undefined){console.log("undef"); return "<undefined>"}
1719
switch(typeof arg) {
Mar 19, 2018
1720
case "string":
1721
return arg
1722
case "number":
1723
if(isFinite(arg)){return arg.toString()}
1726
if(arg.$is_class || arg.$factory){
1727
// arg is a class
1728
// In this case, str() doesn't use the attribute __str__ of the
1729
// class or its subclasses, but the attribute __str__ of the
1730
// class metaclass (usually "type") or its subclasses (usually
1731
// "object")
1732
// The metaclass is the attribute __class__ of the class dictionary
Mar 19, 2018
1733
var func = $B.$getattr(arg.__class__, "__str__")
1735
}
1736
if(arg.__class__ && arg.__class__ === _b_.bytes &&
1737
encoding !== undefined){
1738
// str(bytes, encoding, errors) is equal to
1739
// bytes.decode(encoding, errors)
1740
// Arguments may be passed as keywords (cf. issue #1060)
1741
var $ = $B.args("str", 3, {arg: null, encoding: null, errors: null},
1742
["arg", "encoding", "errors"], arguments,
1743
{encoding: "utf-8", errors: "strict"}, null, null)
1744
return _b_.bytes.decode(arg, $.encoding, $.errors)
1746
var f = $B.$getattr(arg, "__str__", null)
1747
if(f === null ||
1748
// if not better than object.__str__, try __repr__
1749
(arg.__class__ && arg.__class__ !== _b_.object &&
1750
f.$infos && f.$infos.__func__ === _b_.object.__str__)){
1751
var f = $B.$getattr(arg, "__repr__")
1752
}
Sep 5, 2014
1753
}
1754
catch(err){
1755
console.log("no __str__ for", arg)
Mar 19, 2018
1756
console.log("err ", err)
1757
if($B.debug > 1){console.log(err)}
1758
console.log("Warning - no method __str__ or __repr__, " +
1759
"default to toString", arg)
1760
return arg.toString()
Sep 5, 2014
1761
}
Sep 5, 2014
1763
}
str
Feb 10, 2018
1764
1765
str.__new__ = function(cls){
Mar 19, 2018
1766
if(cls === undefined){
1767
throw _b_.TypeError.$factory("str.__new__(): not enough arguments")
Sep 5, 2014
1768
}
Mar 19, 2018
1769
return {__class__: cls}
Sep 5, 2014
1770
}
1771
str
Feb 10, 2018
1772
$B.set_func_names(str, "builtins")
Sep 5, 2014
1774
// dictionary and factory for subclasses of string
str
Feb 10, 2018
1775
var StringSubclass = $B.StringSubclass = {
Mar 19, 2018
1776
__class__: _b_.type,
str
Feb 10, 2018
1777
__mro__: [object],
1778
$infos: {
1779
__module__: "builtins",
1780
__name__: "str"
1781
},
str
Feb 10, 2018
1782
$is_class: true
Sep 5, 2014
1783
}
1784
str
Feb 10, 2018
1785
// the methods in subclass apply the methods in str to the
Sep 5, 2014
1786
// result of instance.valueOf(), which is a Javascript string
str
Feb 10, 2018
1787
for(var $attr in str){
Mar 19, 2018
1788
if(typeof str[$attr] == "function"){
Mar 19, 2018
1789
StringSubclass[$attr] = (function(attr){
Sep 5, 2014
1790
return function(){
Mar 19, 2018
1791
var args = [],
1792
pos = 0
1793
if(arguments.length > 0){
1794
var args = [arguments[0].valueOf()],
1795
pos = 1
1796
for(var i = 1, len = arguments.length; i < len; i++){
1797
args[pos++] = arguments[i]
Sep 5, 2014
1798
}
1799
}
Mar 19, 2018
1800
return str[attr].apply(null, args)
Sep 5, 2014
1801
}
1802
})($attr)
1803
}
1804
}
str
Feb 10, 2018
1805
StringSubclass.__new__ = function(cls){
Sep 5, 2014
1808
str
Feb 10, 2018
1809
$B.set_func_names(StringSubclass, "builtins")
Sep 5, 2014
1811
_b_.str = str
1812
1813
// Function to parse the 2nd argument of format()
1814
$B.parse_format_spec = function(spec){
Mar 19, 2018
1815
if(spec == ""){this.empty = true}
1816
else{
Mar 19, 2018
1817
var pos = 0,
1818
aligns = "<>=^",
1819
digits = "0123456789",
1820
types = "bcdeEfFgGnosxX%",
1821
align_pos = aligns.indexOf(spec.charAt(0))
Mar 19, 2018
1822
if(align_pos != -1){
1823
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1)) != -1){
1824
// If the second char is also an alignment specifier, the
1825
// first char is the fill value
1826
this.fill = spec.charAt(0)
1827
this.align = spec.charAt(1)
1828
pos = 2
1829
}else{
1830
// The first character defines alignment : fill defaults to ' '
Mar 19, 2018
1831
this.align = aligns[align_pos]
1832
this.fill = " "
1833
pos++
1834
}
1835
}else{
1836
align_pos = aligns.indexOf(spec.charAt(1))
Mar 19, 2018
1837
if(spec.charAt(1) && align_pos != -1){
1838
// The second character defines alignment : fill is the first one
Mar 19, 2018
1839
this.align = aligns[align_pos]
1840
this.fill = spec.charAt(0)
1841
pos = 2
1842
}
1843
}
1844
var car = spec.charAt(pos)
Mar 19, 2018
1845
if(car == "+" || car == "-" || car == " "){
1846
this.sign = car
1847
pos++
1848
car = spec.charAt(pos)
Mar 19, 2018
1850
if(car == "#"){this.alternate = true; pos++; car = spec.charAt(pos)}
1851
if(car == "0"){
Mar 19, 2018
1852
// sign-aware : equivalent to fill = 0 and align == "="
Mar 19, 2018
1853
this.fill = "0"
1854
this.align = "="
1855
pos++
1856
car = spec.charAt(pos)
1857
}
Mar 19, 2018
1858
while(car && digits.indexOf(car) > -1){
1859
if(this.width === undefined){this.width = car}
1860
else{this.width += car}
1861
pos++
1862
car = spec.charAt(pos)
Mar 19, 2018
1864
if(this.width !== undefined){this.width = parseInt(this.width)}
1865
if(this.width === undefined && car == "{"){
1866
// Width is determined by a parameter
1867
var end_param_pos = spec.substr(pos).search("}")
1868
this.width = spec.substring(pos, end_param_pos)
1869
console.log("width", "[" + this.width + "]")
1870
pos += end_param_pos + 1
1871
}
Mar 19, 2018
1872
if(car == ","){this.comma = true; pos++; car = spec.charAt(pos)}
1873
if(car == "."){
1874
if(digits.indexOf(spec.charAt(pos + 1)) == -1){
1875
throw _b_.ValueError.$factory(
1876
"Missing precision in format spec")
Mar 19, 2018
1878
this.precision = spec.charAt(pos + 1)
1879
pos += 2
1880
car = spec.charAt(pos)
1881
while(car && digits.indexOf(car) > -1){
Mar 21, 2018
1882
this.precision += car
Mar 19, 2018
1883
pos++
1884
car = spec.charAt(pos)
1885
}
1886
this.precision = parseInt(this.precision)
1887
}
Mar 19, 2018
1888
if(car && types.indexOf(car) > -1){
1889
this.type = car
1890
pos++
1891
car = spec.charAt(pos)
1892
}
1893
if(pos !== spec.length){
1894
throw _b_.ValueError.$factory("Invalid format specifier: " + spec)
1897
this.toString = function(){
Mar 19, 2018
1898
return (this.fill === undefined ? "" : _b_.str.$factory(this.fill)) +
1899
(this.align || "") +
1900
(this.sign || "") +
1901
(this.alternate ? "#" : "") +
1902
(this.sign_aware ? "0" : "") +
1903
(this.width || "") +
1904
(this.comma ? "," : "") +
1905
(this.precision ? "." + this.precision : "") +
1906
(this.type || "")
1907
}
1908
}
1909
1910
$B.format_width = function(s, fmt){
Mar 19, 2018
1911
if(fmt.width && s.length < fmt.width){
1912
var fill = fmt.fill || " ",
1913
align = fmt.align || "<",
1914
missing = fmt.width - s.length
1915
switch(align){
Mar 19, 2018
1916
case "<":
1917
return s + fill.repeat(missing)
1918
case ">":
1919
return fill.repeat(missing) + s
1920
case "=":
1921
if("+-".indexOf(s.charAt(0)) > -1){
1922
return s.charAt(0) + fill.repeat(missing) + s.substr(1)
1923
}else{
Mar 19, 2018
1924
return fill.repeat(missing) + s
Mar 19, 2018
1926
case "^":
1927
var left = parseInt(missing / 2)
1928
return fill.repeat(left) + s + fill.repeat(missing - left)
1929
}
1930
}
1931
return s
1932
}
1933
1934
function fstring_expression(){
Mar 19, 2018
1935
this.type = "expression"
1936
this.expression = ""
1937
this.conversion = null
1938
this.fmt = null
1939
}
1940
1941
$B.parse_fstring = function(string){
1942
// Parse a f-string
1943
var elts = [],
1944
pos = 0,
Mar 19, 2018
1945
current = "",
1946
ctype = null,
1947
nb_braces = 0,
1948
car
1949
Mar 19, 2018
1950
while(pos < string.length){
1951
if(ctype === null){
1952
car = string.charAt(pos)
Mar 19, 2018
1953
if(car == "{"){
Mar 21, 2018
1954
if(string.charAt(pos + 1) == "{"){
Mar 19, 2018
1955
ctype = "string"
1956
current = "{"
1957
pos += 2
1958
}else{
Mar 19, 2018
1959
ctype = "expression"
1960
nb_braces = 1
1961
pos++
1962
}
Mar 19, 2018
1963
}else if(car == "}"){
Mar 21, 2018
1964
if(string.charAt(pos + 1) == car){
Mar 19, 2018
1965
ctype = "string"
1966
current = "}"
1967
pos += 2
1968
}else{
1969
throw Error(" f-string: single '}' is not allowed")
1970
}
1971
}else{
Mar 19, 2018
1972
ctype = "string"
1973
current = car
1974
pos++
Mar 19, 2018
1976
}else if(ctype == "string"){
1977
// end of string is the first single { or end of string
Mar 19, 2018
1978
var i = pos
1979
while(i < string.length){
1980
car = string.charAt(i)
Mar 19, 2018
1981
if(car == "{"){
Mar 21, 2018
1982
if(string.charAt(i + 1) == "{"){
Mar 19, 2018
1983
current += "{"
1984
i += 2
1985
}else{
1986
elts.push(current)
Mar 19, 2018
1987
ctype = "expression"
1988
pos = i + 1
1989
break
1990
}
Mar 19, 2018
1991
}else if(car == "}"){
1992
if(string.charAt(i + 1) == car){
1993
current += car
1994
i += 2
1995
}else{
1996
throw Error(" f-string: single '}' is not allowed")
1997
}
1998
}else{
1999
current += car
2000
i++
2001
}
2002
}
Mar 19, 2018
2003
pos = i + 1
2004
}else{
2005
// End of expression is the } matching the opening {
2006
// There may be nested braces
2007
var i = pos,
2008
nb_braces = 1,
2009
nb_paren = 0,
2010
current = new fstring_expression()
Mar 19, 2018
2011
while(i < string.length){
2012
car = string.charAt(i)
Mar 19, 2018
2013
if(car == "{" && nb_paren == 0){
2014
nb_braces++
2015
current.expression += car
2016
i++
Mar 19, 2018
2017
}else if(car == "}" && nb_paren == 0){
2018
nb_braces -= 1
Mar 19, 2018
2019
if(nb_braces == 0){
2020
// end of expression
2021
elts.push(current)
2022
ctype = null
Mar 19, 2018
2023
current = ""
2024
pos = i + 1
2027
current.expression += car
2028
i++
Mar 19, 2018
2029
}else if(car == "\\"){
2030
// backslash is not allowed in expressions
2031
throw Error("f-string expression part cannot include a" +
2032
" backslash")
Mar 19, 2018
2033
}else if(nb_paren == 0 && car == "!" && current.fmt === null &&
Mar 21, 2018
2034
":}".indexOf(string.charAt(i + 2)) > -1){
Mar 19, 2018
2035
if(current.expression.length == 0){
2036
throw Error("f-string: empty expression not allowed")
2037
}
Mar 19, 2018
2038
if("ars".indexOf(string.charAt(i + 1)) == -1){
2039
throw Error("f-string: invalid conversion character:" +
2040
" expected 's', 'r', or 'a'")
2041
}else{
Mar 19, 2018
2042
current.conversion = string.charAt(i + 1)
2043
i += 2
2044
}
Mar 19, 2018
2045
}else if(car == "("){
2046
nb_paren++
2047
current.expression += car
2048
i++
Mar 19, 2018
2049
}else if(car == ")"){
2050
nb_paren--
2051
current.expression += car
2052
i++
Mar 19, 2018
2053
}else if(car == '"'){
2054
// triple string ?
Mar 19, 2018
2055
if(string.substr(i, 3) == '"""'){
2056
var end = string.indexOf('"""', i + 3)
2057
if(end == -1){
2058
throw Error("f-string: unterminated string")
2059
}else{
2060
var trs = string.substring(i, end + 3)
2061
trs = trs.replace("\n", "\\n\\")
2062
current.expression += trs
Mar 19, 2018
2063
i = end + 3
2064
}
2065
}else{
Mar 19, 2018
2066
var end = string.indexOf('"', i + 1)
2067
if(end == -1){
2068
throw Error("f-string: unterminated string")
2069
}else{
2070
current.expression += string.substring(i, end + 1)
2071
i = end + 1
2072
}
2073
}
Mar 19, 2018
2074
}else if(nb_paren == 0 && car == ":"){
2075
current.fmt = true
2076
current.expression += car
2077
i++
2078
}else{
2079
current.expression += car
2080
i++
2081
}
2082
}
Mar 21, 2018
2083
if(nb_braces > 0){
2084
throw Error("f-string: expected '}'")
2085
}
2086
}
2087
}
Mar 19, 2018
2088
if(current.length > 0){elts.push(current)}
2089
return elts
2090
}
2091
Sep 5, 2014
2092
})(__BRYTHON__)