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