Skip to content
Permalink
Newer
Older
100644 2449 lines (2250 sloc) 78.4 KB
Sep 5, 2014
1
;(function($B){
2
3
var bltns = $B.InjectBuiltins()
4
eval(bltns)
Sep 5, 2014
5
6
// build tables from data in unicode_data.js
7
var unicode_tables = $B.unicode_tables
8
/*
9
// Copy static methods from unicode
10
var from_unicode = [
11
"isalpha",
12
"isalnum",
13
"isdecimal",
14
"isdigit",
15
"isidentifier",
16
]
17
*/
Mar 23, 2018
18
if(!String.prototype.trim){
Mar 19, 2018
19
// Polyfill for older browsers
20
// The code does not use a regex to make it a bit faster.
21
// Implementation taken from a comment by Timo on the blog:
22
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
23
String.prototype.trim = function () {
24
var c
25
for(var i = 0; i < this.length; i++){
26
c = this.charCodeAt(i)
27
if([32, 10, 13, 9, 12, 11, 160, 5760, 6158, 8192, 8193, 8194,
28
8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232,
29
8233, 8239, 8287, 12288, 65279].indexOf(c) > -1){
30
continue
31
}else{break}
32
}
33
for(var j = this.length - 1; j >= i; j--){
34
c = this.charCodeAt(j)
Mar 23, 2018
35
if([32, 10, 13, 9, 12, 11, 160, 5760, 6158, 8192, 8193, 8194,
Mar 19, 2018
36
8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232,
37
8233, 8239, 8287, 12288, 65279].indexOf(c) > -1){
38
continue
39
}else{break}
40
}
41
return this.substring(i, j + 1);
42
}
Mar 23, 2018
44
if(!String.prototype.trimLeft) {
45
// Convenience method for browsers which do not have a native trimLeft
46
// (which is a nonstandard extension in Firefox and Chrome)
Mar 19, 2018
47
String.prototype.trimLeft = function () {
48
var c
49
for(var i = 0; i < this.length; i++){
50
c = this.charCodeAt(i)
Mar 23, 2018
51
if([32, 10, 13, 9, 12, 11, 160, 5760, 6158, 8192, 8193, 8194,
Mar 19, 2018
52
8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232,
53
8233, 8239, 8287, 12288, 65279].indexOf(c) > -1){
54
continue
55
}else{break}
56
}
57
return this.substring(i)
Mar 23, 2018
60
if(!String.prototype.trimRight) {
Mar 19, 2018
61
String.prototype.trimRight = function () {
62
// Convenience method for browsers which do not have a native trimRight
63
// (which is a nonstandard extension in Firefox and Chrome)
64
var c
65
for(var j = this.length - 1; j >= 0; j--){
66
c = this.charCodeAt(j)
67
if([32, 10, 13, 9, 12, 11, 160, 5760, 6158, 8192, 8193, 8194,
68
8195, 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8232,
69
8233, 8239, 8287, 12288, 65279].indexOf(c) > -1){
70
continue
71
}else{break}
72
}
73
return this.substring(0, j + 1)
Sep 5, 2014
78
str
Feb 10, 2018
79
var str = {
Mar 19, 2018
80
__class__: _b_.type,
81
__dir__: object.__dir__,
82
$infos: {
83
__module__: "builtins",
84
__name__: "str"
85
},
str
Feb 10, 2018
86
$is_class: true,
Mar 19, 2018
87
$native: true
Sep 5, 2014
88
}
89
Mar 19, 2018
91
if($.start === null || $.start === _b_.None){$.start = 0}
92
else if($.start < 0){
93
$.start += $.self.length
94
$.start = Math.max(0, $.start)
95
}
96
if($.end === null || $.end === _b_.None){$.end = $.self.length}
97
else if($.end < 0){
98
$.end += $.self.length
99
$.end = Math.max(0, $.end)
100
}
Mar 19, 2018
102
if(! isinstance($.start, _b_.int) || ! isinstance($.end, _b_.int)){
103
throw _b_.TypeError.$factory("slice indices must be integers " +
104
"or None or have an __index__ method")
105
}
109
function reverse(s){
110
// Reverse a string
Mar 19, 2018
111
return s.split("").reverse().join("")
112
}
113
114
function check_str(obj){
Mar 19, 2018
115
if(! _b_.isinstance(obj, str)){
Mar 21, 2018
116
throw _b_.TypeError.$factory("can't convert '" +
117
$B.class_name(obj) + "' object to str implicitly")
Mar 19, 2018
118
}
str
Feb 10, 2018
121
str.__add__ = function(self,other){
Mar 19, 2018
122
if(!(typeof other === "string")){
123
try{return getattr(other, "__radd__")(self)}
124
catch(err){
125
throw _b_.TypeError.$factory("Can't convert " +
126
$B.class_name(other) + " to str implicitly")}
Sep 5, 2014
127
}
Mar 19, 2018
128
return self + other
Sep 5, 2014
129
}
130
Mar 19, 2018
131
str.__contains__ = function(self, item){
132
if(!(typeof item == "string")){
133
throw _b_.TypeError.$factory("'in <string>' requires " +
134
"string as left operand, not " + item.__class__)
135
}
Sep 5, 2014
136
var nbcar = item.length
Mar 19, 2018
137
if(nbcar == 0) {return true} // a string contains the empty string
138
if(self.length == 0){return nbcar == 0}
139
for(var i = 0, len = self.length; i < len; i++){
140
if(self.substr(i, nbcar) == item){return true}
Sep 5, 2014
141
}
142
return false
143
}
144
str
Feb 10, 2018
145
str.__delitem__ = function(){
146
throw _b_.TypeError.$factory("'str' object doesn't support item deletion")
Sep 5, 2014
147
}
148
Mar 19, 2018
149
// __dir__must be assigned explicitely because attribute resolution for
150
// builtin classes doesn't use __mro__
str
Feb 10, 2018
151
str.__dir__ = object.__dir__
str
Feb 10, 2018
153
str.__eq__ = function(self,other){
Mar 19, 2018
154
if(other === undefined){ // compare object "self" to class "str"
155
return self === str
Sep 5, 2014
156
}
Mar 23, 2018
157
if(_b_.isinstance(other, _b_.str)){
158
return other.valueOf() == self.valueOf()
159
}
160
return _b_.NotImplemented
Sep 5, 2014
161
}
162
163
function preformat(self, fmt){
str
Feb 10, 2018
164
if(fmt.empty){return _b_.str.$factory(self)}
Mar 19, 2018
165
if(fmt.type && fmt.type != "s"){
166
throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
167
"' for object of type 'str'")
169
return self
170
}
171
str
Feb 10, 2018
172
str.__format__ = function(self, format_spec) {
173
var fmt = new $B.parse_format_spec(format_spec)
Mar 19, 2018
174
if(fmt.sign !== undefined){
175
throw _b_.ValueError.$factory(
176
"Sign not allowed in string format specifier")
178
// For strings, alignment default to left
Mar 19, 2018
179
fmt.align = fmt.align || "<"
180
return $B.format_width(preformat(self, fmt), fmt)
Sep 5, 2014
181
}
182
str
Feb 10, 2018
183
str.__getitem__ = function(self,arg){
Mar 19, 2018
184
if(isinstance(arg, _b_.int)){
Sep 5, 2014
185
var pos = arg
Mar 19, 2018
186
if(arg < 0) {pos += self.length}
187
if(pos >= 0 && pos < self.length){return self.charAt(pos)}
188
throw _b_.IndexError.$factory("string index out of range")
189
}
190
if(isinstance(arg, slice)) {
191
var s = _b_.slice.$conv_for_seq(arg, self.length),
192
start = s.start,
193
stop = s.stop,
194
step = s.step
195
var res = "",
Mar 19, 2018
196
i = null
Mar 19, 2018
197
if(step > 0){
198
if(stop <= start){return ""}
199
for(var i = start; i < stop; i += step){res += self.charAt(i)}
Mar 23, 2018
200
}else{
Mar 19, 2018
201
if(stop >= start){return ''}
202
for(var i = start; i > stop; i += step){res += self.charAt(i)}
Sep 5, 2014
204
return res
205
}
206
if(isinstance(arg, _b_.bool)){return self.__getitem__(_b_.int.$factory(arg))}
Mar 19, 2018
207
throw _b_.TypeError.$factory("string indices must be integers")
Sep 5, 2014
208
}
209
210
var prefix = 2,
211
suffix = 3,
212
mask = (2 ** 32 - 1)
213
function fnv(p){
214
if(p.length == 0){
215
return 0
216
}
Sep 5, 2014
217
218
var x = prefix
219
x = (x ^ (p.charCodeAt(0) << 7)) & mask
220
for(var i = 0, len = p.length; i < len; i++){
221
x = ((1000003 * x) ^ p.charCodeAt(i)) & mask
222
}
223
x = (x ^ p.length) & mask
224
x = (x ^ suffix) & mask
Sep 5, 2014
225
226
if(x == -1){
227
x = -2
228
}
229
return x
230
}
232
str.__hash__ = function(self) {
233
return fnv(self)
Sep 5, 2014
234
}
235
Mar 19, 2018
236
str.__init__ = function(self, arg){
Sep 5, 2014
237
self.valueOf = function(){return arg}
238
self.toString = function(){return arg}
Sep 5, 2014
240
}
241
242
var str_iterator = $B.make_iterator_class("str_iterator")
str
Feb 10, 2018
243
str.__iter__ = function(self){
Mar 19, 2018
244
var items = self.split("") // list of all characters in string
245
return str_iterator.$factory(items)
Sep 5, 2014
246
}
247
str
Feb 10, 2018
248
str.__len__ = function(self){return self.length}
Sep 5, 2014
249
250
// Start of section for legacy formatting (with %)
251
Mar 19, 2018
252
var kwarg_key = new RegExp("([^\\)]*)\\)")
253
254
var NotANumber = function() {
Mar 19, 2018
255
this.name = "NotANumber"
256
}
257
Mar 19, 2018
258
var number_check = function(s){
259
if(! isinstance(s, [_b_.int, _b_.float])){
260
throw new NotANumber()
261
}
262
}
263
Mar 19, 2018
264
var get_char_array = function(size, char){
Mar 23, 2018
265
if(size <= 0){return ""}
266
return new Array(size + 1).join(char)
267
}
268
Mar 19, 2018
269
var format_padding = function(s, flags, minus_one){
270
var padding = flags.padding
Mar 23, 2018
271
if(! padding){ // undefined
272
return s
273
}
274
s = s.toString()
275
padding = parseInt(padding, 10)
Mar 23, 2018
276
if(minus_one){ // numeric formatting where sign goes in front of padding
277
padding -= 1
278
}
Mar 19, 2018
279
if(! flags.left){
280
return get_char_array(padding - s.length, flags.pad_char) + s
Mar 19, 2018
281
}else{
282
// left adjusted
283
return s + get_char_array(padding - s.length, flags.pad_char)
284
}
285
}
286
Mar 19, 2018
287
var format_int_precision = function(val, flags){
288
var precision = flags.precision
Mar 19, 2018
289
if(!precision){
290
return val.toString()
291
}
292
precision = parseInt(precision, 10)
Mar 19, 2018
294
if(val.__class__ === $B.long_int){
295
s = $B.long_int.to_base(val, 10)
296
}else{
297
s = val.toString()
Mar 19, 2018
299
if(s[0] === "-"){
300
return "-" + get_char_array(precision - s.length + 1, "0") + s.slice(1)
Mar 19, 2018
302
return get_char_array(precision - s.length, "0") + s
303
}
304
Mar 19, 2018
305
var format_float_precision = function(val, upper, flags, modifier){
306
var precision = flags.precision
307
// val is a float
Mar 19, 2018
308
if(isFinite(val)){
309
return modifier(val, precision, flags, upper)
Mar 19, 2018
311
if(val === Infinity){
312
val = "inf"
313
}else if(val === -Infinity){
314
val = "-inf"
315
}else{
316
val = "nan"
Mar 19, 2018
318
if(upper){
319
return val.toUpperCase()
320
}
321
return val
323
}
324
Mar 19, 2018
325
var format_sign = function(val, flags){
326
if(flags.sign){
327
if(val >= 0){
328
return "+"
Sep 5, 2014
329
}
Mar 19, 2018
330
}else if (flags.space){
331
if(val >= 0){
332
return " "
333
}
334
}
335
return ""
336
}
Sep 5, 2014
337
338
var str_format = function(val, flags) {
339
// string format supports left and right padding
340
flags.pad_char = " " // even if 0 padding is defined, don't use it
str
Feb 10, 2018
341
return format_padding(str.$factory(val), flags)
Sep 5, 2014
343
344
var num_format = function(val, flags) {
345
number_check(val)
Mar 19, 2018
346
if(val.__class__ === $B.long_int){
347
val = $B.long_int.to_base(val, 10)
348
}else{
349
val = parseInt(val)
352
var s = format_int_precision(val, flags)
Mar 19, 2018
353
if(flags.pad_char === "0"){
354
if(val < 0){
355
s = s.substring(1)
Mar 19, 2018
356
return "-" + format_padding(s, flags, true)
357
}
358
var sign = format_sign(val, flags)
Mar 19, 2018
359
if(sign !== ""){
360
return sign + format_padding(s, flags, true)
361
}
362
}
364
return format_padding(format_sign(val, flags) + s, flags)
365
}
Sep 5, 2014
366
367
var repr_format = function(val, flags) {
368
flags.pad_char = " " // even if 0 padding is defined, don't use it
369
return format_padding(repr(val), flags)
370
}
Sep 5, 2014
371
372
var ascii_format = function(val, flags) {
373
flags.pad_char = " " // even if 0 padding is defined, don't use it
374
return format_padding(ascii(val), flags)
375
}
Sep 5, 2014
376
377
// converts val to float and sets precision if missing
Mar 19, 2018
378
var _float_helper = function(val, flags){
379
number_check(val)
Mar 19, 2018
380
if(! flags.precision){
381
if(! flags.decimal_point){
382
flags.precision = 6
Mar 19, 2018
383
}else{
384
flags.precision = 0
385
}
Mar 19, 2018
386
}else{
387
flags.precision = parseInt(flags.precision, 10)
388
validate_precision(flags.precision)
389
}
390
return parseFloat(val)
391
}
Sep 5, 2014
392
393
// used to capture and remove trailing zeroes
Mar 19, 2018
394
var trailing_zeros = /(.*?)(0+)([eE].*)/,
395
leading_zeros = /\.(0*)/,
396
trailing_dot = /\.$/
Sep 5, 2014
397
398
var validate_precision = function(precision) {
399
// force precision to limits of javascript
Mar 19, 2018
400
if(precision > 20){precision = 20}
401
}
402
403
// gG
Mar 19, 2018
404
var floating_point_format = function(val, upper, flags){
405
val = _float_helper(val, flags),
406
v = val.toString(),
407
v_len = v.length,
408
dot_idx = v.indexOf('.')
409
if(dot_idx < 0){dot_idx = v_len}
410
if(val < 1 && val > -1){
411
var zeros = leading_zeros.exec(v),
412
numzeros
413
if(zeros){
414
numzeros = zeros[1].length
Mar 19, 2018
415
}else{
416
numzeros = 0
417
}
Mar 19, 2018
418
if(numzeros >= 4){
419
val = format_sign(val, flags) + format_float_precision(val, upper,
420
flags, _floating_g_exp_helper)
421
if(!flags.alternate){
422
var trl = trailing_zeros.exec(val)
Mar 19, 2018
423
if(trl){
424
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
426
}else{
427
if(flags.precision <= 1){
428
val = val[0] + "." + val.substring(1)
430
}
431
return format_padding(val, flags)
432
}
433
flags.precision = (flags.precision || 0) + numzeros
Mar 19, 2018
434
return format_padding(format_sign(val, flags) +
435
format_float_precision(val, upper, flags,
436
function(val, precision) {
437
return val.toFixed(min(precision, v_len - dot_idx) +
438
numzeros)
439
}),
440
flags
441
)
442
}
443
444
if(dot_idx > flags.precision){
445
val = format_sign(val, flags) + format_float_precision(val, upper,
446
flags, _floating_g_exp_helper)
447
if(! flags.alternate){
448
var trl = trailing_zeros.exec(val)
Mar 19, 2018
449
if(trl){
450
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
452
}else{
453
if(flags.precision <= 1){
454
val = val[0] + "." + val.substring(1)
455
}
456
}
457
return format_padding(val, flags)
458
}
Mar 19, 2018
459
return format_padding(format_sign(val, flags) +
460
format_float_precision(val, upper, flags,
461
function(val, precision) {
462
if(!flags.decimal_point){
463
precision = min(v_len - 1, 6)
464
}else if (precision > v_len){
465
if(! flags.alternate){
466
precision = v_len
467
}
Sep 5, 2014
468
}
Mar 19, 2018
469
if(precision < dot_idx){
470
precision = dot_idx
471
}
472
return val.toFixed(precision - dot_idx)
473
}),
474
flags
475
)
Sep 5, 2014
477
Mar 19, 2018
478
var _floating_g_exp_helper = function(val, precision, flags, upper){
479
if(precision){--precision}
480
val = val.toExponential(precision)
481
// pad exponent to two digits
Mar 19, 2018
482
var e_idx = val.lastIndexOf("e")
483
if(e_idx > val.length - 4){
484
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
486
if(upper){return val.toUpperCase()}
487
return val
488
}
489
490
// fF
491
var floating_point_decimal_format = function(val, upper, flags) {
492
val = _float_helper(val, flags)
Mar 19, 2018
493
return format_padding(format_sign(val, flags) +
494
format_float_precision(val, upper, flags,
495
function(val, precision, flags) {
496
val = val.toFixed(precision)
497
if(precision === 0 && flags.alternate){
498
val += '.'
499
}
500
return val
501
}),
502
flags
503
)
504
}
505
506
var _floating_exp_helper = function(val, precision, flags, upper) {
507
val = val.toExponential(precision)
508
// pad exponent to two digits
Mar 19, 2018
509
var e_idx = val.lastIndexOf("e")
Mar 23, 2018
510
if(e_idx > val.length - 4){
Mar 19, 2018
511
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
513
if(upper){return val.toUpperCase()}
514
return val
515
}
516
517
// eE
Mar 19, 2018
518
var floating_point_exponential_format = function(val, upper, flags){
519
val = _float_helper(val, flags)
Mar 19, 2018
521
return format_padding(format_sign(val, flags) +
522
format_float_precision(val, upper, flags, _floating_exp_helper), flags)
523
}
524
Mar 19, 2018
525
var signed_hex_format = function(val, upper, flags){
527
number_check(val)
Mar 23, 2018
529
if(val.__class__ === $B.long_int){
Mar 19, 2018
530
ret = $B.long_int.to_base(val, 16)
531
}else{
532
ret = parseInt(val)
533
ret = ret.toString(16)
534
}
535
ret = format_int_precision(ret, flags)
Mar 19, 2018
536
if(upper){ret = ret.toUpperCase()}
Mar 23, 2018
537
if(flags.pad_char === "0"){
Mar 19, 2018
538
if(val < 0){
539
ret = ret.substring(1)
Mar 19, 2018
540
ret = "-" + format_padding(ret, flags, true)
541
}
542
var sign = format_sign(val, flags)
Mar 19, 2018
543
if(sign !== ""){
544
ret = sign + format_padding(ret, flags, true)
Sep 5, 2014
545
}
Mar 19, 2018
548
if(flags.alternate){
549
if(ret.charAt(0) === "-"){
550
if(upper){ret = "-0X" + ret.slice(1)}
551
else{ret = "-0x" + ret.slice(1)}
552
}else{
553
if(upper){ret = "0X" + ret}
554
else{ret = "0x" + ret}
555
}
556
}
557
return format_padding(format_sign(val, flags) + ret, flags)
558
}
Sep 5, 2014
559
560
var octal_format = function(val, flags) {
561
number_check(val)
Mar 19, 2018
564
if(val.__class__ === $B.long_int){
565
ret = $B.long_int.to_base(8)
566
}else{
567
ret = parseInt(val)
568
ret = ret.toString(8)
571
ret = format_int_precision(ret, flags)
Mar 19, 2018
573
if(flags.pad_char === "0"){
574
if(val < 0){
575
ret = ret.substring(1)
Mar 19, 2018
576
ret = "-" + format_padding(ret, flags, true)
577
}
578
var sign = format_sign(val, flags)
Mar 19, 2018
579
if(sign !== ""){
580
ret = sign + format_padding(ret, flags, true)
581
}
Sep 5, 2014
582
}
Mar 19, 2018
584
if(flags.alternate){
585
if(ret.charAt(0) === "-"){ret = "-0o" + ret.slice(1)}
586
else{ret = "0o" + ret}
Sep 5, 2014
587
}
588
return format_padding(ret, flags)
589
}
590
Mar 19, 2018
591
var single_char_format = function(val, flags){
592
if(isinstance(val, str) && val.length == 1) return val
593
try{
594
val = _b_.int.$factory(val) // yes, floats are valid (they are cast to int)
Mar 19, 2018
595
}catch (err){
596
throw _b_.TypeError.$factory("%c requires int or char")
597
}
598
return format_padding(chr(val), flags)
599
}
600
Mar 19, 2018
601
var num_flag = function(c, flags){
602
if(c === "0" && ! flags.padding && ! flags.decimal_point && ! flags.left){
603
flags.pad_char = "0"
604
return
605
}
Mar 19, 2018
606
if(!flags.decimal_point){
607
flags.padding = (flags.padding || "") + c
Mar 19, 2018
608
}else{
609
flags.precision = (flags.precision || "") + c
610
}
611
}
612
613
var decimal_point_flag = function(val, flags) {
Mar 23, 2018
614
if(flags.decimal_point){
615
// can only have one decimal point
616
throw new UnsupportedChar()
617
}
618
flags.decimal_point = true
619
}
620
Mar 19, 2018
621
var neg_flag = function(val, flags){
622
flags.pad_char = " " // overrides '0' flag
623
flags.left = true
624
}
625
Mar 19, 2018
626
var space_flag = function(val, flags){
627
flags.space = true
628
}
629
Mar 19, 2018
630
var sign_flag = function(val, flags){
631
flags.sign = true
632
}
633
Mar 19, 2018
634
var alternate_flag = function(val, flags){
635
flags.alternate = true
636
}
637
638
var char_mapping = {
Mar 19, 2018
639
"s": str_format,
640
"d": num_format,
641
"i": num_format,
642
"u": num_format,
643
"o": octal_format,
644
"r": repr_format,
645
"a": ascii_format,
646
"g": function(val, flags){
647
return floating_point_format(val, false, flags)
648
},
649
"G": function(val, flags){return floating_point_format(val, true, flags)},
650
"f": function(val, flags){
651
return floating_point_decimal_format(val, false, flags)
652
},
653
"F": function(val, flags){
654
return floating_point_decimal_format(val, true, flags)
655
},
656
"e": function(val, flags){
657
return floating_point_exponential_format(val, false, flags)
658
},
659
"E": function(val, flags){
660
return floating_point_exponential_format(val, true, flags)
661
},
662
"x": function(val, flags){return signed_hex_format(val, false, flags)},
663
"X": function(val, flags){return signed_hex_format(val, true, flags)},
664
"c": single_char_format,
665
"0": function(val, flags){return num_flag("0", flags)},
666
"1": function(val, flags){return num_flag("1", flags)},
667
"2": function(val, flags){return num_flag("2", flags)},
668
"3": function(val, flags){return num_flag("3", flags)},
669
"4": function(val, flags){return num_flag("4", flags)},
670
"5": function(val, flags){return num_flag("5", flags)},
671
"6": function(val, flags){return num_flag("6", flags)},
672
"7": function(val, flags){return num_flag("7", flags)},
673
"8": function(val, flags){return num_flag("8", flags)},
674
"9": function(val, flags){return num_flag("9", flags)},
675
"-": neg_flag,
676
" ": space_flag,
677
"+": sign_flag,
678
".": decimal_point_flag,
679
"#": alternate_flag
680
}
681
682
// exception thrown when an unsupported char is encountered in legacy format
Mar 19, 2018
683
var UnsupportedChar = function(){
684
this.name = "UnsupportedChar"
685
}
686
str
Feb 10, 2018
687
str.__mod__ = function(self, args) {
689
var length = self.length,
Mar 19, 2018
690
pos = 0 | 0,
691
argpos = null,
692
getitem
Mar 19, 2018
693
if(_b_.isinstance(args, _b_.tuple)){
694
argpos = 0 | 0
Mar 19, 2018
696
getitem = _b_.getattr(args, "__getitem__", _b_.None)
697
}
698
var ret = ''
699
var $get_kwarg_string = function(s) {
700
// returns [self, newpos]
701
++pos
702
var rslt = kwarg_key.exec(s.substring(newpos))
Mar 19, 2018
703
if(! rslt){
704
throw _b_.ValueError.$factory("incomplete format key")
705
}
706
var key = rslt[1]
707
newpos += rslt[0].length
Mar 23, 2018
708
try{
709
var self = getitem(key)
Mar 19, 2018
710
}catch(err){
711
if(err.name === "KeyError"){
712
throw err
713
}
714
throw _b_.TypeError.$factory("format requires a mapping")
716
return get_string_value(s, self)
717
}
718
719
var $get_arg_string = function(s) {
720
// returns [self, newpos]
721
var self
723
// non-tuple args
Mar 19, 2018
724
if(argpos === null){
725
// args is the value
Mar 19, 2018
727
}else{
728
self = args[argpos++]
Mar 19, 2018
729
if(self === undefined){
730
throw _b_.TypeError.$factory(
731
"not enough arguments for format string")
Sep 5, 2014
732
}
733
}
734
return get_string_value(s, self)
736
var get_string_value = function(s, self) {
737
// todo: get flags, type
738
// todo: string value based on flags, type, value
Mar 19, 2018
739
var flags = {"pad_char": " "}
740
do{
741
var func = char_mapping[s[newpos]]
Mar 23, 2018
742
try{
Mar 19, 2018
743
if(func === undefined){
744
throw new UnsupportedChar()
Mar 19, 2018
745
}else{
746
var ret = func(self, flags)
Mar 19, 2018
747
if(ret !== undefined){
748
return ret
749
}
750
++newpos
751
}
Mar 19, 2018
752
}catch (err){
753
if(err.name == "UnsupportedChar"){
754
invalid_char = s[newpos]
Mar 19, 2018
755
if(invalid_char === undefined){
756
throw _b_.ValueError.$factory("incomplete format")
Mar 19, 2018
758
throw _b_.ValueError.$factory(
759
"unsupported format character '" + invalid_char +
760
"' (0x" + invalid_char.charCodeAt(0).toString(16) +
761
") at index " + newpos)
762
}else if(err.name === "NotANumber"){
763
var try_char = s[newpos],
764
cls = self.__class__
765
if(!cls){
766
if(typeof(self) === "string"){
767
cls = "str"
768
}else{
769
cls = typeof(self)
Mar 19, 2018
771
}else{
Mar 19, 2018
774
throw _b_.TypeError.$factory("%" + try_char +
775
" format: a number is required, not " + cls)
776
}else{
777
throw err
778
}
Sep 5, 2014
779
}
Mar 19, 2018
780
}while (true)
Sep 5, 2014
781
}
782
var nbph = 0 // number of placeholders
Mar 19, 2018
783
do{
784
var newpos = self.indexOf("%", pos)
785
if(newpos < 0){
786
ret += self.substring(pos)
787
break
788
}
789
ret += self.substring(pos, newpos)
790
++newpos
Mar 19, 2018
791
if(newpos < length){
792
if(self[newpos] === "%"){
793
ret += "%"
794
}else{
Mar 19, 2018
796
if(self[newpos] === "("){
797
++newpos
798
ret += $get_kwarg_string(self)
Mar 23, 2018
799
}else{
800
ret += $get_arg_string(self)
801
}
802
}
Mar 19, 2018
803
}else{
804
// % at end of string
805
throw _b_.ValueError.$factory("incomplete format")
806
}
807
pos = newpos + 1
Mar 19, 2018
808
}while(pos < length)
809
810
if(argpos !== null){
811
if(args.length > argpos){
812
throw _b_.TypeError.$factory(
813
"not enough arguments for format string")
814
}else if(args.length < argpos){
815
throw _b_.TypeError.$factory(
816
"not all arguments converted during string formatting")
Mar 19, 2018
818
}else if(nbph == 0){
819
throw _b_.TypeError.$factory(
820
"not all arguments converted during string formatting")
Sep 5, 2014
824
str
Feb 10, 2018
825
str.__mro__ = [object]
Sep 5, 2014
826
str
Feb 10, 2018
827
str.__mul__ = function(){
Mar 19, 2018
828
var $ = $B.args("__mul__", 2, {self: null, other: null},
829
["self", "other"], arguments, {}, null, null)
830
if(! isinstance($.other, _b_.int)){throw _b_.TypeError.$factory(
831
"Can't multiply sequence by non-int of type '" +
Mar 19, 2018
833
var $res = ""
834
for(var i = 0; i< $.other; i++){$res += $.self.valueOf()}
Sep 5, 2014
835
return $res
836
}
837
Mar 19, 2018
838
str.__ne__ = function(self,other){return other !== self.valueOf()}
Sep 5, 2014
839
str
Feb 10, 2018
840
str.__repr__ = function(self){
842
// escape the escape char
843
res = self.replace(/\\/g, "\\\\")
844
// special cases
845
res = res.replace(new RegExp("\u0007", "g"), "\\x07").
846
replace(new RegExp("\b", "g"), "\\x08").
847
replace(new RegExp("\f", "g"), "\\x0c").
848
replace(new RegExp("\n", "g"), "\\n").
849
replace(new RegExp("\r", "g"), "\\r").
850
replace(new RegExp("\t", "g"), "\\t")
Mar 27, 2019
851
852
res = res.replace(combining_re, "\u200B$1")
Mar 19, 2018
853
if(res.search('"') == -1 && res.search("'") == -1){
854
return "'" + res + "'"
855
}else if(self.search('"') == -1){
856
return '"' + res + '"'
857
}
858
var qesc = new RegExp("'", "g") // to escape single quote
859
res = "'" + res.replace(qesc, "\\'") + "'"
Sep 5, 2014
860
return res
861
}
862
Mar 19, 2018
863
str.__setitem__ = function(self, attr, value){
864
throw _b_.TypeError.$factory(
865
"'str' object does not support item assignment")
Sep 5, 2014
866
}
Mar 27, 2019
867
var combining = []
868
for(var cp = 0x300; cp <= 0x36F; cp++){
869
combining.push(String.fromCharCode(cp))
870
}
871
var combining_re = new RegExp("(" + combining.join("|") + ")")
str
Feb 10, 2018
873
str.__str__ = function(self){
Mar 27, 2019
874
return self.replace(combining_re, "\u200B$1")
Sep 5, 2014
875
}
Mar 19, 2018
876
str.toString = function(){return "string!"}
Sep 5, 2014
877
878
// generate comparison methods
879
var $comp_func = function(self,other){
880
if(typeof other !== "string"){return _b_.NotImplemented}
Sep 5, 2014
881
return self > other
882
}
Mar 19, 2018
883
$comp_func += "" // source code
884
var $comps = {">": "gt", ">=": "ge", "<": "lt", "<=": "le"}
Sep 5, 2014
885
for(var $op in $comps){
Mar 19, 2018
886
eval("str.__" + $comps[$op] + '__ = ' + $comp_func.replace(/>/gm,$op))
Sep 5, 2014
887
}
888
889
// add "reflected" methods
str
Feb 10, 2018
890
$B.make_rmethods(str)
Sep 5, 2014
891
892
// unsupported operations
Mar 19, 2018
893
var $notimplemented = function(self, other){
894
throw NotImplementedError.$factory(
895
"OPERATOR not implemented for class str")
Sep 5, 2014
896
}
897
898
str.capitalize = function(self){
899
var $ = $B.args("capitalize", 1, {self}, ["self"],
900
arguments, {}, null, null)
901
if(self.length == 0){return ""}
902
return self.charAt(0).toUpperCase() + self.substr(1)
903
}
904
905
str.casefold = function(self){
906
var $ = $B.args("casefold", 1, {self}, ["self"],
907
arguments, {}, null, null),
908
res = "",
909
char,
910
cf
911
for(var i = 0, len = self.length; i < len; i++){
912
char = self.charCodeAt(i)
913
cf = $B.unicode_casefold[char]
914
if(cf){
915
cf.forEach(function(cp){
916
res += String.fromCharCode(cp)
917
})
918
}else{
919
res += self.charAt(i).toLowerCase()
920
}
921
}
922
return res
923
}
Sep 5, 2014
924
Mar 19, 2018
925
str.center = function(){
926
var $ = $B.args("center", 3, {self: null, width: null, fillchar: null},
927
["self", "width", "fillchar"],
928
arguments, {fillchar:" "}, null, null),
929
self = $.self
Mar 19, 2018
931
if($.width <= self.length) {return self}
Mar 19, 2018
933
var pad = parseInt(($.width - self.length) / 2),
934
res = $.fillchar.repeat(pad)
Sep 5, 2014
935
res += self + res
Mar 19, 2018
936
if(res.length < $.width){res += $.fillchar}
Sep 5, 2014
937
return res
938
}
939
str
Feb 10, 2018
940
str.count = function(){
Mar 19, 2018
941
var $ = $B.args("count", 4, {self:null, sub:null, start:null, stop:null},
942
["self", "sub", "start", "stop"], arguments, {start:null, stop:null},
Mar 19, 2018
944
if(!(typeof $.sub == "string")){throw _b_.TypeError.$factory(
945
"Can't convert '" + $B.class_name($.sub) +
Mar 19, 2018
946
"' object to str implicitly")}
Mar 19, 2018
948
if($.start !== null){
Mar 19, 2018
950
if($.stop !== null){_slice = _b_.slice.$factory($.start, $.stop)}
951
else{_slice = _b_.slice.$factory($.start, $.self.length)}
str
Feb 10, 2018
952
substr = str.__getitem__.apply(null, [$.self].concat(_slice))
Mar 19, 2018
954
if($.self.length + $.sub.length == 0){return 1}
Mar 19, 2018
956
if($.sub.length == 0){
957
if($.start == $.self.length){return 1}
958
else if(substr.length == 0){return 0}
959
return substr.length + 1
Mar 19, 2018
961
var n = 0,
962
pos = 0
963
while(pos < substr.length){
964
pos = substr.indexOf($.sub, pos)
965
if(pos >= 0){n++; pos += $.sub.length}
966
else{break}
Sep 5, 2014
967
}
968
return n
969
}
970
971
str.encode = function(){
972
var $ = $B.args("encode", 3, {self: null, encoding: null, errors: null},
973
["self", "encoding", "errors"], arguments,
974
{encoding: "utf-8", errors: "strict"}, null, null)
975
if($.encoding == "rot13" || $.encoding == "rot_13"){
976
// Special case : returns a string
Mar 19, 2018
977
var res = ""
978
for(var i = 0, len = $.self.length; i < len ; i++){
979
var char = $.self.charAt(i)
Mar 19, 2018
980
if(("a" <= char && char <= "m") || ("A" <= char && char <= "M")){
981
res += String.fromCharCode(String.charCodeAt(char) + 13)
982
}else if(("m" < char && char <= "z") ||
983
("M" < char && char <= "Z")){
984
res += String.fromCharCode(String.charCodeAt(char) - 13)
985
}else{res += char}
986
}
987
return res
988
}
989
return _b_.bytes.__new__(_b_.bytes, $.self, $.encoding, $.errors)
Sep 5, 2014
990
}
991
str
Feb 10, 2018
992
str.endswith = function(){
993
// Return True if the string ends with the specified suffix, otherwise
994
// return False. suffix can also be a tuple of suffixes to look for.
995
// With optional start, test beginning at that position. With optional
Sep 5, 2014
996
// end, stop comparing at that position.
Mar 19, 2018
997
var $ = $B.args("endswith", 4,
998
{self:null, suffix:null, start:null, end:null},
Mar 19, 2018
999
["self", "suffix", "start", "end"],
1000
arguments, {start: 0, end: null}, null, null)
Sep 20, 2015
1001
1002
normalize_start_end($)
1003
1004
var suffixes = $.suffix
Mar 19, 2018
1005
if(! isinstance(suffixes,_b_.tuple)){suffixes = [suffixes]}
Mar 19, 2018
1007
var s = $.self.substring($.start, $.end)
1008
for(var i = 0, len = suffixes.length; i < len; i++){
1009
var suffix = suffixes[i]
Mar 19, 2018
1010
if(! _b_.isinstance(suffix, str)){throw _b_.TypeError.$factory(
Sep 20, 2015
1011
"endswith first arg must be str or a tuple of str, not int")}
Mar 19, 2018
1012
if(suffix.length <= s.length &&
1013
s.substr(s.length - suffix.length) == suffix){return true}
Sep 5, 2014
1014
}
1015
return false
1016
}
1017
str
Feb 10, 2018
1018
str.expandtabs = function(self, tabsize) {
Mar 19, 2018
1019
var $ = $B.args("expandtabs", 2, {self: null, tabsize: null},
1020
["self", "tabsize"], arguments, {tabsize: 8}, null, null)
1021
var s = $B.$GetInt($.tabsize),
1022
col = 0,
1023
pos = 0,
1024
res = ""
1025
if(s == 1){return self.replace(/\t/g," ")}
1026
while(pos < self.length){
1027
var car = self.charAt(pos)
1028
switch(car){
Mar 19, 2018
1029
case "\t":
Mar 21, 2018
1030
while(col % s > 0){res += " "; col++}
Mar 19, 2018
1032
case "\r":
1033
case "\n":
1034
res += car
1035
col = 0
1036
break
1037
default:
1038
res += car
1039
col++
1040
break
1041
}
1042
pos++
1043
}
Sep 5, 2014
1046
}
1047
str
Feb 10, 2018
1048
str.find = function(){
1049
// Return the lowest index in the string where substring sub is found,
1050
// such that sub is contained in the slice s[start:end]. Optional
1051
// arguments start and end are interpreted as in slice notation.
Sep 5, 2014
1052
// Return -1 if sub is not found.
Mar 19, 2018
1053
var $ = $B.args("str.find", 4,
1054
{self: null, sub: null, start: null, end: null},
1055
["self", "sub", "start", "end"],
1056
arguments, {start: 0, end: null}, null, null)
1057
check_str($.sub)
Mar 19, 2018
1060
if(!isinstance($.start, _b_.int)||!isinstance($.end, _b_.int)){
1061
throw _b_.TypeError.$factory("slice indices must be " +
1062
"integers or None or have an __index__ method")}
1063
// Can't use string.substring(start, end) because if end < start,
1064
// Javascript transforms it into substring(end, start)...
1065
var s = ""
1066
for(var i = $.start; i < $.end; i++){
1067
s += $.self.charAt(i)
1068
}
Mar 19, 2018
1070
if($.sub.length == 0 && $.start == $.self.length){return $.self.length}
1071
if(s.length + $.sub.length == 0){return -1}
Mar 19, 2018
1073
var last_search = s.length - $.sub.length
1074
for(var i = 0; i <= last_search; i++){
1075
if(s.substr(i, $.sub.length) == $.sub){return $.start + i}
Sep 5, 2014
1076
}
Sep 5, 2014
1078
}
1079
1080
// Next function used by method .format()
1081
1082
$B.parse_format = function(fmt_string){
Sep 5, 2014
1083
1084
// Parse a "format string", as described in the Python documentation
1085
// Return a format object. For the format string
1086
// a.x[z]!r:...
1087
// the object has attributes :
1088
// - name : "a"
1089
// - name_ext : [".x", "[z]"]
1090
// - conv : r
1091
// - spec : rest of string after :
Sep 5, 2014
1092
Mar 19, 2018
1093
var elts = fmt_string.split(":"),
1094
name,
1095
conv,
1096
spec,
Mar 19, 2018
1097
name_ext = []
Mar 19, 2018
1098
if(elts.length == 1){
1099
// No : in the string : it only contains a name
1100
name = fmt_string
1101
}else{
1102
// name is before the first ":"
1103
// spec (the format specification) is after
1104
name = elts[0]
Mar 19, 2018
1105
spec = elts.splice(1).join(":")
Mar 19, 2018
1108
var elts = name.split("!")
1109
if(elts.length > 1){
1110
name = elts[0]
1111
conv = elts[1] // conversion flag
Sep 5, 2014
1113
Mar 19, 2018
1114
if(name !== undefined){
1115
// "name' may be a subscription or attribute
1116
// Put these "extensions" in the list "name_ext"
1117
function name_repl(match){
1118
name_ext.push(match)
Mar 19, 2018
1119
return ""
1120
}
1121
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1122
name = name.replace(name_ext_re, name_repl)
1123
}
Sep 5, 2014
1124
1125
return {name: name, name_ext: name_ext,
1126
conv: conv, spec: spec || "", string: fmt_string}
Sep 5, 2014
1128
1129
$B.split_format = function(self){
1130
// Parse self to detect formatting instructions
1131
// Create a list "parts" made of sections of the string :
1132
// - elements of even rank are literal text
1133
// - elements of odd rank are "format objects", built from the
1134
// format strings in self (of the form {...})
Mar 19, 2018
1135
var pos = 0,
1136
_len = self.length,
Mar 19, 2018
1138
text = "",
1139
parts = [],
1140
rank = 0
1141
while(pos < _len){
1142
car = self.charAt(pos)
Mar 21, 2018
1143
if(car == "{" && self.charAt(pos + 1) == "{"){
1144
// replace {{ by literal {
Mar 19, 2018
1145
text += "{"
1146
pos += 2
1147
}else if(car == "}" && self.charAt(pos + 1) == "}"){
1148
// replace }} by literal }
Mar 19, 2018
1149
text += "}"
1150
pos += 2
1151
}else if(car == "{"){
1152
// Start of a format string
1154
// Store current literal text
1155
parts.push(text)
1156
1157
// Search the end of the format string, ie the } closing the
1158
// opening {. Since the string can contain other pairs {} for
1159
// nested formatting, an integer nb is incremented for each { and
1160
// decremented for each } ; the end of the format string is
Mar 19, 2018
1161
// reached when nb == 0
1162
var end = pos + 1,
1163
nb = 1
1164
while(end < _len){
1165
if(self.charAt(end) == "{"){nb++; end++}
1166
else if(self.charAt(end) == "}"){
1167
nb--; end++
1168
if(nb == 0){
1169
// End of format string
Mar 19, 2018
1170
var fmt_string = self.substring(pos + 1, end - 1)
1171
1172
// Create a format object, by function parse_format
1173
var fmt_obj = $B.parse_format(fmt_string)
1174
fmt_obj.raw_name = fmt_obj.name
1175
fmt_obj.raw_spec = fmt_obj.spec
1176
1177
// If no name is explicitely provided, use the rank
1178
if(!fmt_obj.name){
Mar 19, 2018
1179
fmt_obj.name = rank + ""
Sep 5, 2014
1182
Mar 19, 2018
1183
if(fmt_obj.spec !== undefined){
1184
// "spec" may contain "nested replacement fields"
1185
// Replace empty fields by the rank in positional
1186
// arguments
1187
function replace_nested(name, key){
1188
if(key == ""){
1189
// Use implicit rank
1190
return "{" + rank++ + "}"
1194
fmt_obj.spec = fmt_obj.spec.replace(/\{(.*?)\}/g,
1195
replace_nested)
1196
}
1198
// Store format object in list "parts"
1199
parts.push(fmt_obj)
Mar 19, 2018
1200
text = ""
1201
break
1202
}
1203
}else{end++}
Sep 5, 2014
1204
}
Mar 19, 2018
1205
if(nb > 0){throw ValueError.$factory("wrong format " + self)}
Mar 19, 2018
1207
}else{text += car; pos++}
Sep 5, 2014
1208
}
1209
if(text){parts.push(text)}
1210
return parts
1211
}
1212
1213
str.format = function(self) {
1214
var $ = $B.args("format", 1, {self: null}, ["self"],
1215
arguments, {}, "$args", "$kw")
1216
1217
var parts = $B.split_format($.self)
1218
1219
// Apply formatting to the values passed to format()
Mar 19, 2018
1220
var res = "",
1221
fmt
Mar 19, 2018
1223
for(var i = 0; i < parts.length; i++){
1224
// Literal text is added unchanged
Mar 19, 2018
1225
if(typeof parts[i] == "string"){res += parts[i]; continue}
1227
// Format objects
1228
fmt = parts[i]
1229
1230
if(fmt.spec !== undefined){
1231
// "spec" may contain "nested replacement fields"
1232
// In this case, evaluate them using the positional
1233
// or keyword arguments passed to format()
1234
function replace_nested(name, key){
1235
if(/\d+/.exec(key)){
1236
// If key is numeric, search in positional
1237
// arguments
1238
return _b_.tuple.__getitem__($.$args,
1239
parseInt(key))
1240
}else{
1241
// Else try in keyword arguments
1242
return _b_.dict.__getitem__($.$kw, key)
1243
}
1244
}
1245
fmt.spec = fmt.spec.replace(/\{(.*?)\}/g,
1246
replace_nested)
1247
}
Mar 21, 2018
1248
if(fmt.name.charAt(0).search(/\d/) > -1){
1249
// Numerical reference : use positional arguments
1250
var pos = parseInt(fmt.name),
Feb 11, 2018
1251
value = _b_.tuple.__getitem__($.$args, pos)
1252
}else{
1253
// Use keyword arguments
Feb 11, 2018
1254
var value = _b_.dict.__getitem__($.$kw, fmt.name)
1255
}
1256
// If name has extensions (attributes or subscriptions)
Mar 19, 2018
1257
for(var j = 0; j < fmt.name_ext.length; j++){
1258
var ext = fmt.name_ext[j]
Mar 19, 2018
1259
if(ext.charAt(0) == "."){
1260
// Attribute
1261
value = _b_.getattr(value, ext.substr(1))
1262
}else{
1263
// Subscription
Mar 19, 2018
1264
var key = ext.substr(1, ext.length - 2)
1265
// An index made of digits is transformed into an integer
Mar 19, 2018
1266
if(key.charAt(0).search(/\d/) > -1){key = parseInt(key)}
1267
value = _b_.getattr(value, "__getitem__")(key)
Feb 12, 2018
1270
1271
// If the conversion flag is set, first call a function to convert
1272
// the value
Mar 19, 2018
1273
if(fmt.conv == "a"){value = _b_.ascii(value)}
1274
else if(fmt.conv == "r"){value = _b_.repr(value)}
1275
else if(fmt.conv == "s"){value = _b_.str.$factory(value)}
1277
// Call attribute __format__ to perform the actual formatting
1278
if(value.$is_class || value.$factory){
1279
// For classes, don't use the class __format__ method
1280
res += value.__class__.__format__(value, fmt.spec)
Mar 19, 2018
1282
res += _b_.getattr(value, "__format__")(fmt.spec)
Sep 5, 2014
1284
}
Sep 5, 2014
1286
}
1287
str
Feb 10, 2018
1288
str.format_map = function(self) {
Mar 19, 2018
1289
throw NotImplementedError.$factory(
1290
"function format_map not implemented yet")
Sep 5, 2014
1291
}
1292
str
Feb 10, 2018
1293
str.index = function(self){
Sep 5, 2014
1294
// Like find(), but raise ValueError when the substring is not found.
1295
var res = str.find.apply(null, arguments)
Mar 19, 2018
1296
if(res === -1){throw _b_.ValueError.$factory("substring not found")}
Sep 5, 2014
1297
return res
1298
}
1299
1300
str.isascii = function(self){
1301
/* Return true if the string is empty or all characters in the string are
1302
ASCII, false otherwise. ASCII characters have code points in the range
1303
U+0000-U+007F. */
1304
for(var i = 0, len = self.length; i < len; i++){
1305
if(self.charCodeAt(i) > 127){return false}
1306
}
1307
return true
1308
}
1309
1310
str.isalnum = function(self){
1311
/* Return true if all characters in the string are alphanumeric and there
1312
is at least one character, false otherwise. A character c is alphanumeric
1313
if one of the following returns True: c.isalpha(), c.isdecimal(),
1314
c.isdigit(), or c.isnumeric(). */
1315
var $ = $B.args("isalnum", 1, {self: null}, ["self"],
1316
arguments, {}, null, null),
1317
char
1318
for(var i = 0, len = self.length; i < len; i++){
1319
char = self.charCodeAt(i)
1320
if(unicode_tables.Ll[char] ||
1321
unicode_tables.Lu[char] ||
1322
unicode_tables.Lm[char] ||
1323
unicode_tables.Lt[char] ||
1324
unicode_tables.Lo[char] ||
1325
unicode_tables.Nd[char] ||
1326
unicode_tables.digits[char] ||
1327
unicode_tables.numeric[char]){
1328
continue
1329
}
1330
return false
1331
}
1332
return true
1333
}
1334
1335
str.isalpha = function(self){
1336
/* Return true if all characters in the string are alphabetic and there is
1337
at least one character, false otherwise. Alphabetic characters are those
1338
characters defined in the Unicode character database as "Letter", i.e.,
1339
those with general category property being one of "Lm", "Lt", "Lu", "Ll",
1340
or "Lo". */
1341
var $ = $B.args("isalpha", 1, {self: null}, ["self"],
1342
arguments, {}, null, null),
1343
char
1344
for(var i = 0, len = self.length; i < len; i++){
1345
char = self.charCodeAt(i)
1346
if(unicode_tables.Ll[char] ||
1347
unicode_tables.Lu[char] ||
1348
unicode_tables.Lm[char] ||
1349
unicode_tables.Lt[char] ||
1350
unicode_tables.Lo[char]){
1351
continue
1352
}
1353
return false
1354
}
1355
return true
1356
}
1357
1358
str.isdecimal = function(self){
1359
/* Return true if all characters in the string are decimal characters and
1360
there is at least one character, false otherwise. Decimal characters are
1361
those that can be used to form numbers in base 10, e.g. U+0660,
1362
ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in
1363
the Unicode General Category "Nd". */
1364
var $ = $B.args("isdecimal", 1, {self: null}, ["self"],
1365
arguments, {}, null, null),
1366
char
1367
for(var i = 0, len = self.length; i < len; i++){
1368
char = self.charCodeAt(i)
1369
if(! unicode_tables.Nd[char]){
1370
return false
1371
}
1372
}
1373
return self.length > 0
1374
}
1375
1376
str.isdigit = function(self){
1377
/* Return true if all characters in the string are digits and there is at
1378
least one character, false otherwise. */
1379
var $ = $B.args("isdigit", 1, {self: null}, ["self"],
1380
arguments, {}, null, null),
1381
char
1382
for(var i = 0, len = self.length; i < len; i++){
1383
char = self.charCodeAt(i)
1384
if(! unicode_tables.digits[char]){
1385
return false
1386
}
1387
}
1388
return self.length > 0
1389
}
1390
1391
str.isidentifier = function(self){
1392
/* Return true if the string is a valid identifier according to the
1393
language definition. */
1394
var $ = $B.args("isidentifier", 1, {self: null}, ["self"],
1395
arguments, {}, null, null),
1396
char
1397
if(self.length == 0){return false}
1398
else if(unicode_tables.XID_Start[self.charCodeAt(0)] === undefined){
1399
return false
1400
}else{
1401
for(var i = 1, len = self.length; i < len; i++){
1402
if(unicode_tables.XID_Continue[self.charCodeAt(i)] === undefined){
1403
return false
1404
}
1405
}
1406
}
1407
return true
1408
}
1409
1410
str.islower = function(self){
1411
/* Return true if all cased characters 4 in the string are lowercase and
1412
there is at least one cased character, false otherwise. */
1413
var $ = $B.args("islower", 1, {self: null}, ["self"],
1414
arguments, {}, null, null),
1415
has_cased = false,
1416
char
1417
1418
for(var i = 0, len = self.length; i < len; i++){
1419
char = self.charCodeAt(i)
1420
if(unicode_tables.Ll[char]){has_cased = true; continue}
1421
else if(unicode_tables.Lu[char] || unicode_tables.Lt[char]){
1422
return false
1423
}
1424
}
1425
return has_cased
1426
}
1427
1428
str.isnumeric = function(self){
1429
/* Return true if all characters in the string are numeric characters, and
1430
there is at least one character, false otherwise. Numeric characters
1431
include digit characters, and all characters that have the Unicode numeric
1432
value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH. Formally, numeric
1433
characters are those with the property value Numeric_Type=Digit,
1434
Numeric_Type=Decimal or Numeric_Type=Numeric.*/
1435
var $ = $B.args("isnumeric", 1, {self: null}, ["self"],
1436
arguments, {}, null, null)
1437
for(var i = 0, len = self.length; i < len; i++){
1438
if(! unicode_tables.numeric[self.charCodeAt(i)]){
1439
return false
1440
}
1441
}
1442
return self.length > 0
1443
}
1444
1445
var printable,
1446
printable_gc = ['Cc', 'Cf', 'Co', 'Cs','Zl', 'Zp', 'Zs']
1447
1448
str.isprintable = function(self){
1449
/* Return true if all characters in the string are printable or the string
1450
is empty, false otherwise. Nonprintable characters are those characters
1451
defined in the Unicode character database as "Other" or "Separator",
1452
excepting the ASCII space (0x20) which is considered printable. */
1453
1454
// Set printable if not set yet
1455
if(printable === undefined){
1456
for(var i = 0; i < printable_gc.length; i++){
1457
var table = unicode_tables[printable_gc[i]]
1458
for(var cp in table){
1459
printable[cp] = true
1460
}
1461
}
1462
printable[32] = true
1463
}
1464
1465
var $ = $B.args("isprintable", 1, {self: null}, ["self"],
1466
arguments, {}, null, null),
1467
char,
1468
flag
1469
for(var i = 0, len = self.length; i < len; i++){
1470
char = self.charCodeAt(i)
1471
if(! printable[char]){
1472
return false
1473
}
1474
}
1475
return true
1476
}
1477
1478
str.isspace = function(self){
1479
/* Return true if there are only whitespace characters in the string and
1480
there is at least one character, false otherwise.
1481
1482
A character is whitespace if in the Unicode character database, either its
1483
general category is Zs ("Separator, space"), or its bidirectional class is
1484
one of WS, B, or S.*/
1485
var $ = $B.args("isspace", 1, {self: null}, ["self"],
1486
arguments, {}, null, null),
1487
char
1488
for(var i = 0, len = self.length; i < len; i++){
1489
char = self.charCodeAt(i)
1490
if(! unicode_tables.Zs[char] &&
1491
$B.unicode_bidi_whitespace.indexOf(char) == -1){
1492
return false
1493
}
1494
}
1495
return self.length > 0
1496
}
1497
1498
str.istitle = function(self){
1499
/* Return true if the string is a titlecased string and there is at least
1500
one character, for example uppercase characters may only follow uncased
1501
characters and lowercase characters only cased ones. Return false
1502
otherwise. */
1503
var $ = $B.args("istitle", 1, {self: null}, ["self"],
1504
arguments, {}, null, null)
1505
return self.length > 0 && str.title(self) == self
1506
}
1507
1508
str.isupper = function(self){
1509
/* Return true if all cased characters 4 in the string are lowercase and
1510
there is at least one cased character, false otherwise. */
1511
var $ = $B.args("islower", 1, {self: null}, ["self"],
1512
arguments, {}, null, null),
1513
has_cased = false,
1514
char
1515
1516
for(var i = 0, len = self.length; i < len; i++){
1517
char = self.charCodeAt(i)
1518
if(unicode_tables.Lu[char]){has_cased = true; continue}
1519
else if(unicode_tables.Ll[char] || unicode_tables.Lt[char]){
1520
return false
1521
}
1522
}
1523
return has_cased
1524
}
1525
1526
str
Feb 10, 2018
1527
str.join = function(){
Mar 19, 2018
1528
var $ = $B.args("join", 2, {self: null, iterable: null},
Mar 19, 2018
1529
["self", "iterable"], arguments, {}, null, null)
Mar 19, 2018
1531
var iterable = _b_.iter($.iterable),
Mar 19, 2018
1532
res = [],
Sep 5, 2014
1534
while(1){
1535
try{
1536
var obj2 = _b_.next(iterable)
Mar 19, 2018
1537
if(! isinstance(obj2, str)){throw _b_.TypeError.$factory(
1538
"sequence item " + count + ": expected str instance, " +
1539
$B.class_name(obj2) + " found")}
1540
res.push(obj2)
Sep 5, 2014
1541
}catch(err){
1542
if(_b_.isinstance(err, _b_.StopIteration)){
1543
break
1544
}
Sep 5, 2014
1545
else{throw err}
1546
}
1547
}
1548
return res.join($.self)
Sep 5, 2014
1549
}
1550
str
Feb 10, 2018
1551
str.ljust = function(self) {
Mar 19, 2018
1552
var $ = $B.args("ljust", 3, {self: null, width: null, fillchar:null},
1553
["self", "width", "fillchar"],
1554
arguments, {fillchar: " "}, null, null)
Mar 19, 2018
1556
if($.width <= self.length){return self}
1557
return self + $.fillchar.repeat($.width - self.length)
Sep 5, 2014
1558
}
1559
1560
str.lower = function(self){
1561
var $ = $B.args("lower", 1, {self: null}, ["self"],
1562
arguments, {}, null, null)
1563
return self.toLowerCase()
1564
}
1565
str
Feb 10, 2018
1566
str.lstrip = function(self,x){
Mar 19, 2018
1567
var $ = $B.args("lstrip", 2, {self: null, chars: null}, ["self", "chars"],
1568
arguments, {chars:_b_.None}, null, null)
1569
if($.chars === _b_.None){return $.self.trimLeft()}
1570
for(var i = 0; i < $.self.length; i++){
1571
if($.chars.indexOf($.self.charAt(i)) === -1){
1572
return $.self.substring(i)
Mar 19, 2018
1575
return ""
Sep 5, 2014
1576
}
1577
1578
// note, maketrans should be a static function.
str
Feb 10, 2018
1579
str.maketrans = function() {
Mar 19, 2018
1580
var $ = $B.args("maketrans", 3, {x: null, y: null, z: null},
1581
["x", "y", "z"], arguments, {y: null, z: null}, null, null)
Mar 19, 2018
1583
var _t = _b_.dict.$factory()
Mar 19, 2018
1585
if($.y === null && $.z === null){
1586
// If there is only one argument, it must be a dictionary mapping
1587
// Unicode ordinals (integers) or characters (strings of length 1) to
1588
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1589
// keys will then be converted to ordinals.
Mar 19, 2018
1590
if(! _b_.isinstance($.x, _b_.dict)){
1591
throw _b_.TypeError.$factory(
1592
"maketrans only argument must be a dict")
Feb 11, 2018
1594
var items = _b_.list.$factory(_b_.dict.items($.x))
Mar 19, 2018
1595
for(var i = 0, len = items.length; i < len; i++){
1596
var k = items[i][0],
1597
v = items[i][1]
1598
if(! _b_.isinstance(k, _b_.int)){
1599
if(_b_.isinstance(k, _b_.str) && k.length == 1){
1600
k = _b_.ord(k)
1601
}else{throw _b_.TypeError.$factory("dictionary key " + k +
1602
" is not int or 1-char string")}
1603
}
Mar 19, 2018
1604
if(v !== _b_.None && ! _b_.isinstance(v, [_b_.int, _b_.str])){
1605
throw _b_.TypeError.$factory("dictionary value " + v +
1606
" is not None, integer or string")
1607
}
1608
_b_.dict.$setitem(_t, k, v)
1609
}
1610
return _t
1611
}else{
1612
// If there are two arguments, they must be strings of equal length,
1613
// and in the resulting dictionary, each character in x will be mapped
1614
// to the character at the same position in y
Mar 19, 2018
1615
if(! (_b_.isinstance($.x, _b_.str) && _b_.isinstance($.y, _b_.str))){
1616
throw _b_.TypeError.$factory("maketrans arguments must be strings")
Mar 19, 2018
1617
}else if($.x.length !== $.y.length){
1618
throw _b_.TypeError.$factory(
1619
"maketrans arguments must be strings or same length")
1620
}else{
1621
var toNone = {}
Mar 19, 2018
1622
if($.z !== null){
1623
// If there is a third argument, it must be a string, whose
1624
// characters will be mapped to None in the result
Mar 19, 2018
1625
if(! _b_.isinstance($.z, _b_.str)){
1626
throw _b_.TypeError.$factory(
1627
"maketrans third argument must be a string")
Mar 19, 2018
1629
for(var i = 0, len = $.z.length; i < len; i++){
1630
toNone[_b_.ord($.z.charAt(i))] = true
1631
}
Mar 19, 2018
1633
for(var i = 0, len = $.x.length; i < len; i++){
1634
var key = _b_.ord($.x.charAt(i)),
1636
_b_.dict.$setitem(_t, key, value)
1637
}
1638
for(var k in toNone){
1639
_b_.dict.$setitem(_t, parseInt(k), _b_.None)
1640
}
1641
return _t
1642
}
1643
}
Sep 5, 2014
1644
}
1645
1646
str.maketrans.$type = "staticmethod"
1647
str
Feb 10, 2018
1648
str.partition = function() {
Mar 19, 2018
1649
var $ = $B.args("partition", 2, {self: null, sep: null}, ["self", "sep"],
1650
arguments, {}, null, null)
Mar 19, 2018
1651
if($.sep == ""){throw _b_.ValueError.$factory("empty separator")}
Mar 19, 2018
1652
check_str($.sep)
1653
var i = $.self.indexOf($.sep)
Mar 23, 2018
1654
if(i == -1){return _b_.tuple.$factory([$.self, "", ""])}
Mar 19, 2018
1655
return _b_.tuple.$factory([$.self.substring(0, i), $.sep,
1656
$.self.substring(i + $.sep.length)])
1657
}
1658
1659
function $re_escape(str){
1660
var specials = "[.*+?|()$^"
1661
for(var i = 0, len = specials.length; i < len; i++){
1662
var re = new RegExp("\\"+specials.charAt(i), "g")
1663
str = str.replace(re, "\\"+specials.charAt(i))
1664
}
1665
return str
Sep 5, 2014
1666
}
1667
str
Feb 10, 2018
1668
str.replace = function(self, old, _new, count) {
1669
// Replaces occurrences of 'old' by '_new'. Count references
1670
// the number of times to replace. In CPython, negative or undefined
1671
// values of count means replace all.
Mar 19, 2018
1672
var $ = $B.args("replace", 4,
1673
{self: null, old: null, $$new: null, count: null},
1674
["self", "old", "$$new", "count"],
1675
arguments, {count: -1}, null, null),
1676
count = $.count,
1677
self = $.self,
1678
old = $.old,
1679
_new = $.$$new
1680
// Validate type of old
1681
check_str(old)
1682
check_str(_new)
1683
// Validate instance type of 'count'
Mar 23, 2018
1684
if(! isinstance(count,[_b_.int, _b_.float])){
1685
throw _b_.TypeError.$factory("'" + $B.class_name(count) +
Mar 19, 2018
1686
"' object cannot be interpreted as an integer")
1687
}else if(isinstance(count, _b_.float)){
1688
throw _b_.TypeError.$factory("integer argument expected, got float")
1689
}
1690
if(count == 0){return self}
1691
if(count.__class__ == $B.long_int){count = parseInt(count.value)}
1692
if(old == ""){
1693
if(_new == ""){return self}
1694
if(self == ""){return _new}
1695
var elts = self.split("")
1696
if(count > -1 && elts.length >= count){
1697
var rest = elts.slice(count).join("")
1698
return _new + elts.slice(0, count).join(_new) + rest
1699
}else{return _new + elts.join(_new) + _new}
Mar 19, 2018
1701
var elts = str.split(self, old, count)
Sep 5, 2014
1702
}
Mar 19, 2018
1704
var res = self,
1705
pos = -1
1706
if(old.length == 0){
Mar 19, 2018
1708
for(var i = 0; i < elts.length; i++){
1709
res += elts[i] + _new
Mar 19, 2018
1711
return res + rest
Mar 19, 2018
1714
if(count < 0){count = res.length}
1715
while(count > 0){
1716
pos = res.indexOf(old, pos)
1717
if(pos < 0){break}
1718
res = res.substr(0, pos) + _new + res.substr(pos + old.length)
1719
pos = pos + _new.length
1720
count--
Mar 19, 2018
1722
return res
Sep 5, 2014
1723
}
1724
1725
str.rfind = function(self, substr){
1726
// Return the highest index in the string where substring sub is found,
1727
// such that sub is contained within s[start:end]. Optional arguments
Sep 5, 2014
1728
// start and end are interpreted as in slice notation. Return -1 on failure.
1729
if(arguments.length == 2 && typeof substr == "string"){
1730
return self.lastIndexOf(substr)
1731
}
Mar 19, 2018
1732
var $ = $B.args("rfind", 4,
Mar 19, 2018
1733
{self: null, sub: null, start: null, end: null},
1734
["self", "sub", "start", "end"],
1735
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
1736
1739
check_str($.sub)
Mar 19, 2018
1741
if($.sub.length == 0){
1742
if($.start > $.self.length){return -1}
1743
else{return $.self.length}
1744
}
1745
var sublen = $.sub.length
Mar 19, 2018
1747
for(var i = $.end - sublen; i >= $.start; i--){
1748
if($.self.substr(i, sublen) == $.sub){return i}
Sep 5, 2014
1751
}
1752
str
Feb 10, 2018
1753
str.rindex = function(){
Sep 5, 2014
1754
// Like rfind() but raises ValueError when the substring sub is not found
Mar 19, 2018
1755
var res = str.rfind.apply(null, arguments)
1756
if(res == -1){throw _b_.ValueError.$factory("substring not found")}
Sep 5, 2014
1757
return res
1758
}
1759
str
Feb 10, 2018
1760
str.rjust = function(self) {
Mar 19, 2018
1761
var $ = $B.args("rjust",3,
1762
{self: null, width: null, fillchar: null},
1763
["self", "width", "fillchar"],
1764
arguments, {fillchar: " "}, null, null)
Sep 5, 2014
1765
Mar 19, 2018
1766
if($.width <= self.length){return self}
Sep 5, 2014
1767
1768
return $.fillchar.repeat($.width - self.length) + self
Sep 5, 2014
1769
}
1770
str
Feb 10, 2018
1771
str.rpartition = function(self,sep) {
Mar 19, 2018
1772
var $ = $B.args("rpartition", 2, {self: null, sep: null}, ["self", "sep"],
1773
arguments, {}, null, null)
1774
check_str($.sep)
1775
var self = reverse($.self),
1776
sep = reverse($.sep)
Mar 19, 2018
1777
var items = str.partition(self, sep).reverse()
1778
for(var i = 0; i < items.length; i++){
1779
items[i] = items[i].split("").reverse().join("")
1780
}
1781
return items
Sep 5, 2014
1782
}
1783
str
Feb 10, 2018
1784
str.rsplit = function(self) {
Mar 19, 2018
1785
var $ = $B.args("rsplit", 3, {self: null, sep: null, maxsplit: null},
1786
["self", "sep", "maxsplit"], arguments,
1787
{sep: _b_.None, maxsplit: -1}, null, null),
1788
sep = $.sep
1789
1790
// Use split on the reverse of the string and of separator
1791
var rev_str = reverse($.self),
1792
rev_sep = sep === _b_.None ? sep : reverse($.sep),
str
Feb 10, 2018
1793
rev_res = str.split(rev_str, rev_sep, $.maxsplit)
1795
// Reverse the list, then each string inside the list
1796
rev_res.reverse()
Mar 19, 2018
1797
for(var i = 0; i < rev_res.length; i++){
1798
rev_res[i] = reverse(rev_res[i])
Sep 5, 2014
1801
}
1802
Mar 19, 2018
1803
str.rstrip = function(self, x){
1804
var $ = $B.args("rstrip", 2, {self: null, chars: null}, ["self", "chars"],
Mar 19, 2018
1805
arguments, {chars: _b_.None}, null, null)
1806
if($.chars === _b_.None){return $.self.trimRight()}
Mar 21, 2018
1807
for(var j = $.self.length - 1; j >= 0; j--){
Mar 19, 2018
1808
if($.chars.indexOf($.self.charAt(j)) == -1){
1809
return $.self.substring(0, j + 1)
Mar 19, 2018
1812
return ""
Sep 5, 2014
1813
}
1814
str
Feb 10, 2018
1815
str.split = function(){
Mar 19, 2018
1816
var $ = $B.args("split", 3, {self: null, sep: null, maxsplit: null},
1817
["self", "sep", "maxsplit"], arguments,
1818
{sep: _b_.None, maxsplit: -1}, null, null),
1819
sep = $.sep,
1820
maxsplit = $.maxsplit,
1821
self = $.self,
1822
pos = 0
1823
if(maxsplit.__class__ === $B.long_int){maxsplit = parseInt(maxsplit.value)}
1824
if(sep == ""){throw _b_.ValueError.$factory("empty separator")}
1825
if(sep === _b_.None){
Sep 5, 2014
1826
var res = []
Mar 19, 2018
1827
while(pos < self.length && self.charAt(pos).search(/\s/) > -1){pos++}
1828
if(pos === self.length - 1){return [self]}
1829
var name = ""
Sep 5, 2014
1830
while(1){
Mar 19, 2018
1831
if(self.charAt(pos).search(/\s/) == -1){
1832
if(name == ""){name = self.charAt(pos)}
1833
else{name += self.charAt(pos)}
Sep 5, 2014
1834
}else{
Mar 19, 2018
1835
if(name !== ""){
Sep 5, 2014
1836
res.push(name)
Mar 19, 2018
1837
if(maxsplit !== -1 && res.length == maxsplit + 1){
Sep 5, 2014
1838
res.pop()
Mar 19, 2018
1839
res.push(name + self.substr(pos))
Sep 5, 2014
1840
return res
1841
}
Mar 19, 2018
1842
name = ""
Sep 5, 2014
1843
}
1844
}
1845
pos++
Mar 19, 2018
1846
if(pos > self.length - 1){
Sep 5, 2014
1847
if(name){res.push(name)}
1848
break
1849
}
1850
}
1851
return res
1852
}else{
Mar 19, 2018
1853
var res = [],
1854
s = "",
1855
seplen = sep.length
1856
if(maxsplit == 0){return [self]}
1857
while(pos < self.length){
1858
if(self.substr(pos, seplen) == sep){
Mar 19, 2018
1861
if(maxsplit > -1 && res.length >= maxsplit){
1862
res.push(self.substr(pos))
1863
return res
1864
}
Mar 19, 2018
1865
s = ""
1866
}else{
1867
s += self.charAt(pos)
1868
pos++
Sep 5, 2014
1869
}
1870
}
Sep 5, 2014
1873
}
1874
}
1875
str
Feb 10, 2018
1876
str.splitlines = function(self){
Mar 19, 2018
1877
var $ = $B.args("splitlines", 2, {self: null, keepends: null},
Mar 19, 2018
1878
["self", "keepends"], arguments, {keepends: false}, null, null)
1879
if(! _b_.isinstance($.keepends, [_b_.bool, _b_.int])){
1880
throw _b_.TypeError.$factory("integer argument expected, got " +
1881
$B.get_class($.keepends).__name)
1882
}
1883
var keepends = _b_.int.$factory($.keepends)
1884
// Remove trailing line breaks
1885
if(keepends){
1886
var res = [],
Mar 19, 2018
1887
start = pos,
1888
pos = 0,
1889
self = $.self
1890
while(pos < self.length){
1891
if(self.substr(pos, 2) == "\r\n"){
1892
res.push(self.substring(start, pos + 2))
1893
start = pos + 2
1894
pos = start
Mar 19, 2018
1895
}else if(self.charAt(pos) == "\r" || self.charAt(pos) == "\n"){
1896
res.push(self.substring(start, pos + 1))
1897
start = pos + 1
1898
pos = start
1899
}else{pos++}
1900
}
1901
var rest = self.substr(start)
1902
if(rest){res.push(rest)}
1903
return res
1904
}else{
Mar 19, 2018
1905
var self = $.self.replace(/[\r\n]$/, "")
1906
return self.split(/\n|\r\n|\r/)
1907
}
1908
}
Sep 5, 2014
1909
str
Feb 10, 2018
1910
str.startswith = function(){
1911
// Return True if string starts with the prefix, otherwise return False.
1912
// prefix can also be a tuple of prefixes to look for. With optional
1913
// start, test string beginning at that position. With optional end,
Sep 5, 2014
1914
// stop comparing string at that position.
Mar 19, 2018
1915
var $ = $B.args("startswith", 4,
1916
{self: null, prefix: null, start: null, end: null},
1917
["self", "prefix", "start", "end"],
1918
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
1919
1920
normalize_start_end($)
1921
1922
var prefixes = $.prefix
Mar 19, 2018
1923
if(! isinstance(prefixes, _b_.tuple)){prefixes = [prefixes]}
Mar 19, 2018
1925
var s = $.self.substring($.start, $.end)
1926
for(var i = 0, len = prefixes.length; i < len; i++){
1927
var prefix = prefixes[i]
Mar 19, 2018
1928
if(! _b_.isinstance(prefix, str)){throw _b_.TypeError.$factory(
1929
"endswith first arg must be str or a tuple of str, not int")}
Mar 19, 2018
1930
if(s.substr(0, prefix.length) == prefix){return true}
Sep 5, 2014
1931
}
1932
return false
1933
Sep 5, 2014
1934
}
1935
str
Feb 10, 2018
1936
str.strip = function(){
Mar 19, 2018
1937
var $ = $B.args("strip", 2, {self: null, chars: null}, ["self", "chars"],
1938
arguments, {chars: _b_.None}, null, null)
1939
if($.chars === _b_.None){return $.self.trim()}
1940
for(var i = 0; i < $.self.length; i++){
1941
if($.chars.indexOf($.self.charAt(i)) == -1){
1942
break
Mar 19, 2018
1945
for(var j = $.self.length - 1; j >= i; j--){
1946
if($.chars.indexOf($.self.charAt(j)) == -1){
1947
break
Mar 19, 2018
1950
return $.self.substring(i, j + 1)
Sep 5, 2014
1951
}
1952
1953
str.swapcase = function(self){
1954
var $ = $B.args("swapcase", 1, {self}, ["self"],
1955
arguments, {}, null, null),
1956
res = "",
1957
char
1958
1959
for(var i = 0, len = self.length; i < len; i++){
1960
char = self.charCodeAt(i)
1961
if(unicode_tables.Ll[char]){
1962
res += self.charAt(i).toUpperCase()
1963
}else if(unicode_tables.Lu[char]){
1964
res += self.charAt(i).toLowerCase()
1965
}else{
1966
res += self.charAt(i)
1967
}
1968
}
1969
return res
1970
}
1971
1972
str.title = function(self){
1973
var $ = $B.args("title", 1, {self}, ["self"],
1974
arguments, {}, null, null),
1975
state,
1976
char,
1977
res = ""
1978
for(var i = 0, len = self.length; i < len; i++){
1979
char = self.charCodeAt(i)
1980
if(unicode_tables.Ll[char]){
1981
if(! state){
1982
res += self.charAt(i).toUpperCase()
1983
state = "word"
1984
}else{
1985
res += self.charAt(i)
1986
}
1987
}else if(unicode_tables.Lu[char] || unicode_tables.Lt[char]){
1988
res += state ? self.charAt(i).toLowerCase() : self.charAt(i)
1989
state = "word"
1990
}else{
1991
state = null
1992
res += self.charAt(i)
1993
}
1994
}
1995
return res
1996
}
1997
1998
str.translate = function(self, table){
Mar 19, 2018
1999
var res = [],
2000
getitem = $B.$getattr(table, "__getitem__")
2001
for(var i = 0, len = self.length; i < len; i++){
2002
try{
2003
var repl = getitem(self.charCodeAt(i))
2004
if(repl !== _b_.None){
2005
res.push(String.fromCharCode(repl))
2006
}
2007
}catch(err){
2008
res.push(self.charAt(i))
2009
}
Sep 5, 2014
2010
}
Mar 19, 2018
2011
return res.join("")
Sep 5, 2014
2012
}
2013
2014
str.upper = function(self){
2015
var $ = $B.args("upper", 1, {self: null}, ["self"],
2016
arguments, {}, null, null)
2017
return self.toUpperCase()
2018
}
2019
Mar 19, 2018
2020
str.zfill = function(self, width){
Mar 19, 2018
2021
var $ = $B.args("zfill", 2, {self: null, width: null},
Mar 19, 2018
2022
["self", "width"], arguments, {}, null, null)
2023
if($.width <= self.length){return self}
Mar 19, 2018
2025
case "+":
2026
case "-":
2027
return self.charAt(0) +
2028
"0".repeat($.width - self.length) + self.substr(1)
Mar 19, 2018
2030
return "0".repeat(width - self.length) + self
Sep 5, 2014
2032
}
2033
2034
str.$factory = function(arg, encoding, errors){
2035
if(arguments.length == 0){return ""}
2036
if(arg === undefined){
2037
throw _b_.TypeError.$factory("str() argument is undefined")
2038
}
2039
switch(typeof arg) {
Mar 19, 2018
2040
case "string":
Mar 27, 2019
2041
return str.__str__(arg)
Mar 19, 2018
2042
case "number":
2043
if(isFinite(arg)){return arg.toString()}
2046
if(arg.$is_class || arg.$factory){
2047
// arg is a class
2048
// In this case, str() doesn't use the attribute __str__ of the
2049
// class or its subclasses, but the attribute __str__ of the
2050
// class metaclass (usually "type") or its subclasses (usually
2051
// "object")
2052
// The metaclass is the attribute __class__ of the class dictionary
Mar 19, 2018
2053
var func = $B.$getattr(arg.__class__, "__str__")
2055
}
2056
if(arg.__class__ && arg.__class__ === _b_.bytes &&
2057
encoding !== undefined){
2058
// str(bytes, encoding, errors) is equal to
2059
// bytes.decode(encoding, errors)
2060
// Arguments may be passed as keywords (cf. issue #1060)
2061
var $ = $B.args("str", 3, {arg: null, encoding: null, errors: null},
2062
["arg", "encoding", "errors"], arguments,
2063
{encoding: "utf-8", errors: "strict"}, null, null)
2064
return _b_.bytes.decode(arg, $.encoding, $.errors)
2066
var f = $B.$getattr(arg, "__str__", null)
2067
if(f === null ||
2068
// if not better than object.__str__, try __repr__
2069
(arg.__class__ && arg.__class__ !== _b_.object &&
2070
f.$infos && f.$infos.__func__ === _b_.object.__str__)){
2071
var f = $B.$getattr(arg, "__repr__")
2072
}
Sep 5, 2014
2073
}
2074
catch(err){
2075
console.log("no __str__ for", arg)
Mar 19, 2018
2076
console.log("err ", err)
2077
if($B.debug > 1){console.log(err)}
2078
console.log("Warning - no method __str__ or __repr__, " +
2079
"default to toString", arg)
May 20, 2019
2080
throw err
Sep 5, 2014
2081
}
Sep 5, 2014
2083
}
str
Feb 10, 2018
2084
2085
str.__new__ = function(cls){
Mar 19, 2018
2086
if(cls === undefined){
2087
throw _b_.TypeError.$factory("str.__new__(): not enough arguments")
Sep 5, 2014
2088
}
Mar 19, 2018
2089
return {__class__: cls}
Sep 5, 2014
2090
}
2091
str
Feb 10, 2018
2092
$B.set_func_names(str, "builtins")
Sep 5, 2014
2094
// dictionary and factory for subclasses of string
str
Feb 10, 2018
2095
var StringSubclass = $B.StringSubclass = {
Mar 19, 2018
2096
__class__: _b_.type,
str
Feb 10, 2018
2097
__mro__: [object],
2098
$infos: {
2099
__module__: "builtins",
2100
__name__: "str"
2101
},
str
Feb 10, 2018
2102
$is_class: true
Sep 5, 2014
2103
}
2104
str
Feb 10, 2018
2105
// the methods in subclass apply the methods in str to the
Sep 5, 2014
2106
// result of instance.valueOf(), which is a Javascript string
str
Feb 10, 2018
2107
for(var $attr in str){
Mar 19, 2018
2108
if(typeof str[$attr] == "function"){
Mar 19, 2018
2109
StringSubclass[$attr] = (function(attr){
Sep 5, 2014
2110
return function(){
Mar 19, 2018
2111
var args = [],
2112
pos = 0
2113
if(arguments.length > 0){
2114
var args = [arguments[0].valueOf()],
2115
pos = 1
2116
for(var i = 1, len = arguments.length; i < len; i++){
2117
args[pos++] = arguments[i]
Sep 5, 2014
2118
}
2119
}
Mar 19, 2018
2120
return str[attr].apply(null, args)
Sep 5, 2014
2121
}
2122
})($attr)
2123
}
2124
}
str
Feb 10, 2018
2125
StringSubclass.__new__ = function(cls){
Sep 5, 2014
2128
str
Feb 10, 2018
2129
$B.set_func_names(StringSubclass, "builtins")
Sep 5, 2014
2131
_b_.str = str
2132
2133
// Function to parse the 2nd argument of format()
2134
$B.parse_format_spec = function(spec){
Mar 19, 2018
2135
if(spec == ""){this.empty = true}
2136
else{
Mar 19, 2018
2137
var pos = 0,
2138
aligns = "<>=^",
2139
digits = "0123456789",
2140
types = "bcdeEfFgGnosxX%",
2141
align_pos = aligns.indexOf(spec.charAt(0))
Mar 19, 2018
2142
if(align_pos != -1){
2143
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1)) != -1){
2144
// If the second char is also an alignment specifier, the
2145
// first char is the fill value
2146
this.fill = spec.charAt(0)
2147
this.align = spec.charAt(1)
2148
pos = 2
2149
}else{
2150
// The first character defines alignment : fill defaults to ' '
Mar 19, 2018
2151
this.align = aligns[align_pos]
2152
this.fill = " "
2153
pos++
2154
}
2155
}else{
2156
align_pos = aligns.indexOf(spec.charAt(1))
Mar 19, 2018
2157
if(spec.charAt(1) && align_pos != -1){
2158
// The second character defines alignment : fill is the first one
Mar 19, 2018
2159
this.align = aligns[align_pos]
2160
this.fill = spec.charAt(0)
2161
pos = 2
2162
}
2163
}
2164
var car = spec.charAt(pos)
Mar 19, 2018
2165
if(car == "+" || car == "-" || car == " "){
2166
this.sign = car
2167
pos++
2168
car = spec.charAt(pos)
Mar 19, 2018
2170
if(car == "#"){this.alternate = true; pos++; car = spec.charAt(pos)}
2171
if(car == "0"){
Mar 19, 2018
2172
// sign-aware : equivalent to fill = 0 and align == "="
Mar 19, 2018
2173
this.fill = "0"
2174
if(align_pos == -1){
2175
this.align = "="
2176
}
Mar 19, 2018
2177
pos++
2178
car = spec.charAt(pos)
2179
}
Mar 19, 2018
2180
while(car && digits.indexOf(car) > -1){
2181
if(this.width === undefined){this.width = car}
2182
else{this.width += car}
2183
pos++
2184
car = spec.charAt(pos)
Mar 19, 2018
2186
if(this.width !== undefined){this.width = parseInt(this.width)}
2187
if(this.width === undefined && car == "{"){
2188
// Width is determined by a parameter
2189
var end_param_pos = spec.substr(pos).search("}")
2190
this.width = spec.substring(pos, end_param_pos)
2191
console.log("width", "[" + this.width + "]")
2192
pos += end_param_pos + 1
2193
}
Mar 19, 2018
2194
if(car == ","){this.comma = true; pos++; car = spec.charAt(pos)}
2195
if(car == "."){
2196
if(digits.indexOf(spec.charAt(pos + 1)) == -1){
2197
throw _b_.ValueError.$factory(
2198
"Missing precision in format spec")
Mar 19, 2018
2200
this.precision = spec.charAt(pos + 1)
2201
pos += 2
2202
car = spec.charAt(pos)
2203
while(car && digits.indexOf(car) > -1){
Mar 21, 2018
2204
this.precision += car
Mar 19, 2018
2205
pos++
2206
car = spec.charAt(pos)
2207
}
2208
this.precision = parseInt(this.precision)
2209
}
Mar 19, 2018
2210
if(car && types.indexOf(car) > -1){
2211
this.type = car
2212
pos++
2213
car = spec.charAt(pos)
2214
}
2215
if(pos !== spec.length){
2216
throw _b_.ValueError.$factory("Invalid format specifier: " + spec)
2220
this.toString = function(){
Mar 19, 2018
2221
return (this.fill === undefined ? "" : _b_.str.$factory(this.fill)) +
2222
(this.align || "") +
2223
(this.sign || "") +
2224
(this.alternate ? "#" : "") +
2225
(this.sign_aware ? "0" : "") +
2226
(this.width || "") +
2227
(this.comma ? "," : "") +
2228
(this.precision ? "." + this.precision : "") +
2229
(this.type || "")
2230
}
2231
}
2232
2233
$B.format_width = function(s, fmt){
Mar 19, 2018
2234
if(fmt.width && s.length < fmt.width){
2235
var fill = fmt.fill || " ",
2236
align = fmt.align || "<",
2237
missing = fmt.width - s.length
2238
switch(align){
Mar 19, 2018
2239
case "<":
2240
return s + fill.repeat(missing)
2241
case ">":
2242
return fill.repeat(missing) + s
2243
case "=":
2244
if("+-".indexOf(s.charAt(0)) > -1){
2245
return s.charAt(0) + fill.repeat(missing) + s.substr(1)
2246
}else{
Mar 19, 2018
2247
return fill.repeat(missing) + s
Mar 19, 2018
2249
case "^":
2250
var left = parseInt(missing / 2)
2251
return fill.repeat(left) + s + fill.repeat(missing - left)
2252
}
2253
}
2254
return s
2255
}
2256
2257
function fstring_expression(){
Mar 19, 2018
2258
this.type = "expression"
2259
this.expression = ""
2260
this.conversion = null
2261
this.fmt = null
2262
}
2263
2264
$B.parse_fstring = function(string){
2265
// Parse a f-string
2266
var elts = [],
2267
pos = 0,
Mar 19, 2018
2268
current = "",
2269
ctype = null,
2270
nb_braces = 0,
2271
car
2272
Mar 19, 2018
2273
while(pos < string.length){
2274
if(ctype === null){
2275
car = string.charAt(pos)
Mar 19, 2018
2276
if(car == "{"){
Mar 21, 2018
2277
if(string.charAt(pos + 1) == "{"){
Mar 19, 2018
2278
ctype = "string"
2279
current = "{"
2280
pos += 2
2281
}else{
Mar 19, 2018
2282
ctype = "expression"
2283
nb_braces = 1
2284
pos++
2285
}
Mar 19, 2018
2286
}else if(car == "}"){
Mar 21, 2018
2287
if(string.charAt(pos + 1) == car){
Mar 19, 2018
2288
ctype = "string"
2289
current = "}"
2290
pos += 2
2291
}else{
2292
throw Error(" f-string: single '}' is not allowed")
2293
}
2294
}else{
Mar 19, 2018
2295
ctype = "string"
2296
current = car
2297
pos++
Mar 19, 2018
2299
}else if(ctype == "string"){
2300
// end of string is the first single { or end of string
Mar 19, 2018
2301
var i = pos
2302
while(i < string.length){
2303
car = string.charAt(i)
Mar 19, 2018
2304
if(car == "{"){
Mar 21, 2018
2305
if(string.charAt(i + 1) == "{"){
Mar 19, 2018
2306
current += "{"
2307
i += 2
2308
}else{
2309
elts.push(current)
Mar 19, 2018
2310
ctype = "expression"
2311
pos = i + 1
2312
break
2313
}
Mar 19, 2018
2314
}else if(car == "}"){
2315
if(string.charAt(i + 1) == car){
2316
current += car
2317
i += 2
2318
}else{
2319
throw Error(" f-string: single '}' is not allowed")
2320
}
2321
}else{
2322
current += car
2323
i++
2324
}
2325
}
Mar 19, 2018
2326
pos = i + 1
2327
}else if(ctype == "debug"){
2328
// after the equal sign, whitespace are ignored and the only
2329
// valid characters are } and :
2330
while(string.charAt(i) == " "){i++}
2331
if(string.charAt(i) == "}"){
2332
// end of debug expression
2333
elts.push(current)
2334
ctype = null
2335
current = ""
2336
pos = i + 1
2337
}
2338
}else{
2339
// End of expression is the } matching the opening {
2340
// There may be nested braces
2341
var i = pos,
2342
nb_braces = 1,
2343
nb_paren = 0,
2344
current = new fstring_expression()
Mar 19, 2018
2345
while(i < string.length){
2346
car = string.charAt(i)
Mar 19, 2018
2347
if(car == "{" && nb_paren == 0){
2348
nb_braces++
2349
current.expression += car
2350
i++
Mar 19, 2018
2351
}else if(car == "}" && nb_paren == 0){
2352
nb_braces -= 1
Mar 19, 2018
2353
if(nb_braces == 0){
2354
// end of expression
2355
elts.push(current)
2356
ctype = null
Mar 19, 2018
2357
current = ""
2358
pos = i + 1
2361
current.expression += car
2362
i++
Mar 19, 2018
2363
}else if(car == "\\"){
2364
// backslash is not allowed in expressions
2365
throw Error("f-string expression part cannot include a" +
2366
" backslash")
Mar 19, 2018
2367
}else if(nb_paren == 0 && car == "!" && current.fmt === null &&
Mar 21, 2018
2368
":}".indexOf(string.charAt(i + 2)) > -1){
Mar 19, 2018
2369
if(current.expression.length == 0){
2370
throw Error("f-string: empty expression not allowed")
2371
}
Mar 19, 2018
2372
if("ars".indexOf(string.charAt(i + 1)) == -1){
2373
throw Error("f-string: invalid conversion character:" +
2374
" expected 's', 'r', or 'a'")
2375
}else{
Mar 19, 2018
2376
current.conversion = string.charAt(i + 1)
2377
i += 2
2378
}
Mar 19, 2018
2379
}else if(car == "("){
2380
nb_paren++
2381
current.expression += car
2382
i++
Mar 19, 2018
2383
}else if(car == ")"){
2384
nb_paren--
2385
current.expression += car
2386
i++
Mar 19, 2018
2387
}else if(car == '"'){
2388
// triple string ?
Mar 19, 2018
2389
if(string.substr(i, 3) == '"""'){
2390
var end = string.indexOf('"""', i + 3)
2391
if(end == -1){
2392
throw Error("f-string: unterminated string")
2393
}else{
2394
var trs = string.substring(i, end + 3)
2395
trs = trs.replace("\n", "\\n\\")
2396
current.expression += trs
Mar 19, 2018
2397
i = end + 3
2398
}
2399
}else{
Mar 19, 2018
2400
var end = string.indexOf('"', i + 1)
2401
if(end == -1){
2402
throw Error("f-string: unterminated string")
2403
}else{
2404
current.expression += string.substring(i, end + 1)
2405
i = end + 1
2406
}
2407
}
Mar 19, 2018
2408
}else if(nb_paren == 0 && car == ":"){
2409
current.fmt = true
2410
current.expression += car
2411
i++
2412
}else if(car == "="){
2413
// might be a "debug expression", eg f"{x=}"
2414
var ce = current.expression
2415
if(ce.length == 0 ||
2416
"=!<>:".search(ce.charAt(ce.length - 1)) > -1){
2417
current.expression += car
2418
i++
2419
}else{
2420
// add debug string
2421
tail = car
2422
while(string.charAt(i + 1).match(/\s/)){
2423
tail += string.charAt(i + 1)
2424
i++
2425
}
2426
elts.push(current.expression + tail)
2427
// remove trailing whitespace from expression
2428
while(ce.match(/\s$/)){
2429
ce = ce.substr(0, ce.length - 1)
2430
}
2431
current.expression = ce
2432
ctype = "debug"
2433
i++
2434
}
2435
}else{
2436
current.expression += car
2437
i++
2438
}
2439
}
Mar 21, 2018
2440
if(nb_braces > 0){
2441
throw Error("f-string: expected '}'")
2442
}
2443
}
2444
}
Mar 19, 2018
2445
if(current.length > 0){elts.push(current)}
2446
return elts
2447
}
2448
Sep 5, 2014
2449
})(__BRYTHON__)