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